+++ /dev/null
-MLT Demo Notes
-
-Before running the demo script, make sure you '. setenv' from the parent
-directory. Also, please create clips clip1.dv, clip2.dv, clip3.dv, clip1.mpeg,
-clip2.mpeg, clip3.mpeg, and music1.ogg. Please make sure clips are at least 500
-frames duration.
-
-These notes explain the the concepts presented in each demonstration and
-what details to look for.
-
-First, a note on consumers. When you start the script, the main menu asks
-you to choose a consumer. A consumer is like a viewer, but it could also
-write to a stream/file. The "SDL" consumer is the popular Simple DirectMedia
-Layer audio and video output. The "Westley" consumer generates an XML
-representation of the service network. That can be played directly due to the
-westley producer plugin. See docs/westley.txt for more information. The
-"MainConcept DV" consumer refers to the proprietary MLT plugin required to
-use MLT with MainConcept DV, DVCPro, and MPEG codecs. "/dev/dv1394/0" refers
-to a device file for transmitting DV over FireWire using the Linux dv1394 kernel
-module. The "BlueFish444" consumer is another proprietary plugin to use
-the BlueFish444 manufactured SDI video/audio output cards with MLT.
-
-And now the demos...
-
-All clips
-
- Simply builds a playlist containing each video clip, and you can transport
- between them using j and k keys.
-
-Filter in/out
-
- A video filter can be applied to a portion of a producer (clip, playlist,
- or multitrack). This examples shows the greyscale filter.
-
-Watermark
-
- A graphic can overlay video in realtime with support for alpha channel.
- This example uses a PNG file with an alpha channel. Distortion is explicitly
- enabled here so the otherwise circular graphic is scaled to fill the
- compositing region. By default, compositing honours the aspect ratio of the
- overlay.
-
-My name is...
-
- Titles are very easy to composite in realtime. The titler uses Pango
- with the FreeType2 rendering backend. This means it supports high
- quality scalable font rendering with anti-aliasing, unicode (UTF-8),
- and Pango markup capabilities. The compsiting here respects the aspect
- ratio of the rendered title in the first two title pieces but distorts
- the final one. This demo also shows the motion and scaling capabilities
- of the compositor in conjunction with honouring aspect. The compositor
- is doing field-based rendering. So, when displayed non-progressively
- with SDL, you can see motion artifacts during animation.
-
-A composite transition
-
- The compositor also handles video over video as demonstrated in this
- usage of the compositor to create a special transition. This demonstration
- also crossfades the audio during the transition! Progressive rendering
- is explicitly enabled on the compositor due to the poor results that
- would otherwise occur due to scaling an interleaved video frame and moving
- the video in a reverse direction horizontally.
-
-Fade in and out
-
- A simple series of transitions betwen 3 clips using dissolves and audio
- crossfades. This is easy :-).
-
-Clock in and out
-
- Wipe transitions are very easy and highly extensible as they are generated
- using a very convenient lookup table based upon the luma of an image.
- This image can be a 16 bit PGM (grayscale bitmap) or the luma channel of
- any video producer. A number of high quality wipes can be downloaded from
- http://mlt.sf.net/. It also performs field rendering.
- The second wipe demonstrates the ability to control the direction of the
- wipe as well.
-
-Obscure
-
- A popular requirement in news production is to obscure a face, obscenity,
- or trademarked logo. This demonstrates using a simple rectangular
- obscure filter applied to a region of the image. The second example is more
- advanced and shows using the "region" filter to select the image area and a
- property of the region filter to "shape" the region using the alpha channel
- of another image (circle.png) and another property to "filter" the region
- using the obscure filter.
-
-Audio Stuff
-
- A music bed sound track can be mixed with a video. The sound track of the
- video clip has a "floating" amplitude normalisation filter applied.
- Typically, audio normalisation applies a constant gain factor across the
- entire duration of an audio segment from a single source where the
- gain factor is automatically determined by anaylsing the maximum "power"
- or peak levels. However, in news production, a popular requirement is to
- to dynamically boost the amplitude in soft areas and reduce the amplitude
- in louder areas. Thus, the gain analysis is performed using a "sliding
- window" approach. This example also applies a constant gain factor of
- 0.5 (50%) to the normalised audio of the video clip (to get a nicer
- mix level).
-
-Audio and Video Levels
-
- Audio can be normalised by setting a target amplitude level in decibels.
- A gamma curve can be applied to the luma channel of video.
-
-Shadowed Title and Watermark
-
- Two instances of the titler are used to create a shadow effect.
- The aspect ratio of the watermark in this example is not distorted. Since
- the original image is a circle with square pixels--a computer-generated
- image--and ITU BT.601 video is not composed of square samples. Therefore,
- the compositor normalises the pixel aspect ratio of the overlay to the
- destination image, and the circular image remains circular on the analog
- video output. Finally, a greyscale filter is applied to the watermark
- while its opacity is set at 30%.
-
-Station Promo into Story?
-
- Here is fun demo that might show using a still graphic with some music
- to introduce a show. A luma wipe with an audio crossfade transitions from
- the show title or station promotional material.
-
-Voiceover 2 clips with title
-
- A common news production requirement to have a "voiceover" audio track
- to a clip or even multiple clips as demonstrated here. Likewise, it is
- common to place a title caption on the video at the same time! This
- demo has a little fun with the titler at the sake of practicality :-)
- The foreground of the title is transparent while the opacity of the
- background is reduced to blend with the video. Meanwhile, the compositor
- stretches the image to fill the bottom slice of the video--not suitable
- for overscan displays ;-)
-
- Also, pay close attention to the mixing levels of the audio tracks.
- The audio of the video fades out as the voiceover track (just music
- in this demo) fades in. Then, the voiceover remains mixed with the
- ambient audio at a 60% level. Finally, the voiceover fades out smoothly
- from the 60% level to nothing.
-
-GJ-TTAvantika title
-
- This demo requires a special TrueType font called Avantika. If you have the
- font, register it with fontconfig using the fc-cache utility. This
- demonstrates i18n capabilities of the titler and the alignment capabilities
- of both the titler and the compositor. The titler centre aligns
- the two lines of text, and the compositor centre aligns the title
- horizontally on the frame.
-
-Title over graphic
-
- You can superimpose a title over a graphic over video! Also,
- you can apply a luma wipe to the compositor!
-
-Slideshow
-
- This demo requires any number of JPEG images with the extension ".jpg"
- in a subdirectory named "Scotland."
-
-Bouncy, Bouncy
-
- The "watermark" filter encapsulates the compositor, and you have full
- control over the compositor properties. Who says a watermark can not
- also be a video?!
-
-Bouncy, Bouncy Ball
-
- A variation on the above Bouncy, Bouncy demo that applies a shape, or
- alpha producer, to the the compositing region.
-
-Breaking News
-
- This demonstrates layout capabilities of the compositor.
-
-Squeeze Transitions
-
- This demonstrates a distorting barndoor-like wipe.
-
-
-J Cut
-
- A J cut is an edit where the audio cuts before the video.
- It gets its name from the way it looks on a NLE timeline user interface.
- When the audio cuts over, it does an audio crossfade over the duration of
- one frame. This makes the audio cut slightly less abrupt and avoids any
- "click" due to mismatched sample levels at the edit point. The video edit
- is a hard cut.
-
-L Cut
-
- An L cut is an edit where the video cuts before the audio.
- It gets its name from the way it looks on a NLE timeline user interface.
- This demo shows a very quick dissolve over 5 frames for a soft video cut.
- Like the J Cut demo, an audio crossfade for the duration of one frame makes
- an audio edit nearly instantaneous while being slightly softened and
- avoiding aberrations.
-
-Fade from/to black/silence
-
- Of course, it is possible using MLT to fade from black on video and silence
- on audio as well fade to black and silence.
-
-Push wipe
-
- A push wipe is a somewhat fancier transition than most standard wipes
- because it involves motion. The new video clip "pushes" the old video
- clip off one edge. If you can preview on an analog monitor you will notice
- how smooth the motion is due to field-based rendering.
-
-Ticker tape
-
- A very minimal reverse crawling title neard the bottom of the screen.
- The goal of the demo is show fluid motion of the field-based rendering of
- the compositor when viewed on an analog monitor using a DV or BlueFish444
- consumer. The demo also shows the potientional for using and extending the
- existing set of services for a full blown news ticker implementation.
+++ /dev/null
-<svg width='300' height='300'><circle cx='150' cy='150' r='150' fill='white'/></svg>
+++ /dev/null
-SDL Default sdl
-SDL Half D1 sdl:360x288 rescale=nearest resize=1
-SDL High Latency sdl buffer=12 rescale=none
-SDL Progressive sdl progressive=1
-Westley to Terminal westley
-Westley to File westley:
-MainConcept DV to /dev/dv1394/0 mcdv:/dev/dv1394/0 rescale=nearest buffer=25
-libdv to /dev/dv1394/0 libdv:/dev/dv1394/0 rescale=nearest buffer=25
-BlueFish444 PAL bluefish:1
-BlueFish444 NTSC bluefish:1 standard=NTSC
-BlueFish444 PAL Prog LL bluefish:1 progressive=1 buffer=1 frames=4
-BlueFish444 NTSC Prog LL bluefish:1 standard=NTSC progressive=1 buffer=1 frames=4
+++ /dev/null
-#!/bin/bash
-
-function show_consumers( )
-{
- awk -F '\t' '{ printf( "%d. %s\n", ++ i, $1 ); }' < consumers.ini
-}
-
-function get_consumer( )
-{
- option=$1
- [ "$option" != "" ] && [ $option -gt 0 ] && sed 's/\t\+/\t/g' < consumers.ini | cut -f 2 | head -n $option | tail -n -1
-}
-
-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" ); } END { if ( i % 2 == 1 ) 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
-
- echo Select Consumer
- echo
-
- show_consumers
-
- echo
- echo 0. Exit
- echo
- echo -n "Option: "
- read option
- echo
-
- [ "$option" == "0" ] && break
-
- export MLT_CONSUMER=`get_consumer $option`
-
- while [ "$option" != "0" -a "$MLT_CONSUMER" != "" ]
- do
- echo Choose Demo
- echo
-
- show_menu
-
- echo
- echo -n "Option: "
- read option
- echo
-
- [ "$option" == "" ] && break
-
- 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=1 composite.geometry=85%,5%:10%x10%
- 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.mpeg
-mlt_obscure Obscure clip2.mpeg,circle.png
-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.mpeg,clip3.mpeg,circle.png
-mlt_news Breaking News clip1.dv,clip2.dv
-mlt_squeeze Squeeze Transitions clip1.dv,clip2.dv,clip3.dv
-mlt_squeeze_box Squeeze Box clip1.dv,clip2.dv,clip3.dv
-mlt_jcut J Cut clip1.dv,clip2.dv
-mlt_lcut L Cut clip1.dv,clip2.dv
-mlt_fade_black Fade from/to black/silence clip3.mpeg
-mlt_push Push wipe clip1.mpeg, clip2.mpeg
-mlt_ticker Ticker tape clip1.dv
-mlt_attributes Attributes clip1.dv
-mlt_slideshow_black Composite slideshow Scotland
+++ /dev/null
-<?xml version="1.0"?>
-<smil xmlns:smil2="http://www.w3.org/2001/SMIL20/Language">
- <seq title="MLT" copyright="2004" abstract="foo man choo">
- <video src="clip2.dv" clipBegin="171" clipEnd="450"/>
- </seq>
- <seq title="Demo">
- <video src="clip2.dv" clipBegin="0" clipEnd="170"/>
- </seq>
- <seq>
- <video src="clip1.dv" clipBegin="0" clipEnd="159"/>
- <video src="clip3.dv" clipBegin="0" clipEnd="106"/>
- </seq>
-</smil>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE westley SYSTEM "../src/modules/westley/westley.dtd" [
- <!ENTITY name "Westley">
-]>
-<westley>
- <producer id="producer0">
- <property name="mlt_service">pango</property>
- <property name="text">Hello &name;,
-My name is Inigo Montoya.</property>
- </producer>
-</westley>
+++ /dev/null
-inigo \
-clip* \
-$*
+++ /dev/null
-inigo clip1.dv \
-meta.attr.location=1 meta.attr.location.markup="Location" \
-meta.attr.exclusive=1 meta.attr.exclusive.markup="Exclusive" \
-meta.attr.special=1 meta.attr.special.markup="Special" \
-meta.attr.super=1 meta.attr.super.0="Line 1" meta.attr.super.1="Line 2" \
--filter data_show \
-$*
+++ /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:circle \
-composite.geometry="10%,10%:20%x20%;33=30%,70%:25%x25%;66=70%,30%:15%x15%;-1=70%,70%:20%x20%" \
-composite.out=100 \
-composite.softness=0.1 \
-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 clip3.mpeg in=100 out=249 \
--transition luma:luma1.pgm softness=0.5 in=50 out=74 a_track=0 b_track=1 \
--transition luma:luma1.pgm softness=0.2 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% progressive=1 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 \
-colour:black out=199 \
--track \
-clip3.mpeg in=100 out=299 \
--transition luma in=0 out=49 a_track=0 b_track=1 \
--transition luma in=150 out=199 a_track=0 b_track=1 reverse=1 \
--filter volume in=0 out=49 track=1 gain=0 end=1.0 \
--filter volume in=150 out=199 track=1 gain=1.0 end=0 \
-$*
+++ /dev/null
-inigo \
-clip1.dv out=74 -blank 99 clip3.dv in=25 \
--track \
--blank 49 clip2.mpeg out=149 \
--transition luma 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 \
-music1.ogg in=100 out=224 \
--track \
-watermark1.png out=124 \
-clip3.mpeg \
--mix 25 \
--mixer luma resource=luma1.pgm softness=0.2 \
--transition mix:-1 in=100 out=124 \
-$*
+++ /dev/null
-inigo \
--blank 49 \
-clip2.dv in=100 \
--track \
-clip1.dv out=99 \
--transition \
-mix start=0 end=1 in=49 out=50 a_track=1 b_track=0 \
--transition \
-mix:1 in=51 out=99 a_track=1 b_track=0 \
-$*
+++ /dev/null
-inigo \
-clip1.dv out=100 \
--track \
--blank 49 \
-clip2.dv in=100 \
--transition \
-luma in=50 out=55 a_track=0 b_track=1 \
--transition \
-mix:1 in=50 out=98 a_track=1 b_track=0 \
--transition \
-mix start=1 end=0 in=99 out=100 a_track=1 b_track=0 \
-$*
+++ /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" out=99 \
--track \
--blank 74 "+You killed my father.txt" out=74 \
--transition composite:50%,20%:5%x4% end=10%,20%:80%x12% distort=1 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 \
-colour:black out=199 \
--track \
-clip1.dv in=0 out=0 -repeat 99 clip1.dv \
--track \
-clip2.dv out=199 \
--track \
-pango: text=" Breaking News
- MLT Rocks India" bgcolour=0xff000080 out=149 \
-pango: text=" Breaking News
- MLT Rocks the World" bgcolour=0xff000080 out=349 \
--transition mix:0.5 always_active=1 a_track=0 b_track=2 \
--transition composite geometry=50%,15%:37.5%x40% a_track=0 b_track=1 in=0 out=174 \
--transition composite geometry=10%,15%:37.5%x40% a_track=0 b_track=2 in=0 out=199 \
--transition composite geometry="50%,15%:37.5%x40%;-1=0%,0%:100%x100%" a_track=0 b_track=1 in=175 out=199 distort=1 \
--transition composite geometry=10%,65%:90%x20% a_track=0 b_track=3 in=0 out=199 \
--transition composite geometry=10%,65%:90%x20% a_track=1 b_track=3 in=200 out=499 \
-$*
+++ /dev/null
-inigo \
-clip2.mpeg \
--filter obscure:25%,25%:25%x25%:10x10 in=0 out=68 \
--filter region:circle.png filter=obscure composite.start=55%,25%:12%x50% in=68 out=200 \
-$*
+++ /dev/null
-inigo \
--blank 49 colour:black out=25 -blank 999 \
--track \
-clip3.dv in=200 out=275 \
--track \
--blank 49 \
-clip2.dv in=200 \
--transition \
-composite in=50 out=75 a_track=0 b_track=1 \
-start=0,0:100%x100%:100 \
-end=100%,0:100%x100%:100 \
--transition \
-composite in=50 out=75 a_track=0 b_track=2 \
-start=-100%,0:100%x100%:100 \
-end=0,0:100%x100%:100 \
--transition \
-mix:-1 in=50 out=75 a_track=1 b_track=2 \
-$*
+++ /dev/null
-inigo \
-Scotland/.all.jpg ttl=75 \
--filter luma:luma1.pgm luma.softness=0.1 luma.invert=0 \
-$*
+++ /dev/null
-inigo Scotland/.all.jpg ttl=100 \
--filter watermark:colour:black reverse=1 composite.geometry="15%,15%:10%,10%;0.1625=0,0:100%x100%;-.1625=;-1=70%,70%:10%x10%" composite.mirror_off=1 composite.cycle=100 composite.fill=1 composite.valign=c composite.halign=c \
-$*
+++ /dev/null
-inigo \
-clip1.dv out=124 clip2.dv out=149 clip3.dv in=75 out=224 clip1.dv \
--track \
--blank 99 colour:black out=49 -blank 99 colour:black out=49 -blank 99 colour:black out=49 \
--group progressive=1 distort=1 \
--transition composite geometry="0%,0%:100%x100%;25=50%,0%:5%x100%;-1=0%,0%:100%x100%" a_track=1 b_track=0 in=100 out=149 \
--transition composite geometry="0%,0%:100%x100%;25=0%,50%:100%x5%;-1=0%,0%:100%x100%" a_track=1 b_track=0 in=250 out=299 \
--transition composite geometry="0%,0%:100%x100%;25=100%,0%:5%x100%;-1=0%,0%:100%x100%" a_track=1 b_track=0 in=400 out=449 \
-$*
+++ /dev/null
-inigo \
-clip1.dv out=124 clip2.dv out=149 clip3.dv in=75 out=224 clip1.dv \
--track \
--blank 99 colour:black out=49 -blank 99 colour:black out=49 -blank 99 colour:black out=49 \
--group progressive=1 \
--transition composite:0%,0%:100%x100% key[25]=50%,0%:5%x100% end=0%,0%:100%x100% a_track=1 b_track=0 in=100 out=149 \
--transition composite:0%,0%:100%x100% key[25]=0%,50%:100%x5% end=0%,0%:100%x100% a_track=1 b_track=0 in=250 out=299 \
--transition composite:0%,0%:100%x100% key[25]=100%,0%:5%x100% end=0%,0%:100%x100% a_track=1 b_track=0 in=400 out=449 \
-$*
+++ /dev/null
-inigo \
-clip1.dv out=299 \
--track \
-colour:black out=299 \
--track \
-"+The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog..txt" \
-out=299 \
--transition \
-composite a_track=0 b_track=1 out=299 distort=1 \
-start=0,70%:100%x64:100 \
--transition \
-composite a_track=0 b_track=2 out=299 titles=1 \
-start=100%,70%:999%x20% \
-end=-299%,70%:999%x20% \
-$*
+++ /dev/null
-inigo \
- watermark1.png out=9999 \
--track \
- "+title over gfx.txt" fgcolour=0x000000ff \
--track \
- clip1.dv \
--transition \
- composite start=30%,20%:40%x60% \
- in=50 \
- out=199 \
- a_track=0 \
- b_track=1 \
- distort=1 \
--transition \
- composite:0%,75%:100%x20%:0 \
- in=50 \
- out=199 \
- a_track=2 \
- b_track=0 \
- key[24]=0%,75%:100%x20%:100 \
- key[-25]=0%,75%:100%x20%:100 \
- luma=luma1.pgm \
- end=0%,75%:100%x20%:0 \
- distort=1 \
-$*
+++ /dev/null
-inigo \
-"+hello~world.txt" align=1 out=1000 \
--track "+hello~world.txt" align=1 out=1000 fgcolour=0x000000ff \
--track watermark1.png out=1000 \
--track clip3.dv \
--filter greyscale track=2 \
--transition composite:21%,11%:100%x100%:50 end=61%,41%:100%x100% out=99 a_track=3 b_track=1 \
--transition composite:20%,10%:100%x100% end=60%,40%:100%x100% out=99 a_track=3 b_track=0 \
--transition composite:85%,80%:10%x10%:30 out=1000 a_track=3 b_track=2 \
-$*
+++ /dev/null
-inigo \
-"+voice over demo.txt" \
- font="Sans Bold 72" \
- fgcolour=0x00000000 \
- bgcolour=0xff9933aa \
- pad=10 \
--track music1.ogg \
--track clip1.dv out=149 clip2.mpeg \
--transition \
- mix:0.0 \
- end=0.6 \
- in=75 \
- out=99 \
- a_track=2 \
- b_track=1 \
--transition \
- mix:0.6 \
- in=100 \
- out=299 \
- a_track=2 \
- b_track=1 \
--transition \
- mix:0.6 \
- end=0.0 \
- in=300 \
- out=324 \
- a_track=2 \
- b_track=1 \
--transition \
- composite:0%,80%:100%x20% \
- distort=1 \
- in=100 \
- out=299 \
- a_track=2 \
- b_track=0 \
-$*
+++ /dev/null
-inigo \
-clip2.dv out=1000 \
--track \
-watermark1.png out=1000 \
--transition composite fill=1 in=0 out=1000 a_track=0 b_track=1 geometry=85%,5%:10%x10% \
-$*
+++ /dev/null
-<playlist>
- <entry>
- <multitrack>
- <playlist>
- <producer id="foo" in="100" out="149">
- <property name="resource">clip2.mpeg</property>
- </producer>
- <blank length="25"/>
- <entry producer="foo" in="10" out="59"/>
- </playlist>
- <playlist>
- <blank length="25"/>
- <producer id="bar" in="100" out="149">
- <property name="resource">clip3.mpeg</property>
- </producer>
- <entry out="99" producer="bar"/>
- </playlist>
- </multitrack>
- <filter track="0">
- <property name="mlt_service">greyscale</property>
- </filter>
- <transition in="25" out="49" a_track="0" b_track="1">
- <property name="mlt_service">luma</property>
- </transition>
- <transition in="75" out="99" a_track="0" b_track="1" mlt_service="luma">
- <property name="reverse" value="1"/>
- </transition>
- </entry>
-
- <entry>
- <multitrack>
- <playlist>
- <entry producer="foo" in="100" out="149"/>
- <blank length="25"/>
- <entry producer="foo" in="10" out="59"/>
- </playlist>
- <playlist>
- <blank length="25"/>
- <entry producer="bar" in="100" out="149"/>
- <entry out="99" producer="bar"/>
- </playlist>
- </multitrack>
- <transition in="25" out="49" a_track="0" b_track="1">
- <property name="mlt_service">luma</property>
- </transition>
- <transition in="75" out="99" a_track="0" b_track="1" mlt_service="luma">
- <property name="reverse">1</property>
- </transition>
- </entry>
-
-</playlist>
+++ /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="title"/>
- <track producer="video"/>
- </multitrack>
- <transition in="0" out="150">
- <property name="mlt_service">composite</property>
- <property name="a_track">1</property>
- <property name="b_track">0</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>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000303 Stylable//EN" "http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd" [
- <!ENTITY st0 "fill-rule:evenodd;clip-rule:evenodd;fill:url(#aigrd1);stroke:none;">
- <!ENTITY st1 "stroke-width:0.8755;">
- <!ENTITY st2 "fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;stroke:none;">
- <!ENTITY st3 "fill:none;stroke:none;">
- <!ENTITY st4 "fill-rule:evenodd;clip-rule:evenodd;fill:url(#aigrd2);stroke:none;">
- <!ENTITY st5 "fill-rule:evenodd;clip-rule:evenodd;stroke:none;">
- <!ENTITY st6 "fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
-]>
-<westley>
-<playlist>
- <entry>
- <producer out="99" length="99">
- <property name="mlt_service">pixbuf</property>
- <property name="resource">
-
-<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
-<svg width="24pt" height="24pt" viewBox="0 0 24 24" xml:space="preserve">
- <g id="Layer_x0020_2" style="&st6;">
- <path style="&st1;" d="M1,12.1c0,6.1,5,11.1,11.1,11.1c6.1,0,11.1-5,11.1-11.1c0-6.1-5-11.1-11.1-11.1C5.9,1.1,1,6,1,12.1z"/>
- <radialGradient id="aigrd1" cx="8.7681" cy="8.0513" r="13.7645" fx="8.7681" fy="8.0513" gradientUnits="userSpaceOnUse">
- <stop offset="0" style="stop-color:#FED182"/>
- <stop offset="0.2809" style="stop-color:#FFB310"/>
- <stop offset="1" style="stop-color:#996E04"/>
- </radialGradient>
- <path style="&st0;" d="M21.3,12c0,5.2-4.2,9.4-9.4,9.4c-5.2,0-9.4-4.2-9.4-9.4c0-5.2,4.2-9.4,9.4-9.4c5.2,0,9.4,4.2,9.4,9.4z"/>
- </g>
- <g id="Layer_x0020_3" style="&st6;">
- <path style="&st5;" d="M16.4,7.2c-0.5,0.1-0.9,0.3-1.2,0.7c0,0-3,4.2-4.1,5.6c-0.9-0.9-2.5-2.5-2.5-2.5c-0.3-0.3-0.8-0.5-1.3-0.5c-0.5,0-0.9,0.2-1.3,0.5c-0.7,0.7-0.7,1.8,0,2.5l3.9,3.9c0.4,0.4,0.9,0.5,1.4,0.5c0.5,0,1-0.3,1.3-0.7l5.4-7.1
- c0.6-0.8,0.5-1.9-0.3-2.5c-0.4-0.3-0.8-0.4-1.3-0.4z"/>
- <path style="&st2;" d="M16.6,7.4c-0.5,0.1-0.9,0.3-1.2,0.7c0,0-3,4.2-4.1,5.6c-0.9-0.9-2.5-2.5-2.5-2.5c-0.3-0.3-0.8-0.5-1.3-0.5c-0.5,0-0.9,0.2-1.3,0.5c-0.7,0.7-0.7,1.8,0,2.5l3.9,3.9c0.4,0.4,0.9,0.5,1.4,0.5c0.5,0,1-0.3,1.3-0.7l5.4-7.1
- c0.6-0.8,0.5-1.9-0.3-2.5c-0.4-0.3-0.8-0.4-1.3-0.4z"/>
- <radialGradient id="aigrd2" cx="8.6733" cy="8.6187" r="11.0872" fx="8.6733" fy="8.6187" gradientUnits="userSpaceOnUse">
- <stop offset="0" style="stop-color:#FFFFFF"/>
- <stop offset="1" style="stop-color:#F0E1BD"/>
- </radialGradient>
- <path style="&st4;" d="M16.5,7.3c-0.5,0.1-0.9,0.3-1.2,0.7c0,0-3,4.2-4.1,5.6C10.3,12.6,8.6,11,8.6,11c-0.3-0.3-0.8-0.5-1.3-0.5c-0.5,0-0.9,0.2-1.3,0.5c-0.7,0.7-0.7,1.8,0,2.5l3.9,3.9c0.4,0.4,0.9,0.5,1.4,0.5c0.5,0,1-0.3,1.3-0.7l5.4-7.1
- c0.6-0.8,0.5-1.9-0.3-2.5c-0.4-0.3-0.8-0.4-1.3-0.4z"/>
- </g>
- <g id="Layer_x0020_4" style="&st6;">
- <path style="&st3;" d="M24,24H0V0h24v24z"/>
- </g>
-</svg>
-
- </property>
- </producer>
- </entry>
-</playlist>
-</westley>
+++ /dev/null
-Framework Documentation
-
-Copyright (C) 2004 Ushodaya Enterprises Limited
-Author: Charles Yates <charles.yates@pandora.be>
-Last Revision: 2004-10-08
-
-
-MLT FRAMEWORK
--------------
-
-Preamble:
-
- MLT is a multimedia framework designed for television broadcasting. As such,
- it provides a pluggable architecture for the inclusion of new audio/video
- sources, filters, transitions and playback devices.
-
- The framework provides the structure and utility functionality on which
- all of the MLT applications and services are defined.
-
- On its own, the framework provides little more than 'abstract classes' and
- utilities for managing resources, such as memory, properties, dynamic object
- loading and service instantiation.
-
- 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 structure and design, with an emphasis on how the system is
- extended.
-
-
-Target Audience:
-
- This document is provided as a 'road map' for the framework and should be
- considered mandatory reading for anyone wishing to develop code at the MLT
- level.
-
- This includes:
-
- 1. framework maintainers;
- 2. module developers;
- 3. application developers;
- 4. anyone interested in MLT.
-
- The emphasis of the document is in explaining the public interfaces, as
- opposed to the implementation details.
-
- It is not required reading for the MLT client/server integration - please
- refer to valerie.txt and dvcp.txt for more details on this area.
-
-
-SECTION 1 - BASIC OVERVIEW
---------------------------
-
-Basic Design Information:
-
- MLT is written in C.
-
- The framework has no dependencies other than the standard C99 and POSIX
- libraries.
-
- It follows a basic Object Oriented design paradigm, and as such, much of the
- design is loosely based on the Producer/Consumer design pattern.
-
- It employs Reverse Polish Notation for the application of audio and video FX.
-
- The framework is designed to be colour space neutral - the currently
- implemented modules, however, are very much 8bit YUV422 oriented. In theory,
- the modules could be entirely replaced.
-
- A vague understanding of these terms is assumed throughout the remainder of
- this document.
-
-
-Structure and Flow:
-
- The general structure of an MLT 'network' is simply the connection of a
- 'producer' to a 'consumer':
-
- +--------+ +--------+
- |Producer|-->|Consumer|
- +--------+ +--------+
-
- A typical consumer requests MLT Frame objects from the producer, does
- something with them and when finished with a frame, closes it.
-
- /\ A common confusion with the producer/consumer terminology used here is
- /!!\ that a consumer may 'produce' something. For example, the libdv consumer
- \!!/ produces DV and the libdv producer seems to consume DV. However, the
- \/ naming conventions refer only to producers and consumers of MLT Frames.
-
- To put it another way - a producer produces MLT Frame objects and a consumer
- consumes MLT Frame objects.
-
- An MLT Frame essentially provides an uncompressed image and its associated
- audio samples.
-
- Filters may also be placed between the producer and the consumer:
-
- +--------+ +------+ +--------+
- |Producer|-->|Filter|-->|Consumer|
- +--------+ +------+ +--------+
-
- A service is the collective name for producers, filters, transitions and
- consumers.
-
- The communications between a connected consumer and producer or service are
- carried out in 3 phases:
-
- * get the frame
- * get the image
- * get the audio
-
- MLT employs 'lazy evaluation' - the image and audio need not be extracted
- from the source until the get image and audio methods are invoked.
-
- In essence, the consumer pulls from what it's connected to - this means that
- threading is typically in the domain of the consumer implementation and some
- basic functionality is provided on the consumer class to ensure realtime
- throughput.
-
-
-SECTION 2 - USAGE
------------------
-
-Hello World:
-
- Before we go in to the specifics of the framework architecture, a working
- example of usage is provided.
-
- The following simply provides a media player:
-
- #include <stdio.h>
- #include <unistd.h>
- #include <framework/mlt.h>
-
- int main( int argc, char *argv[] )
- {
- // Initialise the factory
- if ( mlt_factory_init( NULL ) == 0 )
- {
- // Create the default consumer
- mlt_consumer hello = mlt_factory_consumer( NULL, NULL );
-
- // Create via the default producer
- mlt_producer world = mlt_factory_producer( NULL, argv[ 1 ] );
-
- // Connect the producer to the consumer
- mlt_consumer_connect( hello, mlt_producer_service( world ) );
-
- // Start the consumer
- mlt_consumer_start( hello );
-
- // Wait for the consumer to terminate
- while( !mlt_consumer_is_stopped( hello ) )
- sleep( 1 );
-
- // Close the consumer
- mlt_consumer_close( hello );
-
- // Close the producer
- mlt_producer_close( world );
-
- // Close the factory
- mlt_factory_close( );
- }
- else
- {
- // Report an error during initialisation
- fprintf( stderr, "Unable to locate factory modules\n" );
- }
-
- // End of program
- return 0;
- }
-
- This is a simple example - it doesn't provide any seeking capabilities or
- runtime configuration options.
-
- The first step of any MLT application is the factory initialisation - this
- ensures that the environment is configured and MLT can function. The factory
- is covered in more detail below.
-
- All services are instantiated via the factories, as shown by the
- mlt_factory_consumer and mlt_factory_producer calls above. There are similar
- factories for filters and transitions. There are details on all the standard
- services in services.txt.
-
- The defaults requested here are a special case - the NULL usage requests
- that we use the default producers and consumers.
-
- The default producer is "fezzik". This producer matches file names to
- locate a service to use and attaches 'normalising filters' (such as scalers,
- deinterlacers, resamplers and field normalisers) to the loaded content -
- these filters ensure that the consumer gets what it asks for.
-
- The default consumer is "sdl". The combination of fezzik and sdl will
- provide a media player.
-
- In this example, we connect the producer and then start the consumer. We
- then wait until the consumer is stopped (in this case, by the action of the
- user closing the SDL window) and finally close the consumer, producer and
- factory before exiting the application.
-
- Note that the consumer is threaded - waiting for an event of some sort is
- always required after starting and before stopping or closing the consumer.
-
- Also note, you can override the defaults as follows:
-
- $ MLT_CONSUMER=westley ./hello file.avi
-
- This will create a westley xml document on stdout.
-
- $ MLT_CONSUMER=westley MLT_PRODUCER=avformat ./hello file.avi
-
- This will play the video using the avformat producer directly, thus it will
- bypass the normalising functions.
-
- $ MLT_CONSUMER=libdv ./hello file.avi > /dev/dv1394
-
- This might, if you're lucky, do on the fly, realtime conversions of file.avi
- to DV and broadcast it to your DV device.
-
-
-Factories:
-
- As shown in the 'Hello World' example, factories create service objects.
-
- The framework itself provides no services - they are provided in the form of
- a plugin structure. A plugin is organised in the form of a 'module' and a
- module can provide many services of different types.
-
- Once the factory is initialised, all the configured services are available
- for use.
-
- The complete set of methods associated to the factory are as follows:
-
- int mlt_factory_init( char *prefix );
- const char *mlt_factory_prefix( );
- char *mlt_environment( char *name );
- mlt_producer mlt_factory_producer( char *name, void *input );
- mlt_filter mlt_factory_filter( char *name, void *input );
- mlt_transition mlt_factory_transition( char *name, void *input );
- mlt_consumer mlt_factory_consumer( char *name, void *input );
- void mlt_factory_close( );
-
- The mlt_factory_prefix returns the path to the location of the installed
- modules directory. This can be specified in the mlt_factory_init call
- itself, or it can be specified via the MLT_REPOSITORY environment variable,
- or in the absence of either of those, it will default to the install
- prefix/shared/mlt/modules.
-
- The mlt_environment provides read only access to a collection of name=value
- pairs as shown in the following table:
-
- +------------------+------------------------------------+------------------+
- |Name |Description |Values |
- +------------------+------------------------------------+------------------+
- |MLT_NORMALISATION |The normalisation of the system |PAL or NTSC |
- +------------------+------------------------------------+------------------+
- |MLT_PRODUCER |The default producer |"fezzik" or other |
- +------------------+------------------------------------+------------------+
- |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.
-
- As shown above, a producer can be created using the 'default normalising'
- producer, and they can also be requested by name. Filters and transitions
- are always requested by name - there is no concept of a 'default' for these.
-
-
-Service Properties:
-
- As shown in the services.txt document, all services have their own set of
- properties than can be manipulated to affect their behaviour.
-
- In order to set properties on a service, we need to retrieve the properties
- object associated to it. For producers, this is done by invoking:
-
- mlt_properties properties = mlt_producer_properties( producer );
-
- All services have a similar method associated to them.
-
- Once retrieved, setting and getting properties can be done directly on this
- object, for example:
-
- mlt_properties_set( properties, "name", "value" );
-
- A more complete description of the properties object is found below.
-
-
-Playlists:
-
- So far, we've shown a simple producer/consumer configuration - the next
- phase is to organise producers in playlists.
-
- Let's assume that we're adapting the Hello World example, and wish to queue
- a number of files for playout, ie:
-
- hello *.avi
-
- 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 and appending to the playlist.
-
- mlt_producer create_playlist( int argc, char **argv )
- {
- // We're creating a playlist here
- mlt_playlist playlist = mlt_playlist_init( );
-
- // We need the playlist properties to ensure clean up
- mlt_properties properties = mlt_playlist_properties( playlist );
-
- // Loop through each of the arguments
- int i = 0;
- for ( i = 1; i < argc; i ++ )
- {
- // Create the producer
- mlt_producer producer = mlt_factory_producer( NULL, argv[ i ] );
-
- // Add it to the playlist
- mlt_playlist_append( playlist, producer );
-
- // 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
- mlt_producer world = mlt_factory_producer( NULL, argv[ 1 ] );
-
- with:
-
- // Create a playlist
- mlt_producer world = create_playlist( argc, argv );
-
- 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:
-
- Inserting filters between the producer and consumer is just a case of
- instantiating the filters, connecting the first to the producer, the next
- to the previous filter and the last filter to the consumer.
-
- For example:
-
- // Create a producer from something
- mlt_producer producer = mlt_factory_producer( ... );
-
- // Create a consumer from something
- mlt_consumer consumer = mlt_factory_consumer( ... );
-
- // Create a greyscale filter
- mlt_filter filter = mlt_factory_filter( "greyscale", NULL );
-
- // Connect the filter to the producer
- mlt_filter_connect( filter, mlt_producer_service( producer ), 0 );
-
- // Connect the consumer to filter
- mlt_consumer_connect( consumer, mlt_filter_service( filter ) );
-
- As with producers and consumers, filters can be manipulated via their
- properties object - the mlt_filter_properties method can be invoked and
- properties can be set as needed.
-
- The additional argument in the filter connection is an important one as it
- dictates the 'track' on which the filter operates. For basic producers and
- playlists, there's only one track (0), and as you will see in the next
- 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:
-
- 1) The need for a consumer and producer to communicate with one another via
- a single frame;
- 2) The desire to be able to serialise and manipulate a 'network' (or filter
- graph if you prefer).
-
- We can visualise a multitrack in the way that an NLE presents it:
-
- +-----------------+ +-----------------------+
- 0: |a1 | |a2 |
- +---------------+-+--------------------------+-+---------------------+
- 1: |b1 |
- +------------------------------+
-
- The overlapping areas of track 0 and 1 would (presumably) have some kind of
- transition - without a transition, the frames from b1 and b2 would be shown
- during the areas of overlap (ie: by default, the higher numbered track takes
- precedence over the lower numbered track).
-
- MLT has a multitrack object, but it is not a producer in the sense that it
- can be connected directly to a consumer and everything will work correctly.
- A consumer would treat it precisely as it would a normal producer, and, in
- the case of the multitrack above, you would never see anything from track 1
- other than the transitions between the clips - the gap between a1 and a2
- would show test frames.
-
- This happens because a consumer pulls one frame from the producer it's
- connected to while a multitrack will provide one frame per track.
- Something, somewhere, must ensure that all frames are pulled from the
- multitrack and elect the correct frame to pass on.
-
- Hence, MLT provides a wrapper for the multitrack, which is called a
- 'tractor', and its the tractors task to ensure that all tracks are pulled
- evenly, the correct frame is output and that we have 'producer like'
- behaviour.
-
- Thus, a multitrack is conceptually 'pulled' by a tractor as shown here:
-
- +----------+
- |multitrack|
- | +------+ | +-------+
- | |track0|-|--->|tractor|
- | +------+ | |\ |
- | | | \ |
- | +------+ | | \ |
- | |track1|-|--->|---o---|--->
- | +------+ | | / |
- | | | / |
- | +------+ | |/ |
- | |track2|-|--->| |
- | +------+ | +-------+
- +----------+
-
- With a combination of the two, we can now connect multitracks to consumers.
- The last non-test card will be retrieved and passed on.
-
- The tracks can be producers, playlists, or even other tractors.
-
- Now we wish to insert filters and transitions between the multitrack and the
- tractor. We can do this directly by inserting filters directly between the
- tractor and the multitrack, but this involves a lot of connecting and
- reconnecting left and right producers and consumers, and it seemed only fair
- that we should be able to automate that process.
-
- So in keeping with our agricultural theme, the concept of the 'field' was
- born. We 'plant' filters and transitions in the field and the tractor pulls
- the multitrack (think of a combine harvester :-)) over the field and
- produces a 'bail' (sorry - kidding - frame :-)).
-
- Conceptually, we can see it like this:
-
- +----------+
- |multitrack|
- | +------+ | +-------------+ +-------+
- | |track0|-|--->|field |--->|tractor|
- | +------+ | | | |\ |
- | | | filters | | \ |
- | +------+ | | and | | \ |
- | |track1|-|--->| transitions |--->|---o---|--->
- | +------+ | | | | / |
- | | | | | / |
- | +------+ | | | |/ |
- | |track2|-|--->| |--->| |
- | +------+ | +-------------+ +-------+
- +----------+
-
- 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 +--------------------------+ |
- | +----------+ | +-+ +-+ +-+ +-+ | |
- | |multitrack| | |f| |f| |t| |t| | |
- | | +------+ | | |i| |i| |r| |r| | |
- | | |track0|-|--->| |l|- ->|l|- ->|a|--->|a|\| |
- | | +------+ | | |t| |t| |n| |n| | |
- | | | | |e| |e| |s| |s| |\ |
- | | +------+ | | |r| |r| |i| |i| | \|
- | | |track1|-|- ->| |0|--->|1|--->|t|--->|t|-|--o--->
- | | +------+ | | | | | | |i| |i| | /|
- | | | | | | | | |o| |o| |/ |
- | | +------+ | | | | | | |n| |n| | |
- | | |track2|-|- ->| | |- ->| |--->|0|- ->|1|/| |
- | | +------+ | | | | | | | | | | | |
- | +----------+ | +-+ +-+ +-+ +-+ | |
- | +--------------------------+ |
- +-----------------------------------------------+
-
- An example will hopefully clarify this.
-
- Let's assume that we want to provide a 'watermark' to our hello world
- example. We have already extended the example to play multiple clips,
- and now we will place a text based watermark, reading 'Hello World' in
- the top left hand corner:
-
- mlt_producer create_tracks( int argc, char **argv )
- {
- // 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_tractor_multitrack( tractor );
-
- // Create a composite transition
- mlt_transition transition = mlt_factory_transition( "composite", "10%,10%:15%x15%" );
-
- // Create track 0
- mlt_producer track0 = create_playlist( argc, argv );
-
- // Create the watermark track - note we NEED fezzik for scaling here
- mlt_producer track1 = mlt_factory_producer( "fezzik", "pango" );
-
- // Get the length of track0
- mlt_position length = mlt_producer_get_playtime( track0 );
-
- // Set the properties of track1
- mlt_properties properties = mlt_producer_properties( track1 );
- mlt_properties_set( properties, "text", "Hello\nWorld" );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", length - 1 );
- mlt_properties_set_position( properties, "length", length );
- mlt_properties_set_int( properties, "a_track", 0 );
- mlt_properties_set_int( properties, "b_track", 1 );
-
- // Now set the properties on the transition
- properties = mlt_transition_properties( transition );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", length - 1 );
-
- // Add our tracks to the multitrack
- mlt_multitrack_connect( multitrack, track0, 0 );
- mlt_multitrack_connect( multitrack, track1, 1 );
-
- // 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 );
-
- // Return the tractor
- return mlt_tractor_producer( tractor );
- }
-
- Now all we need do is to replace these lines in the main function:
-
- // Create a playlist
- mlt_producer world = create_playlist( argc, argv );
-
- with:
-
- // Create a watermarked playlist
- mlt_producer world = create_tracks( argc, argv );
-
- 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
---------------------------------
-
-Class Hierarchy:
-
- The mlt framework consists of an OO class hierarchy which consists of the
- following public classes and abstractions:
-
- mlt_properties
- mlt_frame
- mlt_service
- mlt_producer
- mlt_playlist
- mlt_tractor
- mlt_filter
- mlt_transition
- mlt_consumer
- mlt_deque
- mlt_pool
- mlt_factory
-
- Each class defined above can be read as extending the classes above and to
- the left.
-
- The following sections describe the properties, stacking/queuing and memory
- pooling functionality provided by the framework - these are key components
- and a basic understanding of these is required for the remainder of the
- documentation.
-
-
-mlt_properties:
-
- The properties class is the base class for the frame and service classes.
-
- It is designed to provide an efficient lookup table for various types of
- information, such as strings, integers, floating points values and pointers
- to data and data structures.
-
- All properties are indexed by a unique string.
-
- The most basic use of properties is as follows:
-
- // 1. Create a new, empty properties set;
- mlt_properties properties = mlt_properties_new( );
-
- // 2. Assign the value "world" to the property "hello";
- mlt_properties_set( properties, "hello", "world" );
-
- // 3. Retrieve and print the value of "hello";
- printf( "%s\n", mlt_properties_get( properties, "hello" ) );
-
- // 4. Reassign "hello" to "world!";
- mlt_properties_set( properties, "hello", "world!" );
-
- // 5. Retrieve and print the value of "hello";
- printf( "%s\n", mlt_properties_get( properties, "hello" ) );
-
- // 6. Assign the value "0" to "int";
- mlt_properties_set( properties, "int", "0" );
-
- // 7. Retrieve and print the integer value of "int";
- printf( "%d\n", mlt_properties_get_int( properties, "int" ) );
-
- // 8. Assign the integer value 50 to "int2";
- mlt_properties_set_int( properties, "int2", 50 );
-
- // 9. Retrieve and print the double value of "int2";
- printf( "%s\n", mlt_properties_get( properties, "int2" ) );
-
- Steps 2 through 5 demonstrate that the "name" is unique - set operations on
- an existing "name" change the value. They also free up memory associated to
- the previous value. Note that it also possible to change type in this way
- too.
-
- Steps 6 and 7 demonstrate that the properties object handles deserialisation
- from strings. The string value of "0" is set, the integer value of 0 is
- retrieved.
-
- Steps 8 and 9 demonstrate that the properties object handles serialisation
- to strings.
-
- To show all the name/value pairs in a properties, it is possible to iterate
- through them:
-
- for ( i = 0; i < mlt_properties_count( properties ); i ++ )
- printf( "%s = %s\n", mlt_properties_get_name( properties, i ),
- mlt_properties_get_value( properties, i ) );
-
- Note that properties are retrieved in the order in which they are set.
-
- Properties are also used to hold pointers to memory. This is done via the
- set_data call:
-
- uint8_t *image = malloc( size );
- mlt_properties_set_data( properties, "image", image, size, NULL, NULL );
-
- In this example, we specify that the pointer can be retrieved from
- properties by a subsequent request to get_data:
-
- image = mlt_properties_get_data( properties, "image", &size );
-
- or:
-
- image = mlt_properties_get_data( properties, "image", NULL );
-
- if we don't wish to retrieve the size.
-
- Two points here:
-
- 1) The allocated memory remains after the properties object is closed unless
- you specify a destructor. In the case above, this can be done with:
-
- mlt_properties_set_data( properties, "image", image, size, free, NULL );
-
- When the properties are closed, or the value of "image" is changed, the
- destructor is invoked.
-
- 2) The string value returned by mlt_properties_get is NULL. Typically, you
- wouldn't wish to serialise an image as a string, but other structures
- might need such functionality - you can specify a serialiser as the last
- argument if required (declaration is char *serialise( void * )).
-
- Properties also provides some more advanced usage capabilities.
-
- It has the ability to inherit all serialisable values from another properties
- object:
-
- mlt_properties_inherit( this, that );
-
- It has the ability to mirror properties set on this on another set of
- properties:
-
- mlt_properties_mirror( this, that );
-
- After this call, all serialisable values set on this are passed on to that.
-
-
-mlt_deque:
-
- Stacks and queues are essential components in the MLT framework. Being of a
- lazy disposition, we elected to implement a 'Double Ended Queue' (deque) -
- this encapsulates the functionality of both.
-
- The API of the deque is defined as follows:
-
- mlt_deque mlt_deque_init( );
- int mlt_deque_count( mlt_deque this );
- int mlt_deque_push_back( mlt_deque this, void *item );
- void *mlt_deque_pop_back( mlt_deque this );
- int mlt_deque_push_front( mlt_deque this, void *item );
- void *mlt_deque_pop_front( mlt_deque this );
- void *mlt_deque_peek_back( mlt_deque this );
- void *mlt_deque_peek_front( mlt_deque this );
- void mlt_deque_close( mlt_deque this );
-
- The stacking operations are used in a number of places:
-
- * Reverse Polish Notation (RPN) image and audio operations
- * memory pooling
-
- The queuing operations are used in:
-
- * the consumer base class;
- * consumer implementations may require further queues.
-
-
-mlt_pool:
-
- The MLT framework provides memory pooling capabilities through the mlt_pool
- API. Once initilialised, these can be seen as a straightforward drop in
- replacement for malloc/realloc/free functionality.
-
- The background behind this API is that malloc/free operations are
- notoriously inefficient, especially when dealing with large blocks of memory
- (such as an image). On linux, malloc is optimised for memory allocations
- less than 128k - memory blocks allocated of these sizes or less are retained
- in the process heap for subsequent reuse, thus bypassing the kernel calls
- for repeated allocation/frees for small blocks of memory. However, blocks of
- memory larger than that require kernel calls and this has a detrimental
- impact on performance.
-
- The mlt_pool design is simply to hold a list of stacks - there is one stack
- per 2^n bytes (where n is between 8 and 31). When an alloc is called, the
- requested size is rounded to the next 2^n, the stack is retrieved for that
- size, and an item is popped or created if the stack is empty.
-
- Each item has a 'header', situated immediately before the returned address -
- this holds the 'stack' to which the item belongs.
-
- When an item is released, we retrieve the header, obtain the stack and push
- it back.
-
- Thus, from the programmers point of view, the API is the same as the
- traditional malloc/realloc/free calls:
-
- void *mlt_pool_alloc( int size );
- void *mlt_pool_realloc( void *ptr, int size );
- void mlt_pool_release( void *release );
-
-
-mlt_frame:
-
- A frame object is essentially defined as:
-
- +------------+
- |frame |
- +------------+
- | properties |
- | image stack|
- | audio stack|
- +------------+
-
- The life cycle of a frame can be represented as follows:
-
- +-----+----------------------+-----------------------+---------------------+
- |Stage|Producer |Filter |Consumer |
- +-----+----------------------+-----------------------+---------------------+
- | 0.0 | | |Request frame |
- +-----+----------------------+-----------------------+---------------------+
- | 0.1 | |Receives request | |
- | | |Request frame | |
- +-----+----------------------+-----------------------+---------------------+
- | 0.2 |Receives request | | |
- | |Generates frame for | | |
- | |current position | | |
- | |Increments position | | |
- +-----+----------------------+-----------------------+---------------------+
- | 0.3 | |Receives frame | |
- | | |Updates frame | |
- +-----+----------------------+-----------------------+---------------------+
- | 0.4 | | |Receives frame |
- +-----+----------------------+-----------------------+---------------------+
-
- Note that neither the filter nor the consumer have any conception of
- 'position' until they receive a frame. Speed and position are properties of
- the producer, and they are assigned to the frame object when the producer
- creates it.
-
- Step 0.3 is a critical one here - if the filter determines that the frame is
- of interest to it, then it should manipulate the image and/or audio stacks
- and properties as required.
-
- Assuming that the filter deals with both image and audio, then it should
- push data and methods on to the stacks which will deal with the processing.
- This can be done with the mlt_frame_push_image and audio methods. In order for
- the filter to register interest in the frame, the stacks should hold:
-
- image stack:
- [ producer_get_image ] [ data1 ] [ data2 ] [ filter_get_image ]
-
- audio stack:
- [ producer_get_audio ] [ data ] [ filter_get_audio ]
-
- The filter_get methods are invoked automatically when the consumer invokes a
- get_image on the frame.
-
- +-----+----------------------+-----------------------+---------------------+
- |Stage|Producer |Filter |Consumer |
- +-----+----------------------+-----------------------+---------------------+
- | 1.0 | | |frame_get_image |
- +-----+----------------------+-----------------------+---------------------+
- | 1.1 | |filter_get_image: | |
- | | | pop data2 and data1 | |
- | | | frame_get_image | |
- +-----+----------------------+-----------------------+---------------------+
- | 1.2 |producer_get_image | | |
- | | Generates image | | |
- +-----+----------------------+-----------------------+---------------------+
- | 1.3 | |Receives image | |
- | | |Updates image | |
- +-----+----------------------+-----------------------+---------------------+
- | 1.4 | | |Receives image |
- +-----+----------------------+-----------------------+---------------------+
-
- Obviously, if the filter isn't interested in the image, then it should leave
- the stack alone, and then the consumer will retrieve its image directly from
- the producer.
-
- Similarly, audio is handled as follows:
-
- +-----+----------------------+-----------------------+---------------------+
- |Stage|Producer |Filter |Consumer |
- +-----+----------------------+-----------------------+---------------------+
- | 2.0 | | |frame_get_audio |
- +-----+----------------------+-----------------------+---------------------+
- | 2.1 | |filter_get_audio: | |
- | | | pop data | |
- | | | frame_get_audio | |
- +-----+----------------------+-----------------------+---------------------+
- | 2.2 |producer_get_audio | | |
- | | Generates audio | | |
- +-----+----------------------+-----------------------+---------------------+
- | 2.3 | |Receives audio | |
- | | |Updates audio | |
- +-----+----------------------+-----------------------+---------------------+
- | 2.4 | | |Receives audio |
- +-----+----------------------+-----------------------+---------------------+
-
- And finally, when the consumer is done with the frame, it should close it.
-
- Note that a consumer may not evaluate both image and audio for any given
- frame, especially in a realtime environment. See 'Realtime Considerations'
- below.
-
- By default, a frame has the following properties:
-
- +------------------+------------------------------------+------------------+
- |Name |Description |Values |
- +------------------+------------------------------------+------------------+
- |_position |The producers frame position |0 to n |
- +------------------+------------------------------------+------------------+
- |_speed |The producers speed |double |
- +------------------+------------------------------------+------------------+
- |image |The generated image |NULL or pointer |
- +------------------+------------------------------------+------------------+
- |alpha |The generated alpha mask |NULL or pointer |
- +------------------+------------------------------------+------------------+
- |width |The width of the image | |
- +------------------+------------------------------------+------------------+
- |height |The height of the image | |
- +------------------+------------------------------------+------------------+
- |normalised_width |The normalised width of the image |720 |
- +------------------+------------------------------------+------------------+
- |normalised_height |The normalised height of the image |576 or 480 |
- +------------------+------------------------------------+------------------+
- |progressive |Indicates progressive/interlaced |0 or 1 |
- +------------------+------------------------------------+------------------+
- |top_field_first |Indicates top field first |0 or 1 |
- +------------------+------------------------------------+------------------+
- |audio |The generated audio |NULL or pointer |
- +------------------+------------------------------------+------------------+
- |frequency |The frequency of the audio | |
- +------------------+------------------------------------+------------------+
- |channels |The channels of the audio | |
- +------------------+------------------------------------+------------------+
- |samples |The samples of the audio | |
- +------------------+------------------------------------+------------------+
- |aspect_ratio |The sample aspect ratio of the image|double |
- +------------------+------------------------------------+------------------+
- |test_image |Used to indicate no image available |0 or 1 |
- +------------------+------------------------------------+------------------+
- |test_audio |Used to indicate no audio available |0 or 1 |
- +------------------+------------------------------------+------------------+
-
- The consumer can attach the following properties which affect the default
- behaviour of a frame:
-
- +------------------+------------------------------------+------------------+
- |test_card_producer|Synthesise test images from here |NULL or pointer |
- +------------------+------------------------------------+------------------+
- |consumer_aspect_ |Apply this aspect ratio to the test |double |
- |ratio |card producer | |
- +------------------+------------------------------------+------------------+
- |rescale.interp |Use this scale method for test image|"string" |
- +------------------+------------------------------------+------------------+
-
- While most of these are mainly self explanatory, the normalised_width and
- normalised_height values require a little explanation. These are required
- to ensure that effects are consistently handled as PAL or NTSC, regardless
- of the consumers or producers width/height image request.
-
- The test_image and audio flags are used to determine when images and audio
- should be synthesised.
-
- Additional properties may be provided by the producer implementation, and
- filters, transitions and consumers may add additional properties to
- communicate specific requests. These are documented in modules.txt.
-
- The complete API for the mlt frame is as follows:
-
- mlt_frame mlt_frame_init( );
- mlt_properties mlt_frame_properties( mlt_frame this );
- int mlt_frame_is_test_card( mlt_frame this );
- int mlt_frame_is_test_audio( mlt_frame this );
- double mlt_frame_get_aspect_ratio( mlt_frame this );
- int mlt_frame_set_aspect_ratio( mlt_frame this, double value );
- mlt_position mlt_frame_get_position( mlt_frame this );
- int mlt_frame_set_position( mlt_frame this, mlt_position value );
- int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
- uint8_t *mlt_frame_get_alpha_mask( mlt_frame this );
- int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
- int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image );
- mlt_get_image mlt_frame_pop_get_image( mlt_frame this );
- int mlt_frame_push_frame( mlt_frame this, mlt_frame that );
- mlt_frame mlt_frame_pop_frame( mlt_frame this );
- int mlt_frame_push_service( mlt_frame this, void *that );
- void *mlt_frame_pop_service( mlt_frame this );
- int mlt_frame_push_audio( mlt_frame this, void *that );
- void *mlt_frame_pop_audio( mlt_frame this );
- void mlt_frame_close( mlt_frame this );
-
-
-mlt_service:
-
- The service base class extends properties and allows 0 to m inputs and 0 to
- n outputs and is represented as follows:
-
- +-----------+
- - ->| |- ->
- - ->| Service |- ->
- - ->| |
- +-----------+
- | properties|
- +-----------+
-
- Descendents of service impose restrictions on how inputs and outputs can be
- connected and will provide a basic set of properties. Typically, the service
- instance is encapsulated by the descendent in order for it to ensure that
- its connection rules are followed.
-
- A service does not define any properties when constructed. It should be
- noted that producers, filters and transitions my be serialised (say, via the
- westley consumer), and care should be taken to distinguish between
- serialisable and transient properties. The convention used is to prefix
- transient properties with an underscore.
-
- The public interface is defined by the following functions:
-
- int mlt_service_init( mlt_service this, void *child );
- mlt_properties mlt_service_properties( mlt_service this );
- int mlt_service_connect_producer( mlt_service this, mlt_service producer, int index );
- int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
- void mlt_service_close( mlt_service this );
-
- Typically, only direct descendents of services need invoke these methods and
- developers are encouraged to use those extensions when defining new services.
-
-
-mlt_producer:
-
- A producer has 0 inputs and 1 output:
-
- +-----------+
- | |
- | Producer |--->
- | |
- +-----------+
- | service |
- +-----------+
-
- A producer provides an abstraction for file readers, pipes, streams or any
- other image or audio input.
-
- When instantiated, a producer has the following properties:
-
- +------------------+------------------------------------+------------------+
- |Name |Description |Values |
- +------------------+------------------------------------+------------------+
- |mlt_type |The producers type |mlt_producer |
- +------------------+------------------------------------+------------------+
- |_position |The producers frame position |0 to n |
- +------------------+------------------------------------+------------------+
- |_speed |The producers speed |double |
- +------------------+------------------------------------+------------------+
- |fps |The output frames per second |25 or 29.97 |
- +------------------+------------------------------------+------------------+
- |in |The in point in frames |0 to length - 1 |
- +------------------+------------------------------------+------------------+
- |out |The out point in frames |in to length - 1 |
- +------------------+------------------------------------+------------------+
- |length |The length of the input in frames |0 to n |
- +------------------+------------------------------------+------------------+
- |aspect_ratio |aspect_ratio of the source |0 to n |
- +------------------+------------------------------------+------------------+
- |eof |end of clip behaviour |"pause" or "loop" |
- +------------------+------------------------------------+------------------+
- |resource |Constructor argument (ie: file name)|"<resource>" |
- +------------------+------------------------------------+------------------+
-
- Additional properties may be provided by the producer implementation.
-
- The public interface is defined by the following functions:
-
- mlt_producer mlt_producer_new( );
- int mlt_producer_init( mlt_producer this, void *child );
- mlt_service mlt_producer_service( mlt_producer this );
- mlt_properties mlt_producer_properties( mlt_producer this );
- int mlt_producer_seek( mlt_producer this, mlt_position position );
- mlt_position mlt_producer_position( mlt_producer this );
- mlt_position mlt_producer_frame( mlt_producer this );
- int mlt_producer_set_speed( mlt_producer this, double speed );
- double mlt_producer_get_speed( mlt_producer this );
- double mlt_producer_get_fps( mlt_producer this );
- int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out );
- mlt_position mlt_producer_get_in( mlt_producer this );
- mlt_position mlt_producer_get_out( mlt_producer this );
- mlt_position mlt_producer_get_playtime( mlt_producer this );
- mlt_position mlt_producer_get_length( mlt_producer this );
- void mlt_producer_prepare_next( mlt_producer this );
- void mlt_producer_close( mlt_producer this );
-
-
-mlt_filter:
-
- The public interface is defined by the following functions:
-
- int mlt_filter_init( mlt_filter this, void *child );
- mlt_filter mlt_filter_new( );
- mlt_service mlt_filter_service( mlt_filter this );
- mlt_properties mlt_filter_properties( mlt_filter this );
- mlt_frame mlt_filter_process( mlt_filter this, mlt_frame that );
- int mlt_filter_connect( mlt_filter this, mlt_service producer, int index );
- void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out );
- int mlt_filter_get_track( mlt_filter this );
- mlt_position mlt_filter_get_in( mlt_filter this );
- mlt_position mlt_filter_get_out( mlt_filter this );
- void mlt_filter_close( mlt_filter );
-
-
-mlt_transition:
-
- The public interface is defined by the following functions:
-
- int mlt_transition_init( mlt_transition this, void *child );
- mlt_transition mlt_transition_new( );
- mlt_service mlt_transition_service( mlt_transition this );
- mlt_properties mlt_transition_properties( mlt_transition this );
- int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track );
- void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out );
- int mlt_transition_get_a_track( mlt_transition this );
- int mlt_transition_get_b_track( mlt_transition this );
- mlt_position mlt_transition_get_in( mlt_transition this );
- mlt_position mlt_transition_get_out( mlt_transition this );
- mlt_frame mlt_transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame );
- void mlt_transition_close( mlt_transition this );
-
-
-mlt_consumer:
-
- The public interface is defined by the following functions:
-
- int mlt_consumer_init( mlt_consumer this, void *child );
- mlt_service mlt_consumer_service( mlt_consumer this );
- mlt_properties mlt_consumer_properties( mlt_consumer this );
- int mlt_consumer_connect( mlt_consumer this, mlt_service producer );
- int mlt_consumer_start( mlt_consumer this );
- mlt_frame mlt_consumer_get_frame( mlt_consumer this );
- mlt_frame mlt_consumer_rt_frame( mlt_consumer this );
- int mlt_consumer_stop( mlt_consumer this );
- int mlt_consumer_is_stopped( mlt_consumer this );
- void mlt_consumer_close( mlt_consumer );
-
-
-Specialised Producers:
-
- There are two major types of specialised producers - playlists and tractors.
-
- The following sections describe these.
-
-
-mlt_playlist:
-
- mlt_playlist mlt_playlist_init( );
- mlt_producer mlt_playlist_producer( mlt_playlist this );
- mlt_service mlt_playlist_service( mlt_playlist this );
- mlt_properties mlt_playlist_properties( mlt_playlist this );
- int mlt_playlist_count( mlt_playlist this );
- int mlt_playlist_clear( mlt_playlist this );
- int mlt_playlist_append( mlt_playlist this, mlt_producer producer );
- int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out );
- int mlt_playlist_blank( mlt_playlist this, mlt_position length );
- mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index );
- int mlt_playlist_current_clip( mlt_playlist this );
- mlt_producer mlt_playlist_current( mlt_playlist this );
- int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index );
- int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out );
- int mlt_playlist_remove( mlt_playlist this, int where );
- int mlt_playlist_move( mlt_playlist this, int from, int to );
- int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out );
- void mlt_playlist_close( mlt_playlist this );
-
-mlt_tractor:
+++ /dev/null
-Inigo Documentation
-
-Copyright (C) 2004-2009 Ushodaya Enterprised Limited
-Author: Charles Yates <charles.yates@pandora.be>
-Last Revision: 2009-01-21
-
-
-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 [options] [producer [name=value]* ]+
- Options:
- -attach filter[:arg] [name=value]* Attach a filter to the output
- -attach-cut filter[:arg] [name=value]* Attach a filter to a cut
- -attach-track filter[:arg] [name=value]* Attach a filter to a track
- -attach-clip filter[:arg] [name=value]* Attach a filter to a producer
- -audio-track | -hide-video Add an audio-only track
- -blank frames Add blank silence to a track
- -consumer id[:arg] [name=value]* Set the consumer (sink)
- -debug Set the logging level to debug
- -filter filter[:arg] [name=value]* Add a filter to the current track
- -group [name=value]* Apply properties repeatedly
- -help Show this message
- -join clips Join multiple clips into one cut
- -mix length Add a mix between the last two cuts
- -mixer transition Add a transition to the mix
- -null-track | -hide-track Add a hidden track
- -profile name Set the processing settings
- -progress Display progress along with the position
- -remove Remove the most recent cut
- -repeat times Repeat the last cut
- -query List all of the registered services
- -query "consumers" | "consumer"=id List consumers or show info about one
- -query "filters" | "filter"=id List filters or show info about one
- -query "producers" | "producer"=id List producers or show info about one
- -query "transitions" | "transition"=id List transitions or show info about one
- -serialise [filename] Write the commands to a text file
- -silent Do not display position/transport help
- -split relative-frame Split the last cut into two cuts
- -swap Rearrange the last two cuts
- -track Add a track
- -transition id[:arg] [name=value]* Add a transition
- -verbose Set the logging level to verbose
- -version Show the version and copyright message
- -video-track | -hide-audio Add a video-only track
-
-
-General rules:
-
- 1. Order is incredibly important;
-
- 2. Error checking on command line parsing is weak;
-
- 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 mlt-centric. Producers produce MLT frame objects and consumers
- consume MLT frame objects. The distinction is important - a DV producer
- does not produce DV, it produces MLT frames from a DV source, and similarly
- a DV consumer does not consume DV, it consumes MLT frames and produces DV
- frames.
-
-
-Terminology:
-
- 'Producers' typically refer to files but may also indicate devices (such as
- dv1394 input or video4linux). Hence, the more generic term is used [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. Nothing says that a filter cannot generate frames though
-
- 'Transitions' collect frames from two tracks (a and b) and output 1
- modified frame on their 'a track', and 1 unmodified frame on their 'b track'.
- Never more, never less, ever.
-
- 'Consumers' collect frames from a producer, do something with them and
- destroy them.
-
- Collectively, these are known as 'services'.
-
- All services have 'properties' associated to them. These are typically
- defaulted or evaluated and may be overriden on a case by case basis.
-
- All services except consumers obey in and out properties.
-
- 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:
-
- $ inigo file
-
- Note that 'file' can be anything that inigo has a known 'producer' mapping
- for (so this can be anything from .dv to .txt).
-
- You can also specify the producer directly, for example:
-
- $ inigo avformat:file.mpeg
-
- Would force the direct use of avformat for loading the file.
-
-
-Properties:
-
- Properties can be assigned to the producer by adding additional name=value
- pairs after the producer:
-
- $ inigo file in=50 out=100 something="something else"
-
- Note that while some properties have meaning to all producers (for example:
- in, out and length are guaranteed to be valid for all, though typically,
- length is determined automatically), the validity of others are dependent on
- the producer - however, properties will always be assigned and silently
- ignored if they won't be used.
-
-
-Multiple Files:
-
- Multiple files of different types can be used:
-
- $ inigo a.dv b.mpg c.png
-
- Properties can be assigned to each file:
-
- $ inigo a.dv in=50 out=100 b.mpg out=500 c.png out=500
-
- MLT will take care of 'normalising' the output of a producer to ensure
- that the consumer gets what it needs. So, in the case above, the mlt
- framework will ensure that images are rescaled and audio resampled to meet
- the requirements of your configuration (which, by default, will be PAL).
- See 'Appendix A: Normalisation Rules' below.
-
-
-Filters:
-
- Filters are frame modifiers - they can change the contents of the audio or
- the images associated to a frame.
-
- $ inigo a.dv -filter greyscale
-
- As with producers, properties may be specified on filters too.
-
- Again, in and out properties are common to all, so to apply a filter to a
- range of frames, you would use something like:
-
- $ inigo a.dv -filter greyscale in=0 out=50
-
- 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 following
- 'services'. For example:
-
- $ inigo -group in=0 out=49 clip*
-
- would play the first 50 frames of all clips that match the wild card
- pattern.
-
- Note that the last -group settings also apply to the following filters,
- transitions and consumers, so:
-
- $ inigo -group in=0 out=49 clip* -filter greyscale
-
- is *probably not* what you want (ie: the greyscale filter would only be
- applied to the first 50 frames).
-
- To shed the group properties, you can use any empty group:
-
- $ 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 introduce 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 -transition
- 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
- playlist, or more accurately, track.
-
- When multiple tracks exist, the consumer will receive a frame
- from the 'highest numbered' track that is generating a non-blank
- frame.
-
- It is best to visualise a track arrangement, so we'll start with
- an example:
-
- $ inigo a.dv -track b.dv in=0 out=49
-
- This can be visualised as follows:
-
- +------------------+
- |a |
- +-------+----------+
- |b |
- +-------+
-
- Playout will show the first 50 frames of b and the 51st frame shown will be
- the 51st frame of a.
-
- This rule also applies to audio only producers on the second track, for
- example, the following would show the video from the a track, but the audio
- would come from the second track:
-
- $ inigo a.dv -track b.mp3 in=0 out=49
-
- 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
-
- Which we can visualise as:
-
- +-------+
- |a |
- +-------+-------------------+
- |b |
- +-------------------+
-
- Now playout will continue as though a and b clips are on the
- same track (which on its own, is about as useful as reversing the
- process of slicing bread).
-
-
-Transitions:
-
- Where tracks become useful is in the placing of transitions.
-
- Here we need tracks to overlap, so a useful multitrack
- definition could be given as:
-
- $ inigo a.dv out=49 \
- -track \
- -blank 24 b.dv \
- -transition luma in=25 out=49 a_track=0 b_track=1
-
- Now we're cooking - our visualisation would be something like:
-
- +-------+
- |a |
- +---+---+--------------+
- |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 situations
- like:
-
- +-------+ +----------+
- |a1 | |a2 |
- +---+---+--------------+----+-----+
- |b |
- +-----------------------+
-
- In this case, we have two transitions, a1 to b and b to a2.
-
- In this scenario, we define a command line as follows:
-
- $ inigo a.dv out=49 -blank 49 a2.dv \
- -track \
- -blank 24 b.dv out=99 \
- -transition luma in=25 out=49 a_track=0 b_track=1 \
- -transition luma in=100 out=124 reverse=1 a_track=0 b_track=1
-
-
-Serialisation:
-
- Inigo has a built in serialisation mechanism - you can build up
- your command, test it via any consumer and then add a -serialise
- file.inigo switch to save it.
-
- 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....
-
- A more expressive serialisation can be obtained with the westley consumer
- - this will provide an xml document which can be used freely in inigo and
- miracle.
-
- See westley.txt for more information.
-
-
-Missing Features:
-
- Some filters/transitions should be applied on the output frame regardless
- of which track it comes from - for example, you might have a 3rd text
- track or a watermark which you want composited on every frame, and of
- course, there's the obscure filter....
-
- inigo only supports this in two invocations - as a simple example:
-
- $ inigo a.dv -track -blank 100 b.dv -consumer westley:basic.westley
- $ inigo basic.westley -filter watermark:watermark.png
-
+++ /dev/null
-Service Documentation
-
-Authors: Charles Yates <charles.yates@pandora.be>
- Dan Dennedy <dan@dennedy.org>
-Last Revision: $Date$
-
-
-SERVICES
---------
-
- Services marked as "(Proprietary)" are not distributed with the LGPL
- version of mlt.
-
-Producers
----------
-
- avformat
-
- Description
-
- ffmpeg libavformat based producer for video and audio.
-
- Constructor Argument
-
- 'file' - a filename specification or URL in the form:
- [{protocol}|{format}]:{resource}[?{format-parameter}[&{format-parameter}...]]
- For example, video4linux:/dev/video1?width:320&height:240
- Note: on the bash command line, & must be escaped as '\&'.
- Also, note the use of ':' instead of '=' for parameters.
- Use 'ffmpeg -formats' to see a list of supported protocols
- and formats.
-
- Details
-
- Format parameters only appear to be useful with 'video4linux' or
- 'audio_device' formats. For 'video4linux' the parameters are
- width, height, frame_rate, frame_rate_base, and standard (ntsc|pal).
- For 'audio_device' the parameters are channels and sample_rate.
-
- Initialisation Properties
-
- int video_index - index of video stream to use (-1 is off)
- int audio_index - index of audio stream to use (-1 is off)
- int in - in point
- int out - out point
-
- Read Only Properties
-
- string resource - file location
- double source_fps - the framerate of the resource
- double aspect_ratio - sample aspect ratio of the resource
- - this is determined on every frame read
-
- Dependencies
-
- ffmpeg
-
- Known Bugs
-
- Audio sync discrepancy with some content.
- Not all libavformat supported formats are seekable.
- Fails to play beyond first frame of video of sources with PTS not
- starting at 0 (video4linux).
-
- fezzik
-
- Description
-
- A friendly giant that likes to rhyme and throw rocks
-
- Constructor Argument
-
- 'file' - a filename specification:
- [{mlt-service}:]{resource} | {mlt-service}
- - can also be the name of a producer service that can
- accept the resource specified post construction.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- + all producer initialising properties
-
- Read Only Properties
-
- string resource - file location
- + all producer read only properties
-
- Details
-
- This producer has two roles:
-
- 1. it handles the mappings of all file names to the other
- producers;
- 2. it attaches normalising filters (rescale, resize and resample)
- to the producers (when necessary).
-
- This producer simplifies many aspects of use. Essentially, it
- ensures that a consumer will receive images and audio precisely as
- they request them.
-
- Dependencies
-
- all.
-
- Known Bugs
-
- None.
-
-
- colour
-
- Description
-
- A simple colour generator.
-
- Constructor Argument
-
- colour - A colour value is a hexadecimal representation of RGB plus
- alpha channel as 0xrrggbbaa.
- - Also colours can be the words: white, black, red, green,
- or blue.
- - The default colour is black.
-
- Initialisation Properties
-
- none
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
-
- libdv
-
- Description
-
- libdv based decoder for video and audio.
-
- Constructor Argument
-
- 'file' - produce a/v from file
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- string resource - file location
- double fps - output frames per second
- int length - duration of resource (in frames)
-
- Mutable Properties
-
- string quality - one of "best," "fast" or anything else chooses
- medium.
-
- Dependencies
-
- libdv.
-
- Known Bugs
-
- DVCPRO is incorrectly identified as 16:9 aspect ratio. You must use
- libdv from CVS or a post 0.101 release.
-
- mcdv (Proprietary)
-
- Description
-
- MainConcept based dv decoder for video and audio.
-
- Constructor Argument
-
- 'file' - produce a/v from file
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- string resource - file location
- double fps - output frames per second
- int length - duration of resource (in frames)
-
- Dependencies
-
- MainConcept DV or DVCPRO SDK, libdv.
- "dv_sdk" installed parallel to mlt.
-
- Known Bugs
-
- None
-
- mcmpeg (Proprietary)
-
- Description
-
- MainConcept based mpeg decoder for video and audio.
-
- Constructor Argument
-
- 'file' - produce a/v from file
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- string resource - file location
- double fps - output frames per second
- double aspect_ratio - sample aspect ratio of video
- int length - duration of resource (in frames)
-
- Dependencies
-
- MainConcept MPEG SDK.
- "mpeg_sdk_release" installed parallel to mlt.
-
- Known Bugs
-
- None.
-
- noise
-
- Description
-
- White noise producer
-
- Constructor Argument
-
- none
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- string resource - file location
- double fps - output frames per second
- double aspect_ratio - sample aspect ratio of video
- int length - duration of resource (in frames)
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
- pango
-
- Description
-
- A title generator that uses the Pango international text layout
- and Freetype2 font renderer.
-
- Constructor Argument
-
- string file - a text file containing Pango markup, see:
- http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html
- - requires xml-like encoding special chars from:
- <, >, & -to- <, >, &
-
- Details
-
- Supplying a filename with extension ".txt" causes the Fezzik
- producer to load with pango. If the filename begins with "+" the
- pango producer interprets the filename as pango text. This is a
- shortcut to embed titles in inigo commands. For westley, it is
- recommended that you embed the title text in the property value.
-
- Pango has builtin scaling. It will rescale the originally rendered
- title to whatever the consumer requests. Therefore, it will lose
- its aspect ratio if so requested, and it is up to the consumer to
- request a proper width and height that maintains the image aspect.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- string markup - a string containing Pango markup see:
- http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html
- - requires xml-like encoding special chars from:
- <, >, & -to- <, >, &
- string fgcolour - an RGBA colour specification of the text
- (i.e. 0xrrggbbaa)
- string bgcolour - an RGBA colour of the background rectangle
- string align - paragraph alignment: left, centre, right
- - also, numbers 0, 1 and 2 can be used respectively.
- int pad - the number of pixels to pad the background rectangle
- beyond edges of text. default 0.
- string markup - see constructor argument
- string text - non-markup string in UTF-8 encoding (can contain
- markup chars un-encoded)
- string font - the default typeface to use when not using markup.
- default "Sans 48". FreeType2 renders at 72 dpi.
- string encoding - the text encoding type of the input if not UTF-8.
- - see 'iconv --list' for a list of possible inputs.
- int weight - the weight of the font (default is 400)
-
- Read Only Properties
-
- string resource - the text/markup file or "pango" if no file.
- int real_width - the original, unscaled width of the rendered title.
- int real_height - the original, unscaled height of the title.
- int width - the last requested scaled image width.
- int height - the last requested scaled image height.
-
- Dependencies
-
- libpango-1.0, libpangoft2-1.0, libfreetype, libgdk_pixbuf-2.0,
- libglib-2.0, libgobject-2.0, libgmodule-2.0, libfontconfig.
-
- Known Bugs
-
- The foreground and background Pango markup span attributes are not
- supported.
- Word wrapping is not supported.
-
- pixbuf
-
- Description
-
- A still graphics to video generator using gdk-pixbuf
-
- Constructor Argument
-
- 'file' - The name of a graphics file loadable by
- a gdk-pixbuf loader. see /usr/lib/gdk-pixbuf/loaders
- definitely png, jpeg, tiff, pnm, and xpm
- - If "%" in filename, the filename is used with sprintf
- generate a filename from a counter for multi-file/flipbook
- animation. The file sequence ends when numeric
- discontinuity >100.
- - If filename contains "/.all.", suffix with an extension to
- load all pictures with matching extension from a directory.
- - If filename contains the string "<svg", then pixbuf tries
- to load the filename as inline SVG XML, which is convenient
- for inigo commands.
-
- Details
-
- Pixbuf has builtin scaling. It will rescale the originally rendered
- title to whatever the consumer requests. Therefore, it will lose
- its aspect ratio if so requested, and it is up to the consumer to
- request a proper width and height that maintains the image aspect.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- int begin - when using an image sequence, this sets the starting
- number.
-
- Mutable Properties
-
- int ttl - how long (in frames) to repeat each picture in file
- sequences. default is 25.
-
- Read Only Properties
-
- string resource - file location. See Constructor Argument above.
- int real_width - the original, unscaled width of the rendered title.
- int real_height - the original, unscaled height of the title.
- int width - the last requested scaled image width.
- int height - the last requested scaled image height.
-
- Dependencies
-
- libgdk_pixbuf-2.0, libglib-2.0, libgobject-2.0, libgmodule-2.0
-
- Known Bugs
-
- XXX: in/out settings are incorrectly handled.
-
- ppm
-
- Description
-
- Reads a stream of contiguous PPM images.
-
- Constructor Argument
-
- command - a shell command to run something that produces ppm
- streams on stdout.
-
- Initialisation Properties
-
- none
-
- Read Only Properties
-
- string resource - the command
-
- Dependencies
-
- none
-
- Known Bugs
-
- Since it uses pipes, it is not compatible with bluefish.
-
- westley
-
- Description
-
- Construct a service network from an XML description.
- See docs/westley.txt.
-
- Constructor Argument
-
- URL - an XML text file containing westley XML (schema/DTD pending)
- - Since westley files can be parameterised, the URL syntax is:
- {file-name}[?{param-name}{'='|':'}{param-value}[&{param-name}{'='|':'}{param-value}...]]
- A colon is allowed instead of an equal sign to pacify inigo,
- who tokenises anything with an equal sign as a property
- setting. Also, when running inigo from the shell, beware of
- the '?' and shell filename expansion. You can surround the URL
- with single quotations to prevent expansion. Finally, fezzik
- will fail to match the filename when you use parameters, so
- preface the url with 'westley:' to force fezzik to load with
- the westley service.
-
- Read Only Properties
-
- string resource - file location
-
- Dependencies
-
- libxml2
-
- Known Bugs
-
- Non-referenced producers and playlists are not destroyed until the
- network is destroyed.
- A referenced producer or playlist must appear before the reference.
- A filter that occurs before a producer has been defined causes a
- segfault.
-
- vorbis
-
- Description
-
- OGG Vorbis file reader.
-
- Constructor Argument
-
- 'file' - file to use (only .ogg supported at the moment)
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- double fps - this is fixed at 25 for PAL currently
-
- Dependencies
-
- libvorbisfile
-
- Known Bugs
-
- Fixed frame size (PAL audio chunks).
- Doesn't cover ogg files with multiple, differing sections.
-
-Filters
--------
-
- brightness
-
- Description
-
- Shift the luma component using a constant value.
-
- Constructor Argument
-
- start - the constant floating point numeric value to apply.
- - the default is 0.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- double start - see Constructor Argument above.
- double end - the ending adjustment value. the filter interpolates
- between the start and end adjustments over the
- duration of the effect.
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- Does not go completely to black or white.
-
-
- channelcopy
-
- Description
-
- Copy audio from one channel to another channel.
-
- Constructor Argument
-
- to - the 0-indexed channel to copy into, default is 1.
-
- Mutable Properties
-
- int to - see above
- int from - the channel from which to copy, default is 0.
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
-
-
- deinterlace
-
- Description
-
- Deinterlace a frame consisting of two fields using bob, weave,
- greedy, one-field, and linear blend methods. This code is
- appropriated from the Xine XV video output plugin.
-
- Constructor Argument
-
- method - a string containing the deinterlace method: bob, weave,
- greedy, onefield, or linearblend. The default is
- linearblend.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- string method
-
- Details
-
- If the frame properties "progressive" or "consumer_progressive"
- are non-zero, then the filter is not applied. Also, if applied,
- this sets the frame property "progressive" to 1.
-
- Dependencies
-
- none
-
- Known Bugs
-
- Not a bug, but it only provides fair quality.
-
-
- gamma
-
- Description
-
- Adjust image luma using a non-linear power-law curve
-
- Constructor Argument
-
- gamma - a floating point value. The default is 1.0, or none.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- double gamma - the exponential factor of the power-law curve
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
-
- greyscale
-
- Description
-
- Convert colour image to greyscale
-
- Constructor Argument
-
- none
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
- gtkrescale
-
- Description
-
- Scale the producer video frame size to match the consumer.
- This filter is designed for use as a Fezzik normaliser.
-
- Constructor Argument
-
- interpolation - the rescaling method, one of:
- nearest (lowest quality, fastest),
- tiles,
- bilinear (default; good quality, moderate speed),
- hyper (best quality, slowest).
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- string interpolation - see constructor argument above
-
- If a property "consumer_aspect_ratio" exists on the frame, then
- rescaler normalises the producer's aspect ratio and maximises the
- size of the frame, but may not produce the consumer's requested
- dimension. Therefore, this option works best in conjunction with the
- resize filter. This behavior can be disabled by another service by
- either removing the property, setting it to zero, or setting
- frame property "distort" to 1.
-
- Dependencies
-
- libgdk_pixbuf-2.0, libglib-2.0, libgobject-2.0, libgmodule-2.0
-
- Known Bugs
-
- none
-
- jackrack
-
- Description
-
- Creates Jack ports and runs a JackRack project to process audio
- through a stack of LADSPA filters.
-
- Constructor Argument
-
- src - a JackRack file
-
- Details
-
- If you are using a consumer that uses ALSA, then you should start
- jackd with the dummy driver: jackd -d dummy.
- I also recommend using a period size of 2048: -p 2048.
-
- jackd -ddummy -r48000 -p2048
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- The following can be used without a rack file in order to connect
- filter_jackrack to a running instance of JackRack:
- string out_1 - Jack port to connect MLT's output port (JackRack's input)
- string out_2 - Jack port to connect MLT's output port (JackRack's input)
- string in_1 - Jack port to connect MLT's input port (JackRack's output)
- string in_2 - Jack port to connect MLT's input port (JackRack's output)
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- none
-
- Dependencies
-
- Jack, LADSPA, glib-2.0, libxml2
-
- Known Bugs
-
- Currently, due to timing and synchronisation issues, the audio
- is distorted with repeated samples and latency clicks.
- no encapsulated resampling and jack runs at a fixed frequency
-
- ladspa
-
- Description
-
- Runs a JackRack project to process audio through a stack of
- LADSPA filters without using Jack.
-
- Constructor Argument
-
- src - a JackRack file
-
- Details
-
- Due to audio integrity issues with the jackrack filter, this
- filter is better for runtime, while jackrack is more suitable
- for prototyping a rack file using the Jack Rack GUI.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- none
-
- Dependencies
-
- Jack, LADSPA, glib-2.0, libxml2
- Jack is still required because this coexists with the jackrack
- filter.
-
- Known Bugs
-
- no encapsulated resampling and jack runs at a fixed frequency
-
- luma
-
- Description
-
- Applies a luma transition between the current and next frames.
- Useful for transitions from a slideshow created using producer
- pixbuf.
-
- Constructor Argument
-
- file - a luma wipe
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- int period - how long to wait between success iterations of the
- transition. For best results set this to a multiple
- of ttl used in pixbuf. The default is 24.
-
- luma. - all properties beginning with "luma." are passed to the
- encapsulated luma transition. For example, luma.out controls
- the duration of the wipe.
-
- Dependencies
-
- transition_luma and its dependencies
-
- Known Bugs
-
- none
-
- mcrescale
-
- Description
-
- Scale the producer video frame size to match the consumer.
- This filter is designed for use as a Fezzik normaliser.
-
- Constructor Argument
-
- interpolation - the rescaling method, one of:
- nearest (lowest quality, fastest),
- bilinear (default; good quality, moderate speed),
- hyper (best quality, slowest).
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- string interpolation - see constructor argument above
-
- If a property "consumer_aspect_ratio" exists on the frame, then
- rescaler normalises the producer's aspect ratio and maximises the
- size of the frame, but may not produce the consumer's requested
- dimension. Therefore, this option works best in conjunction with the
- resize filter. This behavior can be disabled by another service by
- either removing the property, setting it to zero, or setting
- frame property "distort" to 1.
-
- Dependencies
-
- the mainconcept rescaling sdk.
-
- Known Bugs
-
- none
-
- mirror
-
- Description
-
- Provides various mirror and image reversing effects.
-
- Constructor Argument
-
- mirror - horizontal, vertical, diagonal, flip, flop
-
- Initialisation Properties
-
- int reverse - being 0 or 1
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
-
- mono
-
- Description
-
- Mix all channels of audio into a mono signal and output it as
- N channels.
-
- Constructor Argument
-
- channels - the number of output channels (default 2)
-
- Initialisation Properties
-
- none
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
-
- obscure
-
- Description
-
- Obscuring filter.
-
- Constructor Argument
-
- none
-
- Initialisation Properties
-
- string start - in the format X,Y:WxH[:PWxPY]
- - PWxPY is the size of the averaging region in pixels.
- string end - in the format X,Y:WxH[:PWxPY]
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
- region
-
- Description
-
- Apply one or more filters to a region of the video image. The region
- can be shaped as well using the alpha channel of another producer.
-
- Constructor Argument
-
- resource - A file whose alpha channel will "shape" the region.
- - The string "circle" is a shortcut but it requires pixbuf with
- the librsvg loader. The circle is automatically stretched
- to the region to create an ellipse.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- plus and region transition properties
-
- Read Only Properties
-
- see the region transition
-
- Dependencies
-
- transition_region
-
- Known Bugs
-
- "circle" is unpredictable in the absence of the librsvg pixbuf loader.
-
-
- resample
-
- Description
-
- Adjust an audio stream's sampling rate, and duplicate channels if
- producer provides less than consumer requested.
-
- This filter is automatically invoked by Fezzik for the sake of
- normalisation over inputs and with the consumer.
-
- Constructor Argument
-
- frequency - a numeric value for the new sample rate
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- int frequency - the target sample rate
-
- Dependencies
-
- libresample
-
- Known Bugs
-
- Assumes 2 channels during libsamplerate initialisation. Untested
- with >2 channels.
-
- rescale
-
- Description
-
- Scale the producer video frame size to match the consumer.
- This filter is designed for use as a Fezzik normaliser.
-
- Constructor Argument
-
- None.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- If a property "consumer_aspect_ratio" exists on the frame, then
- rescaler normalises the producer's aspect ratio and maximises the
- size of the frame, but may not produce the consumer's requested
- dimension. Therefore, this option works best in conjunction with the
- resize filter. This behavior can be disabled by another service by
- either removing the property, setting it to zero, or setting
- frame property "distort" to 1.
-
- Dependencies
-
- none
-
- Known Bugs
-
- none but... it only implements a nearest neighbour scaling - it is
- used as the base class for the gtkrescale and mcrescale filters.
-
- resize
-
- Description
-
- Image scaling and padding and field order adjustment.
-
- Details
-
- Normally resize is used to pad the producer's
- output to what the consumer has requested after an upstream rescale
- filter first scales the image to maximise usage of the image area.
- This filter also adjusts the field order to lower field first
- if the frame property "top_field_first" has been set to 1.
- Therefore, when done, it sets the top_field_first to 0.
- This filter is automatically invoked by Fezzik as part of image
- sample aspect ratio normalisation.
-
- Constructor Argument
-
- scale - "affine" to use affine transform scaling, otherwise
- center and pad.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- Assumes lower field first output.
-
- volume
-
- Description
-
- Adjust an audio stream's volume level
- - based on the 'normalize' utility
-
- Constructor Argument
-
- gain - a string containing one of:
- - a floating point value of the gain adjustment
- - a numeric value with the suffix "dB" to adjust in terms of decibels
- - "normalise" to normalise the volume to the target amplitude -12dBFS
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- int window - the number of video frames over which to smooth normalisation.
- defaults to 75.
-
- Mutable Properties
-
- string gain - same as constructor argument above
-
- string normalise - normalise the volume to the amplitude:
- - a numeric value with the suffix "dB" to set amplitude in decibels
- - a floating point value of the relative volume
- - an unspecified value uses the default -12dBFS
-
- string limiter - limit all samples above:
- - a numeric value with the suffix "dB"
- - a floating point value ( dB = 20 * log10(x) )
- - an unspecified value uses the default -6dBFS
-
- double max_gain - a floating point or decibel value of the maximum gain that
- can be applied during normalisation.
- - an unspecified value uses the default 20dB
-
- string end - a gain value just like the gain property above.
- This causes the gain to be interpolated from 'gain' to 'end'
- over the duration.
-
- int window - the size of the normalising smoothing buffer in video frame units.
- - the smoothing buffer prevents erratic gain changes.
- - the default value is 75 video frames.
-
- gain can be applied as a factor to the normalise amplitude!
-
- Dependencies
-
- none
-
- Known Bugs
-
- none
-
- watermark
-
- Description
-
- Add a watermark to the frames.
-
- Constructor Argument
-
- resource - the producer to use (ie: a .png)
-
- Initialisation Properties
-
- string resource - the producer to use
- string factory - producer required for the resource ('fezzik')
- string geometry - composite geometry
- string distort - control scaling
- int in - in point
- int out - out point
-
- Mutable Properties
-
- none
-
- Dependencies
-
- mlt core modules and optionally, fezzik
-
- Known Bugs
-
- none
-
-Transitions
------------
-
- composite
-
- Description
-
- A key-framable alpha-channel compositor for two frames.
-
- Details
-
- Performs dissolves and luma wipes in addition to alpha compositing.
-
- By default, the aspect ratio of the B frame is respected and the
- size portion of the geometry specification simply defines a
- bounding rectangle.
-
- This performs field-based rendering unless the A frame property
- "progressive" or "consumer_progressive" or the transition property
- "progressive" is set to 1.
-
- Constructor Argument
-
- none[*]
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- string factory - The name of a factory service used as a non-PGM
- producer loader. The default is fezzik.
-
- Read Only Properties
-
- none
-
- Mutable Properties
-
-
- string geometry - key frame specification
- - this is a ; delimited form of the deprecated start,
- key[n], end properties
- int progressive - set to 1 to disable field-based rendering.
- string distort - when set, causes the B frame image to fill the WxH
- completely with no regard to B's aspect ratio.
- string halign - when not distorting, set the horizontal alignment
- of B within the geometry rectangle.
- - one of: left (0), centre (1), or right (2).
- - the default is left.
- string valign - when not distorting, set the vertical alignment of
- B within the geometry rectangle.
- - one of: top (0), middle (1), or bottom (2).
- - the default is top.
- string luma - the luma map file name. If not supplied, a dissolve.
- double softness - only when using a luma map, how soft to make the
- edges between A and B. 0.0 = no softness. 1.0 =
- too soft.
- Any property starting with "luma." is passed to the non-PGM luma
- producer.
-
- Deprecated Properties
-
- string start - a geometry specification as X,Y:WxH[!][:mix]
- - X, Y, W, H are assumed to pixel units unless they
- have the suffix '%'
- - '!' is a shortcut to specify distort, see below.
- - mix is always a 2 digit percentage, defaults to 100.
- - default is "85%,5%:10%x10%"
- string end - the ending size and position.
- string key[F] - X,Y:WxH[:mix] - set a key frame for geometry between
- the in and out. F is a frame number and can be
- negative to make it relative to the out point.
-
- Dependencies
-
- none
-
- Known Bugs
-
- Assumes lower field first during field rendering.
-
- luma
-
- Description
-
- A generic dissolve and wipe transition processor.
-
- Details
-
- luma gets its name
- from how it uses a grayscale "map" file. As the luma value varies
- over time, a threshold filter is applied to the map to determine
- what parts of frame A vs. frame B to show. It reads PGM files
- up to 16 bits! Alternatively, it can use the first frame from any
- producer that outputs yuv, but it will be limited to the luma
- gamut of 220 values.
- This performs field-based rendering unless the A frame property
- "progressive" or "consumer_progressive" or the transition property
- "progressive" is set to 1.
-
- Constructor Argument
-
- string resource - the luma map file name - either PGM or any other
- producable video.
- - If not supplied, a dissolve.
-
- Initialisation Properties
-
- int in - in point
- int out - out point
- string factory - The name of a factory service used as a non-PGM
- producer loader. The default is Fezzik.
-
- Mutable Properties
-
- string resource - same as above
- double softness - only when using a luma map, how soft to make the
- edges between A and B. 0.0 = no softness. 1.0 =
- too soft.
- int reverse - reverse the direction of the transition.
- Any property starting with "producer." is passed to the non-PGM luma
- producer.
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- Assumes lower field first output.
-
- mix
-
- Description
-
- An two stream audio mixer.
-
- Constructor Argument
-
- start - see below
-
- Initalisation Properties
-
- int in - in point
- int out - out point
-
- Mutable Properties
-
- double start - the mix level to apply to the second frame.
- - any negative value causes an automatic crossfade from 0 to 1.
- double end - the ending value of the mix level. mix level will be interpolated
- from start to end over the in-out range.
- int reverse - set to 1 to reverse the direction of the mix.
-
- Read Only Properties
-
- none
-
- Dependencies
-
- none
-
- Known Bugs
-
- Samples from the longer of the two frames are discarded.
-
-
- region
-
- Description
-
- Apply zero or more filters to B frame as it is composited onto
- a region of the A frame. The "shape" of the region can be defined
- by the alpha channel of a third producer.
-
- Constructor Argument
-
- resource - a shape producer
-
- Initialisation Properties
-
- string resource - nothing is rectangle, "circle" is a pixbuf-
- generated SVG circle, anything else is loaded by the factory.
- string factory - the service that creates the shape producer.
- - the default is fezzik.
- string filter[N] - one or more filters to apply. All filter
- properties are passed using the same filter "key"
- Any property starting with "composite." is passed to the
- encapsulated composite transition.
-
- Read Only Properties
-
- none
-
- Dependencies
-
- transition_composite
-
- Known Bugs
-
- none
-
-
-Consumers
----------
-
- avformat
-
- Description
-
- Multiformat transcoding consumer.
-
- Constructor Argument
-
- string target - the filename to write to, e.g. test.mpeg.
-
- Initialisation Properties
-
- int buffer - the number of frames to buffer, minimum 1, default 25.
- string rescale - a rescale method, see the Filters/rescale.
- int progressive - indicates whether to use progressive or field-
- based rendering, default 0 (off).
-
- Read Only Properties
-
- none
-
- Dependencies
-
- libavformat
-
- Known Bugs
-
- Plenty.
-
- bluefish (Proprietary)
-
- Description
-
- BlueFish444 audio and video output module.
-
- Constructor Argument
-
- card - a numeric card id starting at 1, default is 1.
-
- Initialisation Properties
-
- string standard - "PAL" (default) or "NTSC"
- - default is based upon MLT_NORMALISATION
- environment variable, which defaults to PAL.
- int frames - the number of DMA video frames. default is 8.
- minimum is 2. maximum on my system is 11.
- int buffer - the number of frames to buffer within MLT, minimum 1,
- default 25.
- string rescale - a rescale method, see the Filters/rescale.
-
- Read Only Properties
-
- none
-
- Dependencies
-
- BlueVelvet SDK installed parallel to mlt in "bluefish."
-
- Known Bugs
-
- Does not work with any service that uses pipes!
-
- If mlt crashes, you might need to reload the BlueDriver kernel
- module due to unreleased DMA buffers.
-
- Only supports 2 channel audio at the moment.
-
- libdv
-
- Description
-
- libdv dv producer.
-
- Constructor Argument
-
- string target - the filename to write to, e.g. /dev/dv1394.
-
- Initialisation Properties
-
- int buffer - the number of frames to buffer, minimum 1, default 25.
- string rescale - a rescale method, see the Filters/rescale.
-
- Mutable Properties
-
- int progressive - indicates whether to use progressive or field-
- based rendering, default 0 (off).
-
- Read Only Properties
-
- none
-
- Dependencies
-
- libdv
-
- Known Bugs
-
- none
-
- mcmpeg
-
- Description
-
- Mainconcept MPEG encoder.
-
- Constructor Argument
-
- string target - the filename to write to.
-
- Initialisation Properties
-
- int buffer - the number of frames to buffer, minimum 1, default 25.
- string rescale - a rescale method, see the Filters/rescale.
- string format - vcd [default], svcd or dvd provide base settings
- int motion_search_type - 0 to 16 - reduces quality/cpu usage
- int gop - group of picture size (default: format dependent)
-
- Mutable Properties
-
- int progressive - indicates whether to use progressive or field-
- based rendering, default 0 (off).
-
- Read Only Properties
-
- none
-
- Dependencies
-
- Mainconcept MPEG SDK
-
- Known Bugs
-
- none
-
- sdl
-
- Description
-
- Simple DirectMedia Layer audio and video output module.
-
- Constructor Argument
-
- string video_standard - "PAL" (default), "NTSC", or "WxH"
-
- Initialisation Properties
-
- int buffer - the number of frames to buffer, minimum 1, default 25.
- string rescale - a rescale method, see the Filters/rescale.
- - Hint: "none" works very good with SDL output.
-
- Mutable Properties
-
- double volume - audio level factor
- int video_off - if 1, disable video output
- int audio_off - if 1, disable audio output
- int resize - TODO
- int progressive - indicates whether to use progressive or field-
- based rendering, default 0 (off).
- int audio_buffer - size of the sdl audio buffer (default: 1024)
-
- Read Only Properties
-
- none
-
- Dependencies
-
- libSDL-1.2, libasound, libaudio, libXt, libX11, libXext, libSM, libICE
-
- Known Bugs
-
- none
-
- westley
-
- Description
-
- Serialise the service network to XML.
- See docs/westley.txt for more information.
-
- Constructor Argument
-
- resource - the name of a file in which to store the XML.
- - stdout is default.
-
- Initialisation Properties
-
- string resource - same as above.
-
- Dependencies
-
- libxml2
-
- Known Bugs
-
- Untested arbitrary nesting of multitracks and playlists.
- Property "id" is generated as service type followed by number if
- no property named "id" exists, but it fails to guarantee uniqueness.
+++ /dev/null
-Westley Documentation
-
-Copyright (C) 2004 Ushodaya Enterprised Limited
-Authors: Charles Yates <charles.yates@pandora.be>
-Last Revision: 2004-03-20
-
-
-WESTLEY
--------
-
-Preamble:
-
- Westley is the MLT projects XML serialisation/deserialisation format -
- as such, it closely mirrors the internal structure of the MLT API.
-
- If you just want to go straight to the DTD, then see
- mlt/src/modules/westley/westley.dtd, which gets installed at
- $(prefix)/share/mlt/modules/westley.dtd. Currently, the westley parser is
- non-validating.
-
-
-Introduction:
-
- A westley document is essentially a list of 'producers' - a producer is
- an mlt object which generates mlt frames (images and associated audio
- samples).
-
- There are 3 types of producer:
-
- * Basic Producers - these are typically file or device oriented feeds;
- * Playlists - these are arrangements of multiple producers;
- * Multitracks - these are the fx encapsulators.
-
- 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:
-
- As shall become apparent through the remainder of this document, the basic
- tenet of westley authoring is to organise the document in the following
- manner:
-
- 1) create producer elements for each unique media clip in the project;
- 2) create playlists for each track;
- 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.
-
-
-Basic Producers:
-
- The simplest westley document is:
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.dv</property>
- </producer>
- </westley>
-
- The westley wrapping is of course superfluous here - loading this document
- with MLT is identical to loading the clip directly.
-
- Of course, you can specify additional properties. For example, consider an
- MPEG file with multiple soundtracks - you could define a westley document to
- ensure that the second audio track is loaded:
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.mpeg</property>
- <property name="audio_track">1</property>
- </producer>
- </westley>
-
- NB: This relies on the mpeg being handled by the avformat producer, rather
- than the mcmpeg one. See services.txt for more details.
-
- A more useful example comes with the pango producer for a text producer.
-
- TODO: pango example...
-
- Notes:
-
- 1) It is better not to specify in/out points when defining basic producers
- as these can be specified in the playlists. The reasoning is that in/out
- restricts the amount of the clip available, and could lead to the same clip
- being loaded multiple times if you need different regions of the clip
- elsewhere;
- 2) A westley can be specified as a resource, so westleys can naturally
- encapsulate other westleys.
-
-
-Playlists:
-
- Playlists provide a 'collection' structure for producers. These can be used
- to define 'tracks' in the multitrack approach, or simple playlists for
- sequential, single track playout.
-
- As an example, the following defines two basic producers and a playlist with 3
- items:
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.dv</property>
- </producer>
- <producer id="producer1">
- <property name="resource">clip2.dv</property>
- </producer>
- <playlist id="playlist0">
- <entry producer="producer0" in="0" out="2999"/>
- <entry producer="producer1" in="0" out="999"/>
- <entry producer="producer0" in="3000" out="6999"/>
- </playlist>
- </westley>
-
- Here we see how the playlist defines the in/out points of the basic
- producers.
-
- Notes:
-
- 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 Multitracks:
-
- 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.
-
- Note that MLT doesn't see a filter or a transition as a producer in the
- normal sense - filters and transitions are passive when it comes to seeking.
- Internally, seeks are carried out on the producers. This is an important
- point - MLT does not follow a traditional graph oriented model.
-
- Visualising an MLT tractor and it's interaction with the consumer will
- assist here:
-
- +----------------------------------------------+
- |tractor |
- | +----------+ +-+ +-+ +-+ +-+ |
- | |multitrack| |f| |f| |t| |t| |
- | | +------+ | |i| |i| |r| |r| |
- | | |track0|-|--->|l|- ->|l|- ->|a|--->|a|\ |
- | | +------+ | |t| |t| |n| |n| \ |
- | | | |e| |e| |s| |s| \ |
- | | +------+ | |r| |r| |i| |i| \ | +--------+
- | | |track1|-|- ->|0|--->|1|--->|t|--->|t|-----|--->|consumer|
- | | +------+ | | | | | |i| |i| / | +--------+
- | | | | | | | |o| |o| / | ^
- | | +------+ | | | | | |n| |n| / | |
- | | |track2|-|- ->| |- ->| |--->|0|- ->|1|/ | |
- | | +------+ | | | | | | | | | | |
- | +----------+ +-+ +-+ +-+ +-+ | |
- +----------------------------------------------+ |
- ^ |
- | |
- +-----------+ |
- |APPLICATION|--------------------------------------------+
- +-----------+
-
- Internally, all frames from all tracks pass through all the filters and
- transitions - these are told which tracks to deal and which regions of the
- tracks to work on.
-
- Note that the application communicates with the producer - it can alter
- playback speed, position, or even which producer is connected to which
- consumer.
-
- 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
- application to allow the application to interpret key presses).
-
-
-Tractors:
-
- To create a multitrack westley, we can use two playlists and introduce a
- tractor. For the purposes of demonstration, I'll add a filter here too:
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.dv</property>
- </producer>
- <producer id="producer1">
- <property name="resource">clip2.dv</property>
- </producer>
- <playlist id="playlist0">
- <entry producer="producer0" in="0" out="2999"/>
- <blank length="1000"/>
- <entry producer="producer0" in="3000" out="6999"/>
- <playlist id="playlist1">
- <blank length="3000"/>
- <entry producer="producer1" in="0" out="999"/>
- </playlist>
- <tractor id="tractor0">
- <multitrack>
- <track producer="playlist0"/>
- <track producer="playlist1"/>
- </multitrack>
- <filter>
- <property name="track">0</property>
- <property name="mlt_service">greyscale</property>
- </filter>
- </tractor>
- </westley>
-
- Here we see that blank frames are inserted into the first playlist and a
- blank is provided at the beginning of the second - this can be visualised in
- the traditional timeline widget as follows:
-
- +-------+ +-------------+
- |a | |a |
- +-------+---+-------------+
- |b |
- +---+
-
- Adding the filter on the top track, gives us:
-
- +-------+ +-------------+
- |a | |a |
- +-------+---+-------------+
- |greyscale |
- --------+---+-------------+
- |b |
- +---+
-
- Note that it's only applied to the visible parts of the top track.
-
- The requirement to apply a filter to the output, as opposed to a specific
- track leads us to the final item in the Rules section above. As an example,
- let's assume we wish to watermark all output, then we could use the
- following:
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.dv</property>
- </producer>
- <producer id="producer1">
- <property name="resource">clip2.dv</property>
- </producer>
- <playlist id="playlist0">
- <entry producer="producer0" in="0" out="2999"/>
- <blank length="1000"/>
- <entry producer="producer0" in="3000" out="6999"/>
- <playlist id="playlist1">
- <blank length="3000"/>
- <entry producer="producer1" in="0" out="999"/>
- </playlist>
- <tractor id="tractor0">
- <multitrack>
- <track producer="playlist0"/>
- <track producer="playlist1"/>
- </multitrack>
- <filter>
- <property name="track">0</property>
- <property name="mlt_service">greyscale</property>
- </filter>
- </tractor>
- <tractor id="tractor1">
- <multitrack>
- <track producer="tractor0"/>
- </multitrack>
- <filter>
- <property name="mlt_service">watermark</property>
- <property name="resource">watermark1.png</property>
- </filter>
- </tractor>
- </westley>
-
- Here we employ another tractor and we define a single track (being the
- tractor we previously defined) and apply a watermarking filter there.
-
- This is simply provided as an example - the watermarking functionality could
- be better handled at the playout stage itself (ie: as a filter automatically
- placed between all producers and the consumer).
-
- Tracks act like "layers" in an image processing program like the GIMP. The
- bottom-most track takes highest priority and higher layers are overlays
- and do not appear unless there are gaps in the lower layers or unless
- a transition is applied that merges the tracks on the specifed region.
- Practically speaking, for A/B video editing it does not mean too much,
- and it will work as expected; however, as a general rule apply any CGI
- (graphic overlays with pixbuf or titles with pango) on tracks higher than
- your video tracks. Also, this means that any audio-only tracks that are
- lower than your video tracks will play rather than the audio from the video
- clip. Remember, nothing is affected like mixing or compositing until one
- applies a transition or appropriate filter.
-
- <westley>
- <producer id="producer0">
- <property name="resource">clip1.dv</property>
- </producer>
- <playlist id="playlist0">
- <entry producer="producer0"/>
- </playlist>
- <producer id="producer1">
- <property name="resource">clip2.mpeg</property>
- </producer>
- <playlist id="playlist1">
- <blank length="50"/>
- <entry producer="producer1"/>
- </playlist>
- <tractor id="tractor0" in="0" out="315">
- <multitrack id="multitrack0">
- <track producer="playlist0"/>
- <track producer="playlist1"/>
- </multitrack>
- <transition id="transition0" in="50" out="74">
- <property name="a_track">0</property>
- <property name="b_track">1</property>
- <property name="mlt_service">luma</property>
- </transition>
- <transition id="transition1" in="50" out="74">
- <property name="a_track">0</property>
- <property name="b_track">1</property>
- <property name="mlt_service">mix</property>
- <property name="start">0.0</property>
- <property name="end">1.0</property>
- </transition>
- </tractor>
- </westley>
-
- A "luma" transition is a video wipe processor that takes a greyscale bitmap
- for the wipe definition. When one does not specify a bitmap, luma performs
- a dissolve. The "mix" transition does an audio mix, but it interpolates
- between the gain scaling factors between the start and end properties -
- in this example, from 0.0 (none of track B) to 1.0 (all of track B).
- Because the bottom track starts out with a gap specified using the <blank>
- element, the upper track appears during the blank segment. See the demos and
- services.txt to get an idea of the capabilities of the included transitions.
-
-Flexibility:
-
- The information presented above is considered the MLT Westley "normal"
- form. This is the output generated by the westley consumer, for example,
- when used with inigo. It is the output generated when you use the
- "Westley to File" consumer in the demo script, which beginners will find
- most useful for learning to use westley XML. This section describes
- alternative forms the westley producer accepts.
-
- First of all, the normal form is more of a linear format with producers
- and playlists defined prior to their usage in a multitrack. Westley
- also accepts a hierarchical format with producers as children of tracks
- or playlist entries and with playlists as children of tracks:
-
- <westley>
- <tractor>
- <multitrack>
- <track>
- <playlist>
- <entry>
- <producer>
- <property name="resource">clip1.dv</property>
- </producer>
- </entry>
- </playlist>
- </track>
- </multitrack>
- </tractor>
- </westley>
-
- Obviously, this example is meant to demonstrate hierarchy and not effective
- use of playlist or multitrack!
-
- Secondly, as part of error handling, westley is forgiving if you fail to
- supply <tractor>, <track>, and <entry> where one can be understood. This
- affords an abbreviated syntax that is less verbose and perhaps less
- intimidating for a human to read and understand. One can simplify the
- above example as:
-
- <westley>
- <multitrack>
- <playlist>
- <producer>
- <property name="resource">clip1.dv</property>
- </producer>
- </playlist>
- </multitrack>
- </westley>
-
- Yes, filters and transitions can be added to the above example after the
- closing multitrack tag (</multitrack>) because it is still enclosed within
- the westley body tags.
-
- If you specify in and out on a producer and it has been enclosed within
- an <entry> or <playlist>, then the edit points apply to the playlist
- entry and not to the producer itself. This facilitates re-use of media:
-
- <playlist>
- <producer id="clip1" in="25" out="78">
- <property name="resource">clip1.dv</property>
- </producer>
- <entry producer="clip1" in="119" out="347"/>
- </playlist>
-
- In the above example, the producer attribute of the entry element is
- a reference to the preceding producer. All references must follow the
- definition. The edit points supplied on the producer above will not affect
- the entry that references it below because westley knows the clip is a
- playlist entry and optimises this situation. The advantage is that one
- does not need to determine every clip to be included ahead of time
- and specify them outside the context of the mutlitrack timeline.
-
- This form of authoring will be easier for many to visualise as a non-linear
- editor's timeline. Here is a more complex example:
-
- <westley>
- <multitrack>
- <playlist>
- <producer id="foo" in="100" out="149">
- <property name="resource">clip2.mpeg</property>
- </producer>
- <blank length="25"/>
- <entry producer="foo" in="10" out="59"/>
- </playlist>
- <playlist>
- <blank length="25"/>
- <producer id="bar" in="100" out="199">
- <property name="resource">clip3.mpeg</property>
- </producer>
- <entry out="99" producer="bar"/>
- </playlist>
- </multitrack>
- <filter mlt_service="greyscale" track="0"/>
- <transition mlt_service="luma" in="25" out="49" a_track="0" b_track="1"/>
- <transition mlt_service="luma" in="75" out="99" a_track="0" b_track="1">
- <property name="reverse" value="1"/>
- </transition>
- </westley>
-
- Did you notice something different in the last example? Properties can be
- expressed using XML attributes on the element as well. However, only
- non-service-specific properties are supported in this way. For example,
- "mlt_service" is available to any producer, filter, or transition. However,
- "resource" is actually service-specific. Notice the syntax of the last
- property, on the last transition. Westley accepts property values using
- the "value" attribute as well as using element text.
-
- We have seen a few different ways of expressing property values. There are
- a couple more for properties that can accept XML data. For example, the
- GDK pixbuf producer with librsvg can handle embedded SVG, and the Pango
- producer can handle embedded Pango markup. You can enclose the embedded XML
- using a CDATA section:
-
- <property name="resource"><![CDATA[ <svg>...</svg> ]]></property>
-
- Please ensure the opening CDATA tag immediately follows the opening
- property tag and that the section closing tag immediately precedes the
- closing property tag.
-
- However, westley can also accept inline embedded XML:
-
- <property name="resource">
- <svg>
- </svg>
- </property>
-
- Currently, there is no namespace handling so a conflict will occur only on
- any embedded XML that contains an element named "property" because
- westley collects embedded XML until it reaches a closing property tag.
-
-
-Entities and Parameterisation:
-
- The westley producer parser supports XML entities. An example:
-
- <?xml version="1.0"?>
- <!DOCTYPE westley [
- <!ENTITY msg "Hello world!">
- ]>
- <westley>
- <producer id="producer0">
- <property name="mlt_service">pango</property>
- <property name="text">&msg;</property>
- </producer>
- </westley>
-
- If you are embedding another XML document into a property value not using
- a CNODE section, then any DOCTYPE section must be relocated before any of
- the xml elements to be well-formed. See demo/svg.westley for an example.
-
- Entities can be used to parameterise westley! Using the above example, the
- entity declared serves as the default value for &msg;. The entity content
- can be overridden from the resource property supplied to the westley
- producer. The syntax is the familiar, url-encoded query string used with
- HTTP, e.g.: file?name=value&name=value...
-
- There are a couple of rules of usage. The Miracle LOAD command and inigo
- command line tool require you to preface the URL with "westley:" because
- the query string destroys the filename extension matching peformed by
- Fezzik. Also, inigo looks for '=' to tokenise property settings. Therefore,
- one uses ':' between name and value instead of '='. Finally, since inigo
- is run from the shell, one must enclose the URL within single quotes to
- prevent shell filename expansion, or similar.
-
- Needless to say, the ability to parameterise westley XML compositions is
- an extremely powerful tool. An example for you to play with is available in
- demo/entity.westley. Try overriding the name from inigo:
- inigo 'westley:entity.westley?name:Charlie'
-
- Technically, the entity declaration is not needed in the head of the XML
- document if you always supply the parameter. However, you run the risk
- of unpredictable behviour without one. Therefore, it is safest and a best
- practice to always supply an entity declaration. It is improves the
- readability as one does not need to search for the entity references to
- see what parameters are available.
-
-
-Tips and Technique:
-
- If one finds the above hierarchical, abbreviated format intuitive,
- start with a simple template and fill and extend as needed:
- <westley>
- <multitrack>
- <playlist>
- </playlist>
- ...add a playlist for each track...
- </multitrack>
- ...add filters and transitions...
- </westley>
-
- By using a playlist for each track, it is easier to iteratively add new
- clips and blank regions as you develop the project. You will not have to
- use <track> or later add <playlist> when necessary.
-
- A more advanced template that allows sequencing multitracks is:
- <playlist>
- <entry>
- <multitrack>
- <playlist>
- </playlist>
- ...add a playlist for each track...
- </multitrack>
- ...add filters and transitions...
- </entry>
-
- <entry>
- <multitrack>
- <playlist>
- </playlist>
- ...add a playlist for each track...
- </multitrack>
- ...add filters and transitions...
- </entry>
- </playlist>
-
- If you end up making a collection of templates for various situations, then
- consider using XML Entities to make the template more effective by moving
- anything that should parameterised into an entity.
-
- If you want to have a silent, black background for audio and video fades,
- then make the top track simply <producer mlt_service="colour"/>. Then,
- use composite and volume effects. See the "Fade from/to black/silence"
- demo for an example (demo/mlt_fade_black).
-
- If you apply the reverse=1 property to a transition like "luma," then
- be careful because it also inherently swaps the roles of A and B tracks.
- Therefore, you need to might need to swap the a_track and b_track values
- if it did not turn out the way you expected. See the "Clock in and out"
- for an example (demo/mlt_clock_in_and_out).
+++ /dev/null
-MLT++ was developed by:
-Charles Yates <charles.yates@pandora.be>
-
-MLT++ is maintained by:
-Dan Dennedy <dan@dennedy.org>
+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-\f
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-\f
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-\f
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-\f
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
+++ /dev/null
-2009-04-10 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * test/play.cpp, test/server.cpp: cleanup some warnings
-
- * src/MltResponse.cpp, src/MltResponse.h: const update for MltResponse
-
- * src/MltResponse.cpp, src/MltResponse.h: Constness changes
-
- * src/MltTransition.cpp, src/MltTransition.h: Constness changes
-
- * src/MltProducer.cpp, src/MltProducer.h: Constness changes
-
- * src/MltProperties.cpp, src/MltProperties.h: Constness changes
-
- * src/MltConsumer.cpp, src/MltConsumer.h: Constness changes
-
- * src/MltProperties.cpp, src/MltResponse.cpp: Constness changes
-
- * src/MltProperties.cpp, src/MltPushConsumer.cpp: Constness changes
-
- * src/MltFilter.cpp, src/MltFilter.h, src/MltProperties.cpp,
- src/MltProperties.h: Constness changes
-
- * src/MltConsumer.cpp, src/MltField.cpp, src/MltFilter.cpp, src/MltFrame.cpp,
- src/MltMultitrack.cpp, src/MltPlaylist.cpp, src/MltProducer.cpp,
- src/MltTractor.cpp, src/MltTransition.cpp: Fix up warnings about explicit
- base initializers in copy constructors
-
- * configure: Add more warnings
-
- * .gitignore: Add a .gitignore file
-
-2009-04-02 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/ruby/thumbs.rb: thumbs.rb: fix setting size property for avformat
- consumer
-
-2009-02-04 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * debian/changelog, debian/control, debian/copyright, debian/rules: remove
- debian package subdirectory (they provide their own)
-
-2009-01-26 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/configure, swig/php/build, swig/php/play.php: swig/configure,
- swig/php/*: add php bindings
-
-2008-12-28 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/java/build, swig/python/build, swig/python/play.py, swig/tcl/build:
- swig/{java,python,tcl}/build: fix linking error __stack_chk_fail_local.
- swig/python/play.py: fix syntax error reported by Jonathon Thomas.
-
-2008-12-27 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/configure: swig/configure: use pkg-config mlt-framework instead of
- deprecated mlt-config.
-
-2008-12-04 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * README: README: update instructions to use pkg-config instead of mlt-config
-
- * swig/java/build, swig/perl/Makefile.PL, swig/python/build, swig/ruby/build,
- swig/tcl/build, test/Makefile: test/Makefile, swig/*/build: replace more
- mlt-config with pkg-config
-
-2008-11-06 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile: src/Makefile: suppress warning on ldconfig failure
-
-2008-10-25 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure: configure: apply patch from Alberto Villa to fix build on
- FreeBSD
-
-2008-10-20 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure: configure: convert to use pkg-config; mlt-config is deprecated
-
-2008-08-06 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * AUTHORS: update mlt++ AUTHORS
-
- * Makefile: fix make dist target
-
- * configure: bump versions for 0.3.0 release
-
- * Makefile: improve make dist target
-
- * swig/java/Play.java, swig/java/Play.sh, swig/java/build: swig/java: fixup
- the java bindings build script and example (bug 1523941)
-
-2008-06-26 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProducer.cpp, src/MltProducer.h, swig/mltpp.i: MltProducer.{h,cpp},
- mltpp.i: remove Producer::get_frame that is unncessary and introduced a
- memory leak.
-
-2008-06-24 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp: MltPlaylist.cpp: return null on clip_info method if
- mlt_playlist_get_clip_info fails.
-
-2008-06-08 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp: MltPlaylist.cpp: prevent strdup from crashing on a
- null pointer.
-
-2008-04-23 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProducer.cpp, src/MltProducer.h, swig/mltpp.i: MltProducer.{h,cpp},
- swig/mltpp.i: add method Producer::get_frame.
-
-2008-04-12 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * test/server.cpp: test/server.cpp: bugfix (1940389) compilation on gcc 4.3
-
-2008-02-27 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltRepository.cpp, src/MltRepository.h: MltRepository.{h,cpp}: update
- to latest mlt_repository.h change - finalization of callback declarations and
- metadata handling
-
-2008-02-16 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/python/build: swig/python/build: add -fPIC
-
- * src/MltRepository.cpp, src/MltRepository.h, swig/mltpp.i:
- MltRepository.{h,cpp}, swig/mltpp.i: added consumers, filters, producers,
- transitions, register_metadata, and metadata methods to Repository class
-
-2008-02-12 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * Makefile: do not make tests automatically
-
-2008-02-07 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure, src/Makefile: configure: add soversion variable src/Makefile:
- improve library versioning by linking on interface version (soversion)
-
- * swig/ruby/thumbs.rb: thumbs.rb: fix error on Playlist.append due to args
- not int
-
- * src/Makefile, src/Mlt.h, src/MltFactory.cpp, src/MltFactory.h,
- src/MltRepository.cpp, src/MltRepository.h, swig/mltpp.i: Mlt.h,
- MltFactory.{h,cpp}, MltRepository.{h,cpp}, swig/mltpp.i: update to deal with
- changes and new capabilities in mlt_factory and mlt_repository.
-
-2008-02-04 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * COPYING: add COPYING to disclose license
-
-2008-02-02 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltConsumer.cpp, src/MltConsumer.h,
- src/MltFactory.cpp, src/MltFactory.h, src/MltFilter.cpp, src/MltFilter.h,
- src/MltFilteredConsumer.cpp, src/MltFilteredConsumer.h,
- src/MltFilteredProducer.cpp, src/MltFilteredProducer.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProfile.cpp, src/MltProfile.h,
- src/MltPushConsumer.cpp, src/MltPushConsumer.h, src/MltService.cpp,
- src/MltService.h, src/MltTractor.cpp, src/MltTractor.h,
- src/MltTransition.cpp, src/MltTransition.h, swig/mltpp.i, swig/perl/play.pl,
- swig/python/play.py, swig/ruby/miracle.rb, swig/ruby/play.rb,
- swig/ruby/thumbs.rb, swig/tcl/play.tcl, test/play.cpp, test/server.cpp: add
- MltProfile and update examples
-
-2007-06-12 ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * Makefile: added dist make targets
-
- * Makefile, src/Makefile, test/Makefile: added uninstall make targets
-
-2006-03-20 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltFactory.h: + Fix for swig parsing
-
-2006-02-23 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile: + Install of config.h for linux and os/x usage
-
- * src/config.h: + Added the config.h for win32
-
- * mlt++.sln, mlt++.vcproj, src/Mlt.h, src/MltConsumer.h, src/MltDeque.h,
- src/MltEvent.h, src/MltFactory.cpp, src/MltFactory.h, src/MltField.h,
- src/MltFilter.h, src/MltFilteredConsumer.h, src/MltFilteredProducer.h,
- src/MltFrame.cpp, src/MltFrame.h, src/MltGeometry.h, src/MltMultitrack.h,
- src/MltParser.h, src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltProperties.h,
- src/MltPushConsumer.h, src/MltService.h, src/MltTokeniser.h,
- src/MltTractor.h, src/MltTransition.h: + Win32 port - dev studio is required
- to avoid issues with C++ ABI compatibility + Fix for image render in NTSC
- NB: mlt patch to follow (this one isn't much use without it :-)) - mlt build
- is purely mingw32 of course
-
-2005-12-05 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure, src/Makefile: + Fix for Darwin and soname logic
-
- * debian/changelog, debian/control, debian/copyright, debian/rules: +
- Functional debian build rules
-
- * Makefile, configure, src/Makefile, test/Makefile: + MLT++ updates for 0.2.1
- - distclean corrected, soname usage in linking
-
-2005-11-29 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * Makefile, configure: + Correction to a typo
-
- * swig/perl/Makefile.PL: + Perl compilation patch submitted by Torsten
- Spindler
-
- * configure, src/Makefile: + Added a --libdir switch to the configure and
- build and fixed test case compilation
-
-2005-11-22 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure: + Allow LDFLAGS to be inherited from the environment
-
-2005-11-21 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile: + Creates the lib directory on an install
-
-2005-11-10 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * Makefile, src/Makefile: + DESTDIR patch from Anthony Green (green at redhat
- dot com) - many thanks :-)
-
-2005-10-03 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProperties.cpp, src/MltProperties.h: OS/X gcc/g++ 4.x fix
-
- * configure, src/Makefile, src/MltProperties.cpp, src/MltProperties.h,
- test/Makefile: + Whoops - had forgotten these OS/X patches...
-
-2005-09-29 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPushConsumer.cpp: + Oops - fix for memory leak
-
-2005-09-28 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltPushConsumer.cpp, src/MltPushConsumer.h: +
- Added a push based consumer wrapper
-
-2005-07-26 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/Makefile, swig/configure, swig/perl/Makefile.PL, swig/python/build,
- swig/tcl/build: + Cleaned up swig build so it doesn't require an mlt++
- install first - Temporarily disabled java
-
-2005-06-27 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * CUSTOMISING, test/server.cpp: CUSTOMISING + Replaced TBD for frame
- rendering notification event test/server.cpp + Added an example frame
- rendering callback that removes all shotcut related fx
-
-2005-06-26 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * CUSTOMISING, swig/ruby/thumbs.rb: CUSTOMISING + Added an example of how to
- hide a track on reception swig/ruby/thumbs.rb + Changed generator to run,
- rather than sleep and poll
-
-2005-04-12 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * CUSTOMISING: Minor doc updates
-
-2005-03-16 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * CUSTOMISING, src/MltProperties.cpp, src/MltProperties.h,
- src/MltResponse.cpp, src/MltResponse.h, test/server.cpp: Server customisation
-
-
-2005-02-12 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltService.cpp: Minor correction
-
-2005-01-14 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProperties.cpp, src/MltProperties.h: Const string usage in
- properties
-
-2005-01-03 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltGeometry.cpp, src/MltGeometry.h: Next/Prev key extraction
-
- * src/MltMiracle.cpp, src/MltMiracle.h, swig/mltpp.i: Fetch unit from miracle
- server
-
-2004-12-31 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltGeometry.h: Update for geometry
-
-2004-12-24 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltGeometry.cpp, src/MltGeometry.h,
- swig/mltpp.i: Geometry
-
-2004-12-12 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h: blank_at method added
-
-2004-12-11 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h: split_at method added
-
-2004-12-09 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltTractor.cpp, src/MltTractor.h: Tractor constructor modifications
-
-2004-11-25 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/Makefile: Install makefile for swig
-
- * src/Makefile, src/Mlt.h, src/MltDeque.cpp, src/MltDeque.h,
- src/MltFactory.cpp, src/MltFactory.h, src/MltProducer.cpp, src/MltProducer.h,
- src/MltTransition.cpp, src/MltTransition.h: Deque added; simplified producer
- parent access; transition in and out
-
-2004-11-22 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltService.cpp,
- src/MltService.h, test/Makefile: More playlist modifications; service locking
-
-
-2004-11-17 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProperties.cpp, src/MltProperties.h, src/MltTractor.cpp,
- src/MltTractor.h: Ref count and event firing method on properties; locate_cut
- on tractor
-
-2004-11-11 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltProperties.h,
- src/MltTractor.cpp, src/MltTractor.h: Playlist reorganisation
-
-2004-11-07 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltTractor.cpp,
- src/MltTractor.h: Simplified playlist and track access
-
-2004-11-05 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProducer.cpp, src/MltProducer.h: Added cut related methods
-
-2004-10-31 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltTokeniser.cpp, src/MltTokeniser.h,
- test/server.cpp: Added courtesy tokenising class
-
-2004-10-27 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * configure, swig/configure, swig/ruby/build, swig/ruby/miracle.rb: Config
- changes
-
-2004-10-17 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltMiracle.cpp, src/MltMiracle.h: id and log level for server
-
- * src/MltMiracle.cpp: Server shutdown state
-
-2004-10-14 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltConsumer.cpp, src/MltConsumer.h, test/play.cpp: buffer fix and
- tractor handling
-
- * HOWTO: Doc updates
-
- * src/MltMiracle.cpp, src/MltMiracle.h: Improved push capabilities
-
-2004-10-08 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProducer.cpp, src/MltProducer.h: Same and following clip
- identification
-
-2004-10-05 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltFrame.cpp, src/MltFrame.h,
- src/MltParser.cpp, src/MltParser.h, src/MltService.cpp, src/MltService.h,
- swig/mltpp.i: Added the parser object and moved type identity into mlt
-
-2004-09-29 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, swig/mltpp.i: new mix related
- methods
-
-2004-09-26 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * README, src/MltPlaylist.cpp, src/MltPlaylist.h: Playlist repeat clip
- functionality
-
-2004-09-24 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltProducer.cpp, src/MltProducer.h, swig/mltpp.i: Cut management part 1
-
-
-2004-09-23 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltService.cpp, swig/mltpp.i: get_frame and ruby listen fix
-
-2004-09-22 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltFrame.cpp, src/MltProperties.cpp, src/MltProperties.h, swig/mltpp.i:
- Event and frame handling
-
- * configure, src/MltMiracle.cpp: Server shutdown
-
-2004-09-19 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltMiracle.cpp, src/MltMiracle.h,
- src/MltResponse.cpp, src/MltResponse.h, swig/mltpp.i: Added the response
- object
-
- * HOWTO, src/Makefile, src/Mlt.h, src/MltMiracle.cpp, src/MltMiracle.h,
- swig/mltpp.i, swig/ruby/miracle.rb, test/Makefile, test/play.cpp,
- test/server.cpp: Adding miracle
-
-2004-09-09 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h: Adding the mix part 1
-
-2004-09-06 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltFilteredConsumer.cpp, src/MltFilteredConsumer.h,
- src/MltProducer.cpp, src/MltProducer.h, src/MltService.cpp, src/MltService.h,
- swig/mltpp.i: Service attach filters
-
-2004-09-03 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * HOWTO, src/MltProperties.cpp, src/MltProperties.h, swig/mltpp.i,
- swig/perl/play.pl: More event stuff
-
-2004-09-02 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltEvent.cpp, src/MltEvent.h,
- src/MltProperties.cpp, src/MltProperties.h, swig/mltpp.i, swig/ruby/play.rb,
- test/play.cpp: Event modifications
-
-2004-08-31 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * HOWTO, src/Makefile, src/MltConsumer.cpp, src/MltConsumer.h,
- src/MltFilter.cpp, src/MltFilter.h, src/MltFrame.cpp, src/MltFrame.h,
- src/MltMultitrack.cpp, src/MltMultitrack.h, src/MltPlaylist.cpp,
- src/MltPlaylist.h, src/MltProducer.cpp, src/MltProducer.h,
- src/MltService.cpp, src/MltService.h, src/MltTractor.cpp, src/MltTractor.h,
- src/MltTransition.cpp, src/MltTransition.h: Run time type identification
-
-2004-08-28 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * README, src/MltMultitrack.cpp, src/MltMultitrack.h, src/MltTractor.cpp,
- src/MltTractor.h, swig/mltpp.i: Tractor enhancements
-
- * src/Makefile, src/Mlt.h, src/MltField.cpp, src/MltField.h,
- src/MltMultitrack.cpp, src/MltMultitrack.h, src/MltTractor.cpp,
- src/MltTractor.h, swig/mltpp.i: Multitrack classes added
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, swig/mltpp.i: Producer filter extraction method
-
-2004-08-27 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/Mlt.h, src/MltFilteredProducer.cpp,
- src/MltFilteredProducer.h, src/MltProducer.cpp, src/MltProducer.h,
- src/MltService.cpp, src/MltService.h, swig/mltpp.i: Removed FilteredProducer
-
-2004-08-26 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * Makefile, test/Makefile, test/play.cpp: Build modifications
-
- * src/MltConsumer.cpp, src/MltConsumer.h, src/MltFilter.cpp, src/MltFilter.h,
- src/MltFilteredConsumer.cpp, src/MltFilteredConsumer.h, src/MltFrame.cpp,
- src/MltFrame.h, src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltProperties.h,
- src/MltService.cpp, src/MltService.h, src/MltTransition.cpp,
- src/MltTransition.h, swig/perl/play.pl: Mlt Ref Counts and Playlist
- split/join
-
-2004-08-23 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/perl/play.pl: Added play.pl
-
- * src/Makefile, swig/mltpp.i: Workaround for perl
-
-2004-08-21 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltConsumer.cpp, src/MltFilter.cpp, src/MltProperties.cpp,
- src/MltProperties.h, src/MltTransition.cpp: Constructor clean up
-
- * src/MltConsumer.cpp, src/MltConsumer.h: consumer purge
-
-2004-08-20 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltFilter.cpp, src/MltFilter.h, src/MltPlaylist.cpp, src/MltPlaylist.h,
- swig/configure, swig/java/build, swig/ruby/build, swig/ruby/thumbs.rb:
- mlt_position, /usr/bin/env and Instance fix
-
-2004-08-18 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/MltFrame.cpp, src/MltFrame.h, src/MltProducer.cpp, src/MltProducer.h,
- src/MltService.cpp, swig/mltpp.i, swig/ruby/play.rb: image handling
-
-2004-08-17 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/java/Play.java, swig/ruby/play.rb, swig/ruby/thumbs.rb: Fixes for mods
- to api
-
- * src/Makefile, src/Mlt.h, src/MltConsumer.cpp, src/MltConsumer.h,
- src/MltFilteredConsumer.cpp, src/MltFilteredConsumer.h,
- src/MltFilteredProducer.cpp, src/MltFilteredProducer.h, src/MltService.cpp,
- src/MltService.h, swig/mltpp.i: Filtered producers and consumers
-
- * test/play.cpp: oops
-
-2004-08-16 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * swig/configure, swig/java/Play.java, swig/java/Play.sh, swig/java/build,
- swig/mltpp.i, swig/perl/Makefile.PL, swig/perl/build, swig/python/build,
- swig/python/play.py, swig/ruby/build, swig/ruby/play.rb, swig/ruby/thumbs.rb,
- swig/tcl/build, swig/tcl/play.tcl: Experimental swig bindings
-
- * README, src/MltFactory.cpp, src/MltFactory.h, src/MltFilter.cpp,
- src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProperties.cpp, src/MltProperties.h, src/MltService.cpp,
- src/MltService.h, src/MltTransition.cpp, test/Makefile: More cleanups
-
- * README, src/MltConsumer.cpp, src/MltConsumer.h, src/MltFactory.cpp,
- src/MltFactory.h, src/MltFilter.cpp, src/MltFilter.h, src/MltFrame.cpp,
- src/MltFrame.h, src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltProperties.h,
- src/MltService.cpp, src/MltService.h, src/MltTransition.cpp,
- src/MltTransition.h, test/play.cpp: Class rework and simplification
-
- * src/Makefile, src/Mlt.h: Added Mlt.h convenience header
-
- * src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProperties.cpp,
- src/MltProperties.h, src/MltService.cpp: Complete methods for properties and
- playlist; reversed NULL handling on service class
-
- * README, src/MltProperties.cpp, src/MltProperties.h, test/play.cpp: Object
- validity checks
-
- * AUTHORS, Makefile, README, configure, src/Makefile, src/MltService.cpp,
- test/play.cpp: Build and docs modifications
-
-2004-08-15 lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
- * src/Makefile, src/MltConsumer.cpp, src/MltConsumer.h, src/MltFactory.cpp,
- src/MltFactory.h, src/MltFilter.cpp, src/MltFilter.h, src/MltFrame.cpp,
- src/MltFrame.h, src/MltPlaylist.cpp, src/MltPlaylist.h, src/MltProducer.cpp,
- src/MltProducer.h, src/MltProperties.cpp, src/MltProperties.h,
- src/MltService.cpp, src/MltService.h, src/MltTransition.cpp,
- src/MltTransition.h, test/Makefile, test/play.cpp: Initial revision
+++ /dev/null
-INTRODUCTION
-------------
-
- This document provides a brief tutorial on the use of the mlt++ wrapper
- and bindings.
-
-
-Hello World
------------
-
- The mlt++ wrapper is a c++ wrapper for the mlt C library. As such, it
- provides clean C++ access to the underlying library.
-
- An example of use is as follows:
-
- #include <mlt++/Mlt.h>
- using namespace Mlt;
-
- int main( void )
- {
- Factory::init( );
- Producer p( "pango:", "Hello World" );
- Consumer c( "sdl" );
- c.connect( p );
- c.run( );
- return 0;
- }
-
- This is a fairly typical example of mlt++ usage - create a 'producer' (an
- object which produces 'frames'), create a 'consumer' (an object which consumes
- frames), connect them together, start the consumer and wait until done (here
- we just wait for the user to close the window).
-
- In this case, we construct a window as a consumer using the 'sdl' consumer
- (SDL is a standard portable library which provides platform independent
- access to accelerated video display and audio) and use the 'pango'
- producer to generate frames with the words 'Hello World' (pango is a
- library from the gtk toolkit).
-
- The main point of this example is to show that mlt uses existing libraries
- to provide its functionality - this keeps the framework itself very small.
-
- Note that mlt is designed to be housed in GUI or server type applications -
- typically, applications don't wait around for the consumer to be stopped in
- the manner shown.
-
- So far, we've introduced the Producer and Consumer mlt classes. We'll cover
- each of these in more detail later in the tutorial, but for now, we'll
- briefly cover the remaining classes.
-
-
-Playlists
----------
-
- Another simple class is the Playlist - this is direct extension of Producer
- and it allows you to maintain a list of producer objects.
-
- As a simple example of the Playlist in action, we'll convert the example
- above into an application which plays multiple video or audio files.
-
- #include <mlt++/Mlt.h>
- using namespace Mlt;
-
- int main( int argc, char **argv )
- {
- Factory::init( );
- Playlist list;
- for ( int i = 1; i < argc; i ++ )
- {
- Producer p( argv[i] );
- if ( p.is_valid( ) )
- list.append( p );
- }
- Consumer c( "sdl" );
- c.connect( list );
- c.run( );
- return 0;
- }
-
- Now you can run the program as:
-
- ./player *.avi *.mp3 *.jpg etc
-
- In this case, we construct a playlist by simply appending producers to it.
- Notice that although the scope of the Producer is limited to the inner
- for loop, we can safely add it to the playlist - this is due to the fact
- that all mlt objects maintain reference counts and no object is really
- destroyed until all the references are gone. In this case, when the list
- object goes out of scope, all the producers we created will automatically
- be destroyed.
-
-
-Filters
--------
-
- So far, we've shown how you can load and play media. We've given a brief
- intro to the Playlist container, now it's time to start manipulating
- things...
-
- For the next example, I'll add a 'watermark' to the video - a watermark
- is used by broadcasters to brand the channel and normally consists of a
- logo of some sort. We'll just use some black text on a partially
- transparent red background.
-
- #include <mlt++/Mlt.h>
- using namespace Mlt;
-
- int main( int argc, char **argv )
- {
- Factory::init( );
- Playlist list;
- for ( int i = 1; i < argc; i ++ )
- {
- Producer p( argv[i] );
- if ( p.is_valid( ) )
- list.append( p );
- }
- Filter f( "watermark", "pango:" );
- f.set( "producer.text", "MLT++" );
- f.set( "producer.fgcolour", "0x000000ff" );
- f.set( "producer.bgcolour", "0xff000080" );
- list.attach( f );
- Consumer c( "sdl" );
- c.connect( list );
- c.run( );
- return 0;
- }
-
- Notice that the watermark filter reuses the 'pango' producer we showed in the
- first example. In fact, you could use any producer here - if you wanted to
- use a graphic or a video, you would just construct the filter with a full path
- to that as the second argument.
-
- We manipulate the filter using the set method - this method was also shown
- in the first example.
-
- Finally, we attach the filter to the playlist. This ensure that all frames
- that are obtained from the playlist are watermarked.
-
-
-Cuts
-----
-
- When you add a clip to a playlist, the a cut object is created - this is merely a
- wrapper for the producer, spanning the specified in and out points.
-
- Whenever you retrieve a clip from a playlist, you will always get a cut object.
- This allows you to attach filters to a specific part of a producer and should
- the position of the cut in the playlist change, then the filter will remain
- correctly associated to it.
-
- A producer and a cut are generally identical in behaviour, but should you need to
- distinguish between them, you can use:
-
- if ( producer.is_cut( ) )
-
- and to retrieve the parent of a cut, you can use:
-
- Producer parent = producer.parent_cut( );
-
- Filters that are attached directly to a parent are executed before any filters
- attached to the cut.
-
-
-Tractor
--------
-
- A tractor is an object that allows the manipulation of multiple video and audio
- tracks.
-
- Stepping away from the player example we've been tinkering with for a minute,
- let's assume we want to do something like dub a video with some audio. This
- a very trivial thing to do:
-
- Tractor *dub( char *video_file, char *audio_file )
- {
- Tractor *tractor = new Tractor( );
- Producer video( video_file );
- Producer audio( audio_file );
- tractor->set_track( video, 0 );
- tractor->set_track( audio, 1 );
- return tractor;
- }
-
- That's all that needs to be done - you can now connect the returned object to a
- consumer, or add it to a playlist, or even apply it as a track to another tractor.
-
-
-Transition
-----------
-
- Let's now assume we want to mix the audio between two tracks - to do this, we
- need to introduce the concept of a transition. A transition in mlt is a service
- which combines frames from two producers to produce a new frame.
-
- Tractor *mix( char *video_file, char *audio_file )
- {
- Tractor *tractor = new Tractor( );
- Transition mix( "mix" );
- Producer video( video_file );
- Producer audio( audio_file );
- tractor.set_track( video, 0 );
- tractor.set_track( audio, 1 );
- tractor.field.plant_transition( mix, 0, 1 );
- return tractor;
- }
-
- The tractor returned will now mix the audio from the original video and the
- audio.
-
-
-Mix
----
-
- There is a convenience function which simplifies the process of applying
- transitions betwee adjacent cuts on a playlist. This is often preferable
- to use over the constuction of your own tractor and transition set up.
-
- To apply a 25 frame luma transition between the first and second cut on
- the playlist, you could use:
-
- Transition luma;
- playlist.mix( 0, 25, luma );
-
-
-Events
-------
-
- Typically, applications need to be informed when changes occur in an mlt++ object.
- This facilitates application services such as undo/redo management, or project
- rendering in a timeline type widget and many other types of operations which an
- application needs.
-
- As an example, consider the following:
-
- class Westley
- {
- private:
- Consumer consumer;
- Tractor &tractor;
- public:
- Westley( MltTractor &tractor ) :
- tractor( tractor ),
- consumer( "westley" )
- {
- consumer.connect( tractor );
- tractor.listen( tractor, "producer-changed",
- ( mlt_listener )Westley::listener );
- }
-
- static void listener( Properties *tractor, Westley *object )
- {
- object->activate( );
- }
-
- void activate( )
- {
- consumer.start( );
- }
- };
-
- Now, each time the tractor is changed, the westley representation is output to
- stderr.
-
-
-Servers and Westley Docs
-------------------------
-
- One of the key features of MLT is its server capabilities. This feature
- allows you to pass westley documents seamlessly from one process to
- another and even to different computers on your network.
-
- The miracle playout server is one such example of an application which
- uses this functionality - you can build your own servers into your own
- processes with ease.
-
- A server process would be running as follows:
-
- #include <mlt++/Miracle>
- using namespace Mlt;
-
- int main( void )
- {
- Miracle miracle( "miracle", 5250 );
- miracle.start( );
- miracle.execute( "uadd sdl" );
- miracle.execute( "play u0" );
- miracle.wait_for_shutdown( );
- return 0;
- }
-
- Typically, when you have an MLT object such as a producer or a playlist,
- you can send a westley representation of this to a running server with:
-
- Conumser valerie( "valerie", "localhost:5250" );
- valerie.connect( producer );
- valerie.start( );
-
- The effect of the push will be to append the producer on to the first
- unit (u0).
-
- You can completely customise the miracle server - an example of this
- is shown below.
-
-
-That's All Folks...
--------------------
-
- And that, believe it or not, is a fairly complete summary of the classes you'll
- typically be interfacing with in mlt++. Obviously, there's a little more to it
- than this - a couple of intrisinc classes have been glossed over (notably, the
- Properties and Service base classes). The next section will cover all of the
- above, but in much more detail...
-
-
-DIGGING DEEPER
---------------
-
- The previous section was designed to give you a whistle stop tour through the major
- framework classes. This section will take you through the scenic route.
-
-
-Introducing Base Classes
-------------------------
-
- Services in mlt are the collective noun for Producers, Filters, Transitions and
- Consumer. A Service is also the base class from which all of these classes
- extend. It provides the basic connectivity which has been shown throughout the
- examples in the previous section.
-
- Properties are the main way in which we communicate with the Services -
- essentially, it provides get/set methods for named values. All services extend
- Properties.
-
-
-Properties
-----------
-
- Properties provide the general mechanism for communicating with Services -
- through the Properties interface, we are able to manipulate and serialise
- a services state.
-
- For example, to dump all the properties to stdout, you can use something
- like:
-
- void dump( Properties &properties )
- {
- for ( int i = 0; i < properties.count( ); i ++ )
- cout << Properties.get_name( i ) << " = " << Properties.get( i ) << endl;
- }
-
- Note that the properties object handles type conversion, so the following
- is acceptable:
-
- properties.set( "hello", "10.5" );
- int hello_int = properties.get_int( "hello" );
- double hello_double = properties.get_double( "hello" );
-
- A couple of convenience methods are provide to examine or serialise property
- objects.
-
- For example:
-
- properties.debug( );
-
- will report all serialisable properties on stderr, in the form:
-
- Object: [ ref=1, in=0, out=0, track=0, u=75, v=150, _unique_id=15,
- mlt_type=filter, mlt_service=sepia ]
-
-
-Services
---------
-
- Typically, all the services are constructed via the specific classes
- constructor. Often, you will receive Service objects rather than their
- specific type. In order to access the extended classes interface,
- you will need to create a reference.
-
- For example, given an arbitrary Service object, you can determine its
- type by using the type method - this will return a 'service_type' which
- has values of producer_type, filter_type etc. Alternatively, you can
- create a wrapping object and check on its validity.
-
- bool do_we_have_a_producer( Service &service )
- {
- Producer producer( service );
- return producer.is_valid( );
- }
-
-
-Events
-------
-
-
-Servers and Westley Docs
-------------------------
-
- For various reasons, you might want to serialise a producer to a string.
- To do this, you just need to specify a property to write to:
-
- Consumer westley( "westley", "buffer" );
- westley.connect( producer );
- westley.start( );
- buffer = westley.get( "buffer" );
-
- You can use any name you want, and you can change it using the "resource"
- property. Any name with a '.' in it is considered to be a file. Hence, you
- can use a westley consumer to store multiple instances of the same MLT
- object - useful if you want to provide undo/redo capabilities in an
- editing application.
-
- Should you receive an xml document as a string, and you want to send it
- on to a server, you can use:
-
- Conumser valerie( "valerie", "localhost:5250" );
- valerie.set( "westley", buffer );
- valerie.start( );
-
- If you need to obtain an MLT object from a string:
-
- Producer producer( "westley-xml", buffer );
-
- The following shows a working example of an extended server:
-
- class ShotcutServer : public Miracle
- {
- public:
- ShotcutServer( char *id, int port ) :
- Miracle( id, port )
- {
- }
-
- void set_receive_doc( bool doc )
- {
- set( "push-parser-off", doc );
- }
-
- // Reject all commands other than push/receive
- Response *execute( char *command )
- {
- valerie_response response = valerie_response_init( );
- valerie_response_set_error( response, 400, "Not OK" );
- return new Response( response );
- }
-
- // Push document handler
- Response *received( char *command, char *doc )
- {
- valerie_response response = valerie_response_init( );
- // Use doc in some way and assign Response
- if ( doc != NULL )
- valerie_response_set_error( response, 200, "OK" );
- return new Response( response );
- }
-
- // Push service handler
- Response *push( char *command, Service *service )
- {
- valerie_response response = valerie_response_init( );
- // Use service in some way and assign Response
- if ( service != NULL )
- valerie_response_set_error( response, 200, "OK" );
- return new Response( response );
- }
- };
-
- NB: Should you be incorporating this into a GUI application, remember that the
- execute, received and push methods are invoked from a thread - make sure that
- you honour the locking requirements of your GUI toolkit before interacting with
- the UI.
-
-
+++ /dev/null
-MLT++
------
-
- This mlt sub-project provides a C++ wrapping for the MLT library.
-
-INSTALLATION
-------------
-
- ./configure [ --prefix=path ]
- make
- make install
-
-USAGE
------
-
- Use the following definitions in a Makefile to compile and link with mlt++:
-
- CXXFLAGS=`pkg-config --cflags mlt-framework` -Wall
- LDFLAGS=-lmlt++ `pkg-config --libs mlt-framework`
-
- Include files for the classes can either be explicitly included, ie:
-
- #include <mlt++/MltProducer.h>
- etc
-
- Or you can include all using:
-
- #include <mlt++/Mlt.h>
-
- All definitions are placed in an Mlt namespace, and adhere closely to the C
- naming convention. Mappings always follow the pattern:
-
- Factory methods:
-
- mlt_factory_init ==> Mlt::Factory::init
- mlt_factory_producer ==> Mlt::Factory::producer
- mlt_factory_filter ==> Mlt::Factory::filter
- mlt_factory_transition ==> Mlt::Factory::transition
- mlt_factory_consumer ==> Mlt::Factory::consumer
- mlt_factory_close ==> Mlt::Factory::close
-
- NB: Factory usage for service construction is optional.
-
- Types:
-
- mlt_properties ==> Mlt::Properties
- mlt_frame ==> Mlt::Frame
- mlt_service ==> Mlt::Service
- mlt_producer ==> Mlt::Producer
- mlt_filter ==> Mlt::Filter
- mlt_transition ==> Mlt::Transition
- mlt_consumer ==> Mlt::Consumer
-
- Methods:
-
- mlt_type_method ==> Mlt::Type.method
- ie: mlt_playlist_append ==> Mlt::Playlist.append
-
- Parent methods are available directly on children.
-
- Additionally, you can specify:
-
- using namespace Mlt;
-
- To avoid the enforced use of the Mlt:: prefix.
-
- Enumerators and macros are reused directly from the C library.
-
-CLASS HIERARCHY
----------------
-
- The currently mapped objects are shown in the following hierarchy:
-
- Factory
- Properties
- Frame
- Service
- Consumer
- Field
- Filter
- Multitrack
- Producer
- Playlist
- Tractor
- Transition
-
- An additional set of classes allow apps to behave as, and communicate with,
- client/server components - these components provide MLT with unique
- possibilties for process to process or system to system communications.
-
- Miracle
- Response
-
-SPECIAL CASES
--------------
-
- Care should be taken with wrapper objects.
-
- Taking, as an example, the C function that returns the immediate consumer of
- a service:
-
- mlt_service mlt_service_consumer( mlt_service );
-
- This maps to:
-
- Mlt::Service *Mlt::Service.consumer( );
-
- Note that you get an object back - it is never the original c++ object, but
- a wrapping object. This is done to keep consistency with the C api which may
- instantiate C instances - therefore it cannot be assumed that a C++ object
- exists for all mlt service instances.
-
- As such, it is mandatory that you delete these objects. The original will
- not be affected. However, all other modifications (to properties or its
- state of connection) will be reflected in the original object.
-
- This approach excludes the use of RTTI to determine the real type of the
- object - this can only be done by parsing the objects properties.
-
- Objects may be invalid - always use the is_valid method to check validity
- before use.
-
-LIMITATIONS
------------
-
- The mechanisms for the definition of new services are deliberately
- excluded from the C++ wrappings - this is done to ensure that service
- networks constructed can be serialised and used by existing applications
- which are based on the C API (such as miracle).
-
-SWIG
-----
-
- Experimental swig bindings based on mlt++ are provided.
-
+++ /dev/null
-Microsoft Visual Studio Solution File, Format Version 8.00\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mlt++", "mlt++.vcproj", "{31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}"\r
- ProjectSection(ProjectDependencies) = postProject\r
- EndProjectSection\r
-EndProject\r
-Global\r
- GlobalSection(SolutionConfiguration) = preSolution\r
- Debug = Debug\r
- Release = Release\r
- EndGlobalSection\r
- GlobalSection(ProjectConfiguration) = postSolution\r
- {31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}.Debug.ActiveCfg = Debug|Win32\r
- {31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}.Debug.Build.0 = Debug|Win32\r
- {31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}.Release.ActiveCfg = Release|Win32\r
- {31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}.Release.Build.0 = Release|Win32\r
- EndGlobalSection\r
- GlobalSection(ExtensibilityGlobals) = postSolution\r
- EndGlobalSection\r
- GlobalSection(ExtensibilityAddIns) = postSolution\r
- EndGlobalSection\r
-EndGlobal\r
+++ /dev/null
-<?xml version="1.0" encoding="Windows-1252"?>\r
-<VisualStudioProject\r
- ProjectType="Visual C++"\r
- Version="7.10"\r
- Name="mlt++"\r
- ProjectGUID="{31B6CBDB-6A84-4BC7-AACF-A1BCE02444FD}"\r
- Keyword="Win32Proj">\r
- <Platforms>\r
- <Platform\r
- Name="Win32"/>\r
- </Platforms>\r
- <Configurations>\r
- <Configuration\r
- Name="Debug|Win32"\r
- OutputDirectory="Debug"\r
- IntermediateDirectory="Debug"\r
- ConfigurationType="2"\r
- CharacterSet="2">\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- Optimization="0"\r
- AdditionalIncludeDirectories=""C:\Program Files\mlt\include\mlt""\r
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MLTPP_EXPORTS"\r
- MinimalRebuild="TRUE"\r
- BasicRuntimeChecks="3"\r
- RuntimeLibrary="3"\r
- TreatWChar_tAsBuiltInType="TRUE"\r
- UsePrecompiledHeader="0"\r
- WarningLevel="3"\r
- Detect64BitPortabilityProblems="TRUE"\r
- DebugInformationFormat="4"/>\r
- <Tool\r
- Name="VCCustomBuildTool"/>\r
- <Tool\r
- Name="VCLinkerTool"\r
- AdditionalDependencies="libmlt.0.2.1.lib"\r
- OutputFile="$(OutDir)/mlt++.dll"\r
- LinkIncremental="2"\r
- AdditionalLibraryDirectories=""C:\Program Files\mlt\lib""\r
- GenerateDebugInformation="TRUE"\r
- ProgramDatabaseFile="$(OutDir)/mlt++.pdb"\r
- SubSystem="2"\r
- ImportLibrary="$(OutDir)/mlt++.lib"\r
- TargetMachine="1"/>\r
- <Tool\r
- Name="VCMIDLTool"/>\r
- <Tool\r
- Name="VCPostBuildEventTool"/>\r
- <Tool\r
- Name="VCPreBuildEventTool"/>\r
- <Tool\r
- Name="VCPreLinkEventTool"/>\r
- <Tool\r
- Name="VCResourceCompilerTool"/>\r
- <Tool\r
- Name="VCWebServiceProxyGeneratorTool"/>\r
- <Tool\r
- Name="VCXMLDataGeneratorTool"/>\r
- <Tool\r
- Name="VCWebDeploymentTool"/>\r
- <Tool\r
- Name="VCManagedWrapperGeneratorTool"/>\r
- <Tool\r
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
- </Configuration>\r
- <Configuration\r
- Name="Release|Win32"\r
- OutputDirectory="Release"\r
- IntermediateDirectory="Release"\r
- ConfigurationType="2"\r
- CharacterSet="2">\r
- <Tool\r
- Name="VCCLCompilerTool"\r
- AdditionalIncludeDirectories=""C:\Program Files\mlt\include\mlt""\r
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MLTPP_EXPORTS"\r
- RuntimeLibrary="0"\r
- TreatWChar_tAsBuiltInType="TRUE"\r
- UsePrecompiledHeader="0"\r
- WarningLevel="3"\r
- Detect64BitPortabilityProblems="TRUE"\r
- DebugInformationFormat="3"/>\r
- <Tool\r
- Name="VCCustomBuildTool"/>\r
- <Tool\r
- Name="VCLinkerTool"\r
- AdditionalDependencies="libmlt.0.2.1.lib"\r
- OutputFile="$(OutDir)/mlt++.dll"\r
- LinkIncremental="1"\r
- AdditionalLibraryDirectories=""C:\Program Files\mlt\lib""\r
- GenerateDebugInformation="TRUE"\r
- SubSystem="2"\r
- OptimizeReferences="2"\r
- EnableCOMDATFolding="2"\r
- ImportLibrary="$(OutDir)/mlt++.lib"\r
- TargetMachine="1"/>\r
- <Tool\r
- Name="VCMIDLTool"/>\r
- <Tool\r
- Name="VCPostBuildEventTool"/>\r
- <Tool\r
- Name="VCPreBuildEventTool"/>\r
- <Tool\r
- Name="VCPreLinkEventTool"/>\r
- <Tool\r
- Name="VCResourceCompilerTool"/>\r
- <Tool\r
- Name="VCWebServiceProxyGeneratorTool"/>\r
- <Tool\r
- Name="VCXMLDataGeneratorTool"/>\r
- <Tool\r
- Name="VCWebDeploymentTool"/>\r
- <Tool\r
- Name="VCManagedWrapperGeneratorTool"/>\r
- <Tool\r
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
- </Configuration>\r
- </Configurations>\r
- <References>\r
- </References>\r
- <Files>\r
- <Filter\r
- Name="Source Files"\r
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
- <File\r
- RelativePath=".\src\config.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\Mlt.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltConsumer.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltConsumer.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltDeque.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltDeque.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltEvent.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltEvent.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFactory.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFactory.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltField.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltField.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilter.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilter.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilteredConsumer.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilteredConsumer.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilteredProducer.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFilteredProducer.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFrame.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltFrame.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltGeometry.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltGeometry.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltMultitrack.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltMultitrack.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltParser.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltParser.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltPlaylist.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltPlaylist.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltProducer.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltProducer.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltProperties.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltProperties.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltPushConsumer.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltPushConsumer.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltService.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltService.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTokeniser.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTokeniser.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTractor.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTractor.h">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTransition.cpp">\r
- </File>\r
- <File\r
- RelativePath=".\src\MltTransition.h">\r
- </File>\r
- </Filter>\r
- <Filter\r
- Name="Header Files"\r
- Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
- </Filter>\r
- <Filter\r
- Name="Resource Files"\r
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
- </Filter>\r
- </Files>\r
- <Globals>\r
- </Globals>\r
-</VisualStudioProject>\r
+++ /dev/null
-/**
- * Mlt.h - Convenience header file for all mlt++ objects
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_H_
-#define _MLTPP_H_
-
-#include "MltConsumer.h"
-#include "MltDeque.h"
-#include "MltEvent.h"
-#include "MltFactory.h"
-#include "MltField.h"
-#include "MltFilter.h"
-#include "MltFilteredConsumer.h"
-#include "MltFrame.h"
-#include "MltGeometry.h"
-#ifndef WIN32
-#include "MltMiracle.h"
-#endif
-#include "MltMultitrack.h"
-#include "MltParser.h"
-#include "MltPlaylist.h"
-#include "MltProducer.h"
-#include "MltProfile.h"
-#include "MltProperties.h"
-#include "MltPushConsumer.h"
-#include "MltRepository.h"
-#ifndef WIN32
-#include "MltResponse.h"
-#endif
-#include "MltService.h"
-#include "MltTokeniser.h"
-#include "MltTractor.h"
-#include "MltTransition.h"
-
-#endif
+++ /dev/null
-/**
- * MltConsumer.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "MltConsumer.h"
-#include "MltEvent.h"
-#include "MltProfile.h"
-using namespace Mlt;
-
-Consumer::Consumer( ) :
- instance( NULL )
-{
- instance = mlt_factory_consumer( NULL, NULL, NULL );
-}
-
-Consumer::Consumer( Profile& profile ) :
- instance( NULL )
-{
- instance = mlt_factory_consumer( profile.get_profile(), NULL, NULL );
-}
-
-Consumer::Consumer( Profile& profile, const char *id, const char *arg ) :
- instance( NULL )
-{
- if ( id == NULL || arg != NULL )
- {
- instance = mlt_factory_consumer( profile.get_profile(), id, arg );
- }
- else
- {
- if ( strchr( id, ':' ) )
- {
- char *temp = strdup( id );
- char *arg = strchr( temp, ':' ) + 1;
- *( arg - 1 ) = '\0';
- instance = mlt_factory_consumer( profile.get_profile(), temp, arg );
- free( temp );
- }
- else
- {
- instance = mlt_factory_consumer( profile.get_profile(), id, NULL );
- }
- }
-}
-
-Consumer::Consumer( Service &consumer ) :
- instance( NULL )
-{
- if ( consumer.type( ) == consumer_type )
- {
- instance = ( mlt_consumer )consumer.get_service( );
- inc_ref( );
- }
-}
-
-Consumer::Consumer( Consumer &consumer ) :
- Mlt::Service( consumer ),
- instance( consumer.get_consumer( ) )
-{
- inc_ref( );
-}
-
-Consumer::Consumer( mlt_consumer consumer ) :
- instance( consumer )
-{
- inc_ref( );
-}
-
-Consumer::~Consumer( )
-{
- mlt_consumer_close( instance );
-}
-
-mlt_consumer Consumer::get_consumer( )
-{
- return instance;
-}
-
-mlt_service Consumer::get_service( )
-{
- return mlt_consumer_service( get_consumer( ) );
-}
-
-int Consumer::connect( Service &service )
-{
- return connect_producer( service );
-}
-
-int Consumer::start( )
-{
- return mlt_consumer_start( get_consumer( ) );
-}
-
-void Consumer::purge( )
-{
- mlt_consumer_purge( get_consumer( ) );
-}
-
-int Consumer::stop( )
-{
- return mlt_consumer_stop( get_consumer( ) );
-}
-
-bool Consumer::is_stopped( )
-{
- return mlt_consumer_is_stopped( get_consumer( ) ) != 0;
-}
-
-int Consumer::run( )
-{
- int ret = start( );
- if ( !is_stopped( ) )
- {
- Event *e = setup_wait_for( "consumer-stopped" );
- wait_for( e );
- delete e;
- }
- return ret;
-}
+++ /dev/null
-/**
- * MltConsumer.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_CONSUMER_H_
-#define _MLTPP_CONSUMER_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltService.h"
-
-namespace Mlt
-{
- class Service;
- class Profile;
-
- class MLTPP_DECLSPEC Consumer : public Service
- {
- private:
- mlt_consumer instance;
- public:
- Consumer( );
- Consumer( Profile& profile );
- Consumer( Profile& profile, const char *id , const char *service = NULL );
- Consumer( Service &consumer );
- Consumer( Consumer &consumer );
- Consumer( mlt_consumer consumer );
- virtual ~Consumer( );
- virtual mlt_consumer get_consumer( );
- mlt_service get_service( );
- virtual int connect( Service &service );
- int run( );
- int start( );
- void purge( );
- int stop( );
- bool is_stopped( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltDeque.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltDeque.h"
-using namespace Mlt;
-
-Deque::Deque( )
-{
- deque = mlt_deque_init( );
-}
-
-Deque::~Deque( )
-{
- mlt_deque_close( deque );
-}
-
-int Deque::count( )
-{
- return mlt_deque_count( deque );
-}
-
-int Deque::push_back( void *item )
-{
- return mlt_deque_push_back( deque, item );
-}
-
-void *Deque::pop_back( )
-{
- return mlt_deque_pop_back( deque );
-}
-
-int Deque::push_front( void *item )
-{
- return mlt_deque_push_front( deque, item );
-}
-
-void *Deque::pop_front( )
-{
- return mlt_deque_pop_front( deque );
-}
-
-void *Deque::peek_back( )
-{
- return mlt_deque_peek_back( deque );
-}
-
-void *Deque::peek_front( )
-{
- return mlt_deque_peek_front( deque );
-}
-
+++ /dev/null
-/**
- * MltDeque.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_DEQUE_H
-#define _MLTPP_DEQUE_H
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class MLTPP_DECLSPEC Deque
- {
- private:
- mlt_deque deque;
- public:
- Deque( );
- ~Deque( );
- int count( );
- int push_back( void *item );
- void *pop_back( );
- int push_front( void *item );
- void *pop_front( );
- void *peek_back( );
- void *peek_front( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltEvent.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltEvent.h"
-using namespace Mlt;
-
-
-Event::Event( mlt_event event ) :
- instance( event )
-{
- mlt_event_inc_ref( instance );
-}
-
-Event::Event( Event &event ) :
- instance( event.get_event( ) )
-{
- mlt_event_inc_ref( instance );
-}
-
-Event::~Event( )
-{
- mlt_event_close( instance );
-}
-
-mlt_event Event::get_event( )
-{
- return instance;
-}
-
-bool Event::is_valid( )
-{
- return instance != NULL;
-}
-
-void Event::block( )
-{
- mlt_event_block( get_event( ) );
-}
-
-void Event::unblock( )
-{
- mlt_event_unblock( get_event( ) );
-}
-
+++ /dev/null
-/**
- * MltEvent.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_EVENT_H_
-#define _MLTPP_EVENT_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class MLTPP_DECLSPEC Event
- {
- private:
- mlt_event instance;
- public:
- Event( mlt_event );
- Event( Event & );
- ~Event( );
- mlt_event get_event( );
- bool is_valid( );
- void block( );
- void unblock( );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltFactory.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltFactory.h"
-#include "MltProducer.h"
-#include "MltFilter.h"
-#include "MltTransition.h"
-#include "MltConsumer.h"
-#include "MltRepository.h"
-using namespace Mlt;
-
-Repository *Factory::init( const char *directory )
-{
- return new Repository( mlt_factory_init( directory ) );
-}
-
-Properties *Factory::event_object( )
-{
- return new Properties( mlt_factory_event_object( ) );
-}
-
-Producer *Factory::producer( Profile& profile, char *id, char *arg )
-{
- return new Producer( profile, id, arg );
-}
-
-Filter *Factory::filter( Profile& profile, char *id, char *arg )
-{
- return new Filter( profile, id, arg );
-}
-
-Transition *Factory::transition( Profile& profile, char *id, char *arg )
-{
- return new Transition( profile, id, arg );
-}
-
-Consumer *Factory::consumer( Profile& profile, char *id, char *arg )
-{
- return new Consumer( profile, id, arg );
-}
-
-#ifdef WIN32
-char *Factory::getenv( const char *name )
-{
- return mlt_getenv( name );
-}
-
-int Factory::setenv( const char *name, const char *value )
-{
- return mlt_setenv( name, value );
-}
-#endif
-
-void Factory::close( )
-{
- mlt_factory_close( );
-}
-
-
+++ /dev/null
-/**
- * MltFactory.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FACTORY_H_
-#define _MLTPP_FACTORY_H_
-
-#include "config.h"
-
-#ifdef SWIG
-#define MLTPP_DECLSPEC
-#endif
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class Properties;
- class Producer;
- class Filter;
- class Transition;
- class Consumer;
- class Profile;
- class Repository;
-
- class MLTPP_DECLSPEC Factory
- {
- public:
- static Repository *init( const char *directory = NULL );
- static Properties *event_object( );
- static Producer *producer( Profile& profile, char *id, char *arg = NULL );
- static Filter *filter( Profile& profile, char *id, char *arg = NULL );
- static Transition *transition( Profile& profile, char *id, char *arg = NULL );
- static Consumer *consumer( Profile& profile, char *id, char *arg = NULL );
-#ifdef WIN32
- static char *getenv( const char * );
- static int setenv( const char *, const char * );
-#endif
- static void close( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltField.cpp - Field wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltField.h"
-#include "MltFilter.h"
-#include "MltTransition.h"
-using namespace Mlt;
-
-Field::Field( mlt_field field ) :
- instance( field )
-{
- inc_ref( );
-}
-
-Field::Field( Field &field ) :
- Mlt::Service( field ),
- instance( field.get_field( ) )
-{
- inc_ref( );
-}
-
-Field::~Field( )
-{
- mlt_field_close( instance );
-}
-
-mlt_field Field::get_field( )
-{
- return instance;
-}
-
-mlt_service Field::get_service( )
-{
- return mlt_field_service( get_field( ) );
-}
-
-int Field::plant_filter( Filter &filter, int track )
-{
- return mlt_field_plant_filter( get_field( ), filter.get_filter( ), track );
-}
-
-int Field::plant_transition( Transition &transition, int a_track, int b_track )
-{
- return mlt_field_plant_transition( get_field( ), transition.get_transition( ), a_track, b_track );
-}
-
-
+++ /dev/null
-/**
- * MltField.h - Field wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FIELD_H_
-#define _MLTPP_FIELD_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltService.h"
-
-namespace Mlt
-{
- class Service;
- class Filter;
- class Transition;
-
- class MLTPP_DECLSPEC Field : public Service
- {
- private:
- mlt_field instance;
- public:
- Field( mlt_field field );
- Field( Field &field );
- virtual ~Field( );
- mlt_field get_field( );
- mlt_service get_service( );
- int plant_filter( Filter &filter, int track = 0 );
- int plant_transition( Transition &transition, int a_track = 0, int b_track = 1 );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltFilter.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "MltFilter.h"
-#include "MltProfile.h"
-using namespace Mlt;
-
-Filter::Filter( Profile& profile, const char *id, const char *arg ) :
- instance( NULL )
-{
- if ( arg != NULL )
- {
- instance = mlt_factory_filter( profile.get_profile(), id, arg );
- }
- else
- {
- if ( strchr( id, ':' ) )
- {
- char *temp = strdup( id );
- char *arg = strchr( temp, ':' ) + 1;
- *( arg - 1 ) = '\0';
- instance = mlt_factory_filter( profile.get_profile(), temp, arg );
- free( temp );
- }
- else
- {
- instance = mlt_factory_filter( profile.get_profile(), id, NULL );
- }
- }
-}
-
-Filter::Filter( Service &filter ) :
- instance( NULL )
-{
- if ( filter.type( ) == filter_type )
- {
- instance = ( mlt_filter )filter.get_service( );
- inc_ref( );
- }
-}
-
-Filter::Filter( Filter &filter ) :
- Mlt::Service( filter ),
- instance( filter.get_filter( ) )
-{
- inc_ref( );
-}
-
-Filter::Filter( mlt_filter filter ) :
- instance( filter )
-{
- inc_ref( );
-}
-
-Filter::~Filter( )
-{
- mlt_filter_close( instance );
-}
-
-mlt_filter Filter::get_filter( )
-{
- return instance;
-}
-
-mlt_service Filter::get_service( )
-{
- return mlt_filter_service( get_filter( ) );
-}
-
-int Filter::connect( Service &service, int index )
-{
- return mlt_filter_connect( get_filter( ), service.get_service( ), index );
-}
-
-void Filter::set_in_and_out( int in, int out )
-{
- mlt_filter_set_in_and_out( get_filter( ), in, out );
-}
-
-int Filter::get_in( )
-{
- return mlt_filter_get_in( get_filter( ) );
-}
-
-int Filter::get_out( )
-{
- return mlt_filter_get_out( get_filter( ) );
-}
-
-int Filter::get_track( )
-{
- return mlt_filter_get_track( get_filter( ) );
-}
-
+++ /dev/null
-/**
- * MltFilter.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FILTER_H_
-#define _MLTPP_FILTER_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltService.h"
-
-namespace Mlt
-{
- class Service;
- class Profile;
-
- class MLTPP_DECLSPEC Filter : public Service
- {
- private:
- mlt_filter instance;
- public:
- Filter( Profile& profile, const char *id, const char *service = NULL );
- Filter( Service &filter );
- Filter( Filter &filter );
- Filter( mlt_filter filter );
- virtual ~Filter( );
- virtual mlt_filter get_filter( );
- mlt_service get_service( );
- int connect( Service &service, int index = 0 );
- void set_in_and_out( int in, int out );
- int get_in( );
- int get_out( );
- int get_track( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltFilteredConsumer.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltFilteredConsumer.h"
-using namespace Mlt;
-
-FilteredConsumer::FilteredConsumer( Profile& profile, char *id, char *arg ) :
- Consumer( profile, id, arg )
-{
- // Create a reference to the first service
- first = new Service( *this );
-}
-
-FilteredConsumer::FilteredConsumer( Consumer &consumer ) :
- Consumer( consumer )
-{
- // Create a reference to the first service
- first = new Service( *this );
-}
-
-FilteredConsumer::~FilteredConsumer( )
-{
- // Delete the reference to the first service
- delete first;
-}
-
-int FilteredConsumer::connect( Service &service )
-{
- // All producers must connect to the first service, hence the use of the virtual here
- return first->connect_producer( service );
-}
-
-int FilteredConsumer::attach( Filter &filter )
-{
- int error = 0;
- if ( filter.is_valid( ) )
- {
- Service *producer = first->producer( );
- error = filter.connect( *producer );
- if ( error == 0 )
- {
- first->connect_producer( filter );
- delete first;
- first = new Service( filter );
- }
- delete producer;
- }
- else
- {
- error = 1;
- }
- return error;
-}
-
-int FilteredConsumer::last( Filter &filter )
-{
- int error = 0;
- if ( filter.is_valid( ) )
- {
- Service *producer = this->producer( );
- error = filter.connect( *producer );
- if ( error == 0 )
- connect_producer( filter );
- delete producer;
- }
- else
- {
- error = 1;
- }
- return error;
-}
-
-int FilteredConsumer::detach( Filter &filter )
-{
- if ( filter.is_valid( ) )
- {
- Service *it = new Service( *first );
- while ( it->is_valid( ) && it->get_service( ) != filter.get_service( ) )
- {
- Service *consumer = it->consumer( );
- delete it;
- it = consumer;
- }
- if ( it->get_service( ) == filter.get_service( ) )
- {
- Service *producer = it->producer( );
- Service *consumer = it->consumer( );
- consumer->connect_producer( *producer );
- Service dummy( NULL );
- it->connect_producer( dummy );
- if ( first->get_service( ) == it->get_service( ) )
- {
- delete first;
- first = new Service( *consumer );
- }
- }
- delete it;
- }
- return 0;
-}
-
+++ /dev/null
-/**
- * MltFilteredConsumer.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FILTERED_CONSUMER_H_
-#define _MLTPP_FILTERED_CONSUMER_H_
-
-#include "config.h"
-
-#include "MltConsumer.h"
-#include "MltFilter.h"
-#include "MltService.h"
-
-namespace Mlt
-{
- class Consumer;
- class Service;
- class Filter;
- class Profile;
-
- class MLTPP_DECLSPEC FilteredConsumer : public Consumer
- {
- private:
- Service *first;
- public:
- FilteredConsumer( Profile& profile, char *id, char *arg = NULL );
- FilteredConsumer( Consumer &consumer );
- virtual ~FilteredConsumer( );
- int connect( Service &service );
- int attach( Filter &filter );
- int last( Filter &filter );
- int detach( Filter &filter );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltFilteredProducer.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltFilteredProducer.h"
-using namespace Mlt;
-
-FilteredProducer::FilteredProducer( Profile& profile, char *id, char *arg ) :
- Producer( profile, id, arg )
-{
- // Create a reference to the last service
- last = new Service( *this );
-}
-
-FilteredProducer::~FilteredProducer( )
-{
- // Delete the reference to the last service
- delete last;
-}
-
-int FilteredProducer::attach( Filter &filter )
-{
- int error = 0;
- if ( filter.is_valid( ) )
- {
- Service *consumer = last->consumer( );
- filter.connect_producer( *last );
- if ( consumer->is_valid( ) )
- consumer->connect_producer( filter );
- delete consumer;
- delete last;
- last = new Service( filter );
- }
- else
- {
- error = 1;
- }
- return error;
-}
-
-int FilteredProducer::detach( Filter &filter )
-{
- if ( filter.is_valid( ) )
- {
- Service *it = new Service( *last );
- while ( it->is_valid( ) && it->get_service( ) != filter.get_service( ) )
- {
- Service *producer = it->producer( );
- delete it;
- it = producer;
- }
- if ( it->get_service( ) == filter.get_service( ) )
- {
- Service *producer = it->producer( );
- Service *consumer = it->consumer( );
- if ( consumer->is_valid( ) )
- consumer->connect_producer( *producer );
- Producer dummy( "colour" );
- dummy.connect_producer( *it );
- if ( last->get_service( ) == it->get_service( ) )
- {
- delete last;
- last = new Service( *producer );
- }
- }
- delete it;
- }
- return 0;
-}
-
+++ /dev/null
-/**
- * MltFilteredProducer.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FILTERED_PRODUCER_H_
-#define _MLTPP_FILTERED_PRODUCER_H_
-
-#include "config.h"
-
-#include "MltProducer.h"
-#include "MltFilter.h"
-#include "MltService.h"
-
-namespace Mlt
-{
- class Producer;
- class Service;
- class Filter;
- class Profile;
-
- class MLTPP_DECLSPEC FilteredProducer : public Producer
- {
- private:
- Service *last;
- public:
- FilteredProducer( Profile* profile, char *id, char *arg = NULL );
- virtual ~FilteredProducer( );
- int attach( Filter &filter );
- int detach( Filter &filter );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltFrame.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltFrame.h"
-#include "MltProducer.h"
-using namespace Mlt;
-
-Frame::Frame( mlt_frame frame ) :
- instance( frame )
-{
- inc_ref( );
-}
-
-Frame::Frame( Frame &frame ) :
- Mlt::Properties( frame ),
- instance( frame.get_frame( ) )
-{
- inc_ref( );
-}
-
-Frame::~Frame( )
-{
- mlt_frame_close( instance );
-}
-
-mlt_frame Frame::get_frame( )
-{
- return instance;
-}
-
-mlt_properties Frame::get_properties( )
-{
- return mlt_frame_properties( get_frame( ) );
-}
-
-uint8_t *Frame::get_image( mlt_image_format &format, int &w, int &h, int writable )
-{
- uint8_t *image = NULL;
- if ( get_double( "consumer_aspect_ratio" ) == 0.0 )
- set( "consumer_aspect_ratio", 1.0 );
- mlt_frame_get_image( get_frame( ), &image, &format, &w, &h, writable );
- set( "format", format );
- set( "writable", writable );
- return image;
-}
-
-unsigned char *Frame::fetch_image( mlt_image_format f, int w, int h, int writable )
-{
- uint8_t *image = NULL;
- if ( get_double( "consumer_aspect_ratio" ) == 0.0 )
- set( "consumer_aspect_ratio", 1.0 );
- mlt_frame_get_image( get_frame( ), &image, &f, &w, &h, writable );
- set( "format", f );
- set( "writable", writable );
- return image;
-}
-
-int16_t *Frame::get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples )
-{
- int16_t *audio = NULL;
- mlt_frame_get_audio( get_frame( ), &audio, &format, &frequency, &channels, &samples );
- return audio;
-}
-
-unsigned char *Frame::get_waveform( int w, int h )
-{
- return mlt_frame_get_waveform( get_frame( ), w, h );
-}
-
-Producer *Frame::get_original_producer( )
-{
- return new Producer( mlt_frame_get_original_producer( get_frame( ) ) );
-}
+++ /dev/null
-/**
- * MltFilter.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_FRAME_H_
-#define _MLTPP_FRAME_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-#include "MltProperties.h"
-
-namespace Mlt
-{
- class Properties;
- class Producer;
-
- class MLTPP_DECLSPEC Frame : public Properties
- {
- private:
- mlt_frame instance;
- public:
- Frame( mlt_frame frame );
- Frame( Frame &frame );
- virtual ~Frame( );
- virtual mlt_frame get_frame( );
- mlt_properties get_properties( );
- uint8_t *get_image( mlt_image_format &format, int &w, int &h, int writable = 0 );
- unsigned char *fetch_image( mlt_image_format format, int w, int h, int writable = 0 );
- int16_t *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
- unsigned char *get_waveform( int w, int h );
- Producer *get_original_producer( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltGeometry.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include "MltGeometry.h"
-using namespace Mlt;
-
-Geometry::Geometry( char *data, int length, int nw, int nh )
-{
- geometry = mlt_geometry_init( );
- parse( data, length, nw, nh );
-}
-
-Geometry::~Geometry( )
-{
- mlt_geometry_close( geometry );
-}
-
-int Geometry::parse( char *data, int length, int nw, int nh )
-{
- return mlt_geometry_parse( geometry, data, length, nw, nh );
-}
-
-// Fetch a geometry item for an absolute position
-int Geometry::fetch( GeometryItem &item, float position )
-{
- return mlt_geometry_fetch( geometry, item.get_item( ), position );
-}
-
-int Geometry::fetch( GeometryItem *item, float position )
-{
- return mlt_geometry_fetch( geometry, item->get_item( ), position );
-}
-
-// Specify a geometry item at an absolute position
-int Geometry::insert( GeometryItem &item )
-{
- return mlt_geometry_insert( geometry, item.get_item( ) );
-}
-
-int Geometry::insert( GeometryItem *item )
-{
- return mlt_geometry_insert( geometry, item->get_item( ) );
-}
-
-// Remove the key at the specified position
-int Geometry::remove( int position )
-{
- return mlt_geometry_remove( geometry, position );
-}
-
-// Get the key at the position or the next following
-int Geometry::next_key( GeometryItem &item, int position )
-{
- return mlt_geometry_next_key( geometry, item.get_item( ), position );
-}
-
-int Geometry::next_key( GeometryItem *item, int position )
-{
- return mlt_geometry_next_key( geometry, item->get_item( ), position );
-}
-
-int Geometry::prev_key( GeometryItem &item, int position )
-{
- return mlt_geometry_prev_key( geometry, item.get_item( ), position );
-}
-
-int Geometry::prev_key( GeometryItem *item, int position )
-{
- return mlt_geometry_prev_key( geometry, item->get_item( ), position );
-}
-
-// Serialise the current geometry
-char *Geometry::serialise( int in, int out )
-{
- return mlt_geometry_serialise_cut( geometry, in, out );
-}
-
-char *Geometry::serialise( )
-{
- return mlt_geometry_serialise( geometry );
-}
-
+++ /dev/null
-/**
- * MltGeometry.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_GEOMETRY_H
-#define _MLTPP_GEOMETRY_H
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- // Just for consistent naming purposes
- class MLTPP_DECLSPEC GeometryItem
- {
- private:
- struct mlt_geometry_item_s item;
- public:
- mlt_geometry_item get_item( ) { return &item; }
- bool key( ) { return item.key != 0; }
- int frame( ) { return item.frame; }
- void frame( int value ) { item.frame = value; }
- float x( ) { return item.x; }
- void x( float value ) { item.f[0] = 1; item.x = value; }
- float y( ) { return item.y; }
- void y( float value ) { item.f[1] = 1; item.y = value; }
- float w( ) { return item.w; }
- void w( float value ) { item.f[2] = 1; item.w = value; }
- float h( ) { return item.h; }
- void h( float value ) { item.f[3] = 1; item.h = value; }
- float mix( ) { return item.mix; }
- void mix( float value ) { item.f[4] = 1; item.mix = value; }
- };
-
- class MLTPP_DECLSPEC Geometry
- {
- private:
- mlt_geometry geometry;
- public:
- Geometry( char *data = NULL, int length = 0, int nw = -1, int nh = -1 );
- ~Geometry( );
- int parse( char *data, int length, int nw = -1, int nh = -1 );
- // Fetch a geometry item for an absolute position
- int fetch( GeometryItem &item, float position );
- int fetch( GeometryItem *item, float position );
- // Specify a geometry item at an absolute position
- int insert( GeometryItem &item );
- int insert( GeometryItem *item );
- // Remove the key at the specified position
- int remove( int position );
- // Get the key at the position or the next following
- int next_key( GeometryItem &item, int position );
- int next_key( GeometryItem *item, int position );
- int prev_key( GeometryItem &item, int position );
- int prev_key( GeometryItem *item, int position );
- // Serialise the current geometry
- char *serialise( int in, int out );
- char *serialise( );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltMultitrack.h - Multitrack wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltMultitrack.h"
-#include "MltProducer.h"
-using namespace Mlt;
-
-Multitrack::Multitrack( mlt_multitrack multitrack ) :
- instance( multitrack )
-{
- inc_ref( );
-}
-
-Multitrack::Multitrack( Service &multitrack ) :
- instance( NULL )
-{
- if ( multitrack.type( ) == multitrack_type )
- {
- instance = ( mlt_multitrack )multitrack.get_service( );
- inc_ref( );
- }
-}
-
-Multitrack::Multitrack( Multitrack &multitrack ) :
- Mlt::Producer( multitrack ),
- instance( multitrack.get_multitrack( ) )
-{
- inc_ref( );
-}
-
-Multitrack::~Multitrack( )
-{
- mlt_multitrack_close( instance );
-}
-
-mlt_multitrack Multitrack::get_multitrack( )
-{
- return instance;
-}
-
-mlt_producer Multitrack::get_producer( )
-{
- return mlt_multitrack_producer( get_multitrack( ) );
-}
-
-int Multitrack::connect( Producer &producer, int index )
-{
- return mlt_multitrack_connect( get_multitrack( ), producer.get_producer( ), index );
-}
-
-int Multitrack::clip( mlt_whence whence, int index )
-{
- return mlt_multitrack_clip( get_multitrack( ), whence, index );
-}
-
-int Multitrack::count( )
-{
- return mlt_multitrack_count( get_multitrack( ) );
-}
-
-Producer *Multitrack::track( int index )
-{
- return new Producer( mlt_multitrack_track( get_multitrack( ), index ) );
-}
-
-void Multitrack::refresh( )
-{
- return mlt_multitrack_refresh( get_multitrack( ) );
-}
+++ /dev/null
-/**
- * MltMultitrack.h - Multitrack wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_MULTITRACK_H_
-#define _MLTPP_MULTITRACK_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltProducer.h"
-
-namespace Mlt
-{
- class Service;
- class Producer;
-
- class MLTPP_DECLSPEC Multitrack : public Producer
- {
- private:
- mlt_multitrack instance;
- public:
- Multitrack( mlt_multitrack multitrack );
- Multitrack( Service &multitrack );
- Multitrack( Multitrack &multitrack );
- virtual ~Multitrack( );
- mlt_multitrack get_multitrack( );
- mlt_producer get_producer( );
- int connect( Producer &producer, int index );
- int clip( mlt_whence whence, int index );
- int count( );
- Producer *track( int index );
- void refresh( );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltPlaylist.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include "MltPlaylist.h"
-#include "MltTransition.h"
-using namespace Mlt;
-
-ClipInfo::ClipInfo( ) :
- clip( 0 ),
- producer( NULL ),
- cut( NULL ),
- start( 0 ),
- resource( NULL ),
- frame_in( 0 ),
- frame_out( 0 ),
- frame_count( 0 ),
- length( 0 ),
- fps( 0 ),
- repeat( 0 )
-{
-}
-
-ClipInfo::ClipInfo( mlt_playlist_clip_info *info ) :
- clip( info->clip ),
- producer( new Producer( info->producer ) ),
- cut( new Producer( info->cut ) ),
- start( info->start ),
- resource( info->resource? strdup( info->resource ) : 0 ),
- frame_in( info->frame_in ),
- frame_out( info->frame_out ),
- frame_count( info->frame_count ),
- length( info->length ),
- fps( info->fps ),
- repeat( info->repeat )
-{
-}
-
-ClipInfo::~ClipInfo( )
-{
- delete producer;
- delete cut;
- free( resource );
-}
-
-void ClipInfo::update( mlt_playlist_clip_info *info )
-{
- delete producer;
- delete cut;
- free( resource );
- clip = info->clip;
- producer = new Producer( info->producer );
- cut = new Producer( info->cut );
- start = info->start;
- resource = strdup( info->resource );
- frame_in = info->frame_in;
- frame_out = info->frame_out;
- frame_count = info->frame_count;
- length = info->length;
- fps = info->fps;
- repeat = info->repeat;
-}
-
-Playlist::Playlist( ) :
- instance( NULL )
-{
- instance = mlt_playlist_init( );
-}
-
-Playlist::Playlist( Service &producer ) :
- instance( NULL )
-{
- if ( producer.type( ) == playlist_type )
- {
- instance = ( mlt_playlist )producer.get_service( );
- inc_ref( );
- }
-}
-
-Playlist::Playlist( Playlist &playlist ) :
- Mlt::Producer( playlist ),
- instance( playlist.get_playlist( ) )
-{
- inc_ref( );
-}
-
-Playlist::Playlist( mlt_playlist playlist ) :
- instance( playlist )
-{
- inc_ref( );
-}
-
-Playlist::~Playlist( )
-{
- mlt_playlist_close( instance );
-}
-
-mlt_playlist Playlist::get_playlist( )
-{
- return instance;
-}
-
-mlt_producer Playlist::get_producer( )
-{
- return mlt_playlist_producer( get_playlist( ) );
-}
-
-int Playlist::count( )
-{
- return mlt_playlist_count( get_playlist( ) );
-}
-
-int Playlist::clear( )
-{
- return mlt_playlist_clear( get_playlist( ) );
-}
-
-int Playlist::append( Producer &producer, int in, int out )
-{
- return mlt_playlist_append_io( get_playlist( ), producer.get_producer( ), in, out );
-}
-
-int Playlist::blank( int length )
-{
- return mlt_playlist_blank( get_playlist( ), length );
-}
-
-int Playlist::clip( mlt_whence whence, int index )
-{
- return mlt_playlist_clip( get_playlist( ), whence, index );
-}
-
-int Playlist::current_clip( )
-{
- return mlt_playlist_current_clip( get_playlist( ) );
-}
-
-Producer *Playlist::current( )
-{
- return new Producer( mlt_playlist_current( get_playlist( ) ) );
-}
-
-ClipInfo *Playlist::clip_info( int index, ClipInfo *info )
-{
- mlt_playlist_clip_info clip_info;
- if ( mlt_playlist_get_clip_info( get_playlist( ), &clip_info, index ) )
- return NULL;
- if ( info == NULL )
- return new ClipInfo( &clip_info );
- info->update( &clip_info );
- return info;
-}
-
-void Playlist::delete_clip_info( ClipInfo *info )
-{
- delete info;
-}
-
-int Playlist::insert( Producer &producer, int where, int in, int out )
-{
- return mlt_playlist_insert( get_playlist( ), producer.get_producer( ), where, in, out );
-}
-
-int Playlist::remove( int where )
-{
- return mlt_playlist_remove( get_playlist( ), where );
-}
-
-int Playlist::move( int from, int to )
-{
- return mlt_playlist_move( get_playlist( ), from, to );
-}
-
-int Playlist::resize_clip( int clip, int in, int out )
-{
- return mlt_playlist_resize_clip( get_playlist( ), clip, in, out );
-}
-
-int Playlist::split( int clip, int position )
-{
- return mlt_playlist_split( get_playlist( ), clip, position );
-}
-
-int Playlist::split_at( int position, bool left )
-{
- return mlt_playlist_split_at( get_playlist( ), position, left );
-}
-
-int Playlist::join( int clip, int count, int merge )
-{
- return mlt_playlist_join( get_playlist( ), clip, count, merge );
-}
-
-int Playlist::mix( int clip, int length, Transition *transition )
-{
- return mlt_playlist_mix( get_playlist( ), clip, length, transition == NULL ? NULL : transition->get_transition( ) );
-}
-
-int Playlist::mix_add( int clip, Transition *transition )
-{
- return mlt_playlist_mix_add( get_playlist( ), clip, transition == NULL ? NULL : transition->get_transition( ) );
-}
-
-int Playlist::repeat( int clip, int count )
-{
- return mlt_playlist_repeat_clip( get_playlist( ), clip, count );
-}
-
-Producer *Playlist::get_clip( int clip )
-{
- mlt_producer producer = mlt_playlist_get_clip( get_playlist( ), clip );
- return producer != NULL ? new Producer( producer ) : NULL;
-}
-
-Producer *Playlist::get_clip_at( int position )
-{
- mlt_producer producer = mlt_playlist_get_clip_at( get_playlist( ), position );
- return producer != NULL ? new Producer( producer ) : NULL;
-}
-
-int Playlist::get_clip_index_at( int position )
-{
- return mlt_playlist_get_clip_index_at( get_playlist( ), position );
-}
-
-bool Playlist::is_mix( int clip )
-{
- return mlt_playlist_clip_is_mix( get_playlist( ), clip ) != 0;
-}
-
-bool Playlist::is_blank( int clip )
-{
- return mlt_playlist_is_blank( get_playlist( ), clip ) != 0;
-}
-
-bool Playlist::is_blank_at( int position )
-{
- return mlt_playlist_is_blank_at( get_playlist( ), position ) != 0;
-}
-
-Producer *Playlist::replace_with_blank( int clip )
-{
- mlt_producer producer = mlt_playlist_replace_with_blank( get_playlist( ), clip );
- Producer *object = producer != NULL ? new Producer( producer ) : NULL;
- mlt_producer_close( producer );
- return object;
-}
-
-void Playlist::consolidate_blanks( int keep_length )
-{
- return mlt_playlist_consolidate_blanks( get_playlist( ), keep_length );
-}
-
-void Playlist::insert_blank( int clip, int length )
-{
- mlt_playlist_insert_blank( get_playlist( ), clip, length );
-}
-
-void Playlist::pad_blanks( int position, int length, int find )
-{
- mlt_playlist_pad_blanks( get_playlist( ), position, length, find );
-}
-
-int Playlist::insert_at( int position, Producer *producer, int mode )
-{
- return mlt_playlist_insert_at( get_playlist( ), position, producer->get_producer( ), mode );
-}
-
-int Playlist::insert_at( int position, Producer &producer, int mode )
-{
- return mlt_playlist_insert_at( get_playlist( ), position, producer.get_producer( ), mode );
-}
-
-int Playlist::clip_start( int clip )
-{
- return mlt_playlist_clip_start( get_playlist( ), clip );
-}
-
-int Playlist::blanks_from( int clip, int bounded )
-{
- return mlt_playlist_blanks_from( get_playlist( ), clip, bounded );
-}
-
-int Playlist::clip_length( int clip )
-{
- return mlt_playlist_clip_length( get_playlist( ), clip );
-}
-
-int Playlist::remove_region( int position, int length )
-{
- return mlt_playlist_remove_region( get_playlist( ), position, length );
-}
-
-int Playlist::move_region( int position, int length, int new_position )
-{
- return mlt_playlist_move_region( get_playlist( ), position, length, new_position );
-}
-
+++ /dev/null
-/**
- * MltPlaylist.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_PLAYLIST_H_
-#define _MLTPP_PLAYLIST_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltProducer.h"
-
-namespace Mlt
-{
- class Producer;
- class Service;
- class Playlist;
- class Transition;
-
- class MLTPP_DECLSPEC ClipInfo
- {
- public:
- ClipInfo( );
- ClipInfo( mlt_playlist_clip_info *info );
- ~ClipInfo( );
- void update( mlt_playlist_clip_info *info );
- int clip;
- Producer *producer;
- Producer *cut;
- int start;
- char *resource;
- int frame_in;
- int frame_out;
- int frame_count;
- int length;
- float fps;
- int repeat;
- };
-
- class MLTPP_DECLSPEC Playlist : public Producer
- {
- private:
- mlt_playlist instance;
- public:
- Playlist( );
- Playlist( Service &playlist );
- Playlist( Playlist &playlist );
- Playlist( mlt_playlist playlist );
- virtual ~Playlist( );
- virtual mlt_playlist get_playlist( );
- mlt_producer get_producer( );
- int count( );
- int clear( );
- int append( Producer &producer, int in = -1, int out = -1 );
- int blank( int length );
- int clip( mlt_whence whence, int index );
- int current_clip( );
- Producer *current( );
- ClipInfo *clip_info( int index, ClipInfo *info = NULL );
- static void delete_clip_info( ClipInfo *info );
- int insert( Producer &producer, int where, int in = -1, int out = -1 );
- int remove( int where );
- int move( int from, int to );
- int resize_clip( int clip, int in, int out );
- int split( int clip, int position );
- int split_at( int position, bool left = true );
- int join( int clip, int count = 1, int merge = 1 );
- int mix( int clip, int length, Transition *transition = NULL );
- int mix_add( int clip, Transition *transition );
- int repeat( int clip, int count );
- Producer *get_clip( int clip );
- Producer *get_clip_at( int position );
- int get_clip_index_at( int position );
- bool is_mix( int clip );
- bool is_blank( int clip );
- bool is_blank_at( int position );
- void consolidate_blanks( int keep_length = 0 );
- Producer *replace_with_blank( int clip );
- void insert_blank( int clip, int length );
- void pad_blanks( int position, int length, int find = 0 );
- int insert_at( int position, Producer *producer, int mode = 0 );
- int insert_at( int position, Producer &producer, int mode = 0 );
- int clip_start( int clip );
- int clip_length( int clip );
- int blanks_from( int clip, int bounded = 0 );
- int remove_region( int position, int length );
- int move_region( int position, int length, int new_position );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltProducer.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltProducer.h"
-#include "MltFilter.h"
-#include "MltProfile.h"
-using namespace Mlt;
-
-Producer::Producer( ) :
- instance( NULL ),
- parent_( NULL )
-{
-}
-
-Producer::Producer( Profile& profile, const char *id, const char *service ) :
- instance( NULL ),
- parent_( NULL )
-{
- if ( id != NULL && service != NULL )
- instance = mlt_factory_producer( profile.get_profile(), id, service );
- else
- instance = mlt_factory_producer( profile.get_profile(), "fezzik", id != NULL ? id : service );
-}
-
-Producer::Producer( Service &producer ) :
- instance( NULL ),
- parent_( NULL )
-{
- mlt_service_type type = producer.type( );
- if ( type == producer_type || type == playlist_type ||
- type == tractor_type || type == multitrack_type )
- {
- instance = ( mlt_producer )producer.get_service( );
- inc_ref( );
- }
-}
-
-Producer::Producer( mlt_producer producer ) :
- instance( producer ),
- parent_( NULL )
-{
- inc_ref( );
-}
-
-Producer::Producer( Producer &producer ) :
- Mlt::Service( producer ),
- instance( producer.get_producer( ) ),
- parent_( NULL )
-{
- inc_ref( );
-}
-
-Producer::Producer( Producer *producer ) :
- instance( producer != NULL ? producer->get_producer( ) : NULL ),
- parent_( NULL )
-{
- if ( is_valid( ) )
- inc_ref( );
-}
-
-Producer::~Producer( )
-{
- delete parent_;
- mlt_producer_close( instance );
- instance = NULL;
-}
-
-mlt_producer Producer::get_producer( )
-{
- return instance;
-}
-
-mlt_producer Producer::get_parent( )
-{
- return get_producer( ) != NULL && mlt_producer_cut_parent( get_producer( ) ) != NULL ? mlt_producer_cut_parent( get_producer( ) ) : get_producer( );
-}
-
-Producer &Producer::parent( )
-{
- if ( is_cut( ) && parent_ == NULL )
- parent_ = new Producer( get_parent( ) );
- return parent_ == NULL ? *this : *parent_;
-}
-
-mlt_service Producer::get_service( )
-{
- return mlt_producer_service( get_producer( ) );
-}
-
-int Producer::seek( int position )
-{
- return mlt_producer_seek( get_producer( ), position );
-}
-
-int Producer::position( )
-{
- return mlt_producer_position( get_producer( ) );
-}
-
-int Producer::frame( )
-{
- return mlt_producer_frame( get_producer( ) );
-}
-
-int Producer::set_speed( double speed )
-{
- return mlt_producer_set_speed( get_producer( ), speed );
-}
-
-double Producer::get_speed( )
-{
- return mlt_producer_get_speed( get_producer( ) );
-}
-
-double Producer::get_fps( )
-{
- return mlt_producer_get_fps( get_producer( ) );
-}
-
-int Producer::set_in_and_out( int in, int out )
-{
- return mlt_producer_set_in_and_out( get_producer( ), in, out );
-}
-
-int Producer::get_in( )
-{
- return mlt_producer_get_in( get_producer( ) );
-}
-
-int Producer::get_out( )
-{
- return mlt_producer_get_out( get_producer( ) );
-}
-
-int Producer::get_length( )
-{
- return mlt_producer_get_length( get_producer( ) );
-}
-
-int Producer::get_playtime( )
-{
- return mlt_producer_get_playtime( get_producer( ) );
-}
-
-Producer *Producer::cut( int in, int out )
-{
- mlt_producer producer = mlt_producer_cut( get_producer( ), in, out );
- Producer *result = new Producer( producer );
- mlt_producer_close( producer );
- return result;
-}
-
-bool Producer::is_cut( )
-{
- return mlt_producer_is_cut( get_producer( ) ) != 0;
-}
-
-bool Producer::is_blank( )
-{
- return mlt_producer_is_blank( get_producer( ) ) != 0;
-}
-
-bool Producer::same_clip( Producer &that )
-{
- return mlt_producer_cut_parent( get_producer( ) ) == mlt_producer_cut_parent( that.get_producer( ) );
-}
-
-bool Producer::runs_into( Producer &that )
-{
- return same_clip( that ) && get_out( ) == ( that.get_in( ) - 1 );
-}
-
-void Producer::optimise( )
-{
- mlt_producer_optimise( get_producer( ) );
-}
+++ /dev/null
-/**
- * MltProducer.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_PRODUCER_H_
-#define _MLTPP_PRODUCER_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltService.h"
-
-namespace Mlt
-{
- class Service;
- class Filter;
- class Profile;
- class Frame;
-
- class MLTPP_DECLSPEC Producer : public Service
- {
- private:
- mlt_producer instance;
- Producer *parent_;
- public:
- Producer( );
- Producer( Profile& profile, const char *id, const char *service = NULL );
- Producer( Service &producer );
- Producer( mlt_producer producer );
- Producer( Producer &producer );
- Producer( Producer *producer );
- virtual ~Producer( );
- virtual mlt_producer get_producer( );
- Producer &parent( );
- mlt_producer get_parent( );
- mlt_service get_service( );
- int seek( int position );
- int position( );
- int frame( );
- int set_speed( double speed );
- double get_speed( );
- double get_fps( );
- int set_in_and_out( int in, int out );
- int get_in( );
- int get_out( );
- int get_length( );
- int get_playtime( );
- Producer *cut( int in = 0, int out = -1 );
- bool is_cut( );
- bool is_blank( );
- bool same_clip( Producer &that );
- bool runs_into( Producer &that );
- void optimise( );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltProfile.cpp - MLT Wrapper
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltProfile.h"
-#include "MltProperties.h"
-using namespace Mlt;
-
-Profile::Profile( ) :
- instance( NULL )
-{
- instance = mlt_profile_init( NULL );
-}
-
-Profile::Profile( const char* name ) :
- instance( NULL )
-{
- instance = mlt_profile_init( name );
-}
-
-Profile::Profile( Properties& properties ) :
- instance( NULL )
-{
- instance = mlt_profile_load_properties( properties.get_properties() );
-}
-
-Profile::Profile( mlt_profile profile ) :
- instance( profile )
-{
-}
-
-Profile::~Profile( )
-{
- if ( instance )
- mlt_profile_close( instance );
- instance = NULL;
-}
-
-mlt_profile Profile::get_profile( ) const
-{
- return instance;
-}
-
-char* Profile::description() const
-{
- return instance->description;
-}
-
-int Profile::frame_rate_num() const
-{
- return instance->frame_rate_num;
-}
-
-int Profile::frame_rate_den() const
-{
- return instance->frame_rate_den;
-}
-
-double Profile::fps() const
-{
- return mlt_profile_fps( instance );
-}
-
-int Profile::width() const
-{
- return instance->width;
-}
-
-int Profile::height() const
-{
- return instance->height;
-}
-
-bool Profile::progressive() const
-{
- return instance->progressive;
-}
-
-int Profile::sample_aspect_num() const
-{
- return instance->sample_aspect_num;
-}
-
-int Profile::sample_aspect_den() const
-{
- return instance->sample_aspect_den;
-}
-
-double Profile::sar() const
-{
- return mlt_profile_sar( instance );
-}
-
-int Profile::display_aspect_num() const
-{
- return instance->display_aspect_num;
-}
-
-int Profile::display_aspect_den() const
-{
- return instance->display_aspect_den;
-}
-
-double Profile::dar() const
-{
- return mlt_profile_dar( instance );
-}
+++ /dev/null
-/**
- * MltProfile.h - MLT Wrapper
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_PROFILE_H_
-#define _MLTPP_PROFILE_H_
-
-#include "config.h"
-
-#ifdef SWIG
-#define MLTPP_DECLSPEC
-#endif
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class Properties;
-
- class MLTPP_DECLSPEC Profile
- {
- private:
- mlt_profile instance;
- public:
- Profile( );
- Profile( const char* name );
- Profile( Properties& properties );
- Profile( mlt_profile profile );
- ~Profile();
-
- mlt_profile get_profile( ) const;
- char* description() const;
- int frame_rate_num() const;
- int frame_rate_den() const;
- double fps() const;
- int width() const;
- int height() const;
- bool progressive() const;
- int sample_aspect_num() const;
- int sample_aspect_den() const;
- double sar() const;
- int display_aspect_num() const;
- int display_aspect_den() const;
- double dar() const;
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltProperties.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltProperties.h"
-#include "MltEvent.h"
-using namespace Mlt;
-
-Properties::Properties( ) :
- instance( NULL )
-{
- instance = mlt_properties_new( );
-}
-
-Properties::Properties( bool /*dummy*/ ) :
- instance( NULL )
-{
-}
-
-Properties::Properties( Properties &properties ) :
- instance( properties.get_properties( ) )
-{
- inc_ref( );
-}
-
-Properties::Properties( mlt_properties properties ) :
- instance( properties )
-{
- inc_ref( );
-}
-
-Properties::Properties( const char *file ) :
- instance( NULL )
-{
- instance = mlt_properties_load( file );
-}
-
-Properties::~Properties( )
-{
- mlt_properties_close( instance );
-}
-
-mlt_properties Properties::get_properties( )
-{
- return instance;
-}
-
-int Properties::inc_ref( )
-{
- return mlt_properties_inc_ref( get_properties( ) );
-}
-
-int Properties::dec_ref( )
-{
- return mlt_properties_dec_ref( get_properties( ) );
-}
-
-int Properties::ref_count( )
-{
- return mlt_properties_ref_count( get_properties( ) );
-}
-
-void Properties::block( void *object )
-{
- mlt_events_block( get_properties( ), object != NULL ? object : get_properties( ) );
-}
-
-void Properties::unblock( void *object )
-{
- mlt_events_unblock( get_properties( ), object != NULL ? object : get_properties( ) );
-}
-
-void Properties::fire_event( const char *event )
-{
- mlt_events_fire( get_properties( ), event, NULL );
-}
-
-bool Properties::is_valid( )
-{
- return get_properties( ) != NULL;
-}
-
-int Properties::count( )
-{
- return mlt_properties_count( get_properties( ) );
-}
-
-char *Properties::get( const char *name )
-{
- return mlt_properties_get( get_properties( ), name );
-}
-
-int Properties::get_int( const char *name )
-{
- return mlt_properties_get_int( get_properties( ), name );
-}
-
-double Properties::get_double( const char *name )
-{
- return mlt_properties_get_double( get_properties( ), name );
-}
-
-void *Properties::get_data( const char *name, int &size )
-{
- return mlt_properties_get_data( get_properties( ), name, &size );
-}
-
-void *Properties::get_data( const char *name )
-{
- return mlt_properties_get_data( get_properties( ), name, NULL );
-}
-
-int Properties::set( const char *name, const char *value )
-{
- return mlt_properties_set( get_properties( ), name, value );
-}
-
-int Properties::set( const char *name, int value )
-{
- return mlt_properties_set_int( get_properties( ), name, value );
-}
-
-int Properties::set( const char *name, double value )
-{
- return mlt_properties_set_double( get_properties( ), name, value );
-}
-
-int Properties::set( const char *name, void *value, int size, mlt_destructor destructor, mlt_serialiser serialiser )
-{
- return mlt_properties_set_data( get_properties( ), name, value, size, destructor, serialiser );
-}
-
-int Properties::pass_values( Properties &that, const char *prefix )
-{
- return mlt_properties_pass( get_properties( ), that.get_properties( ), prefix );
-}
-
-int Properties::parse( const char *namevalue )
-{
- return mlt_properties_parse( get_properties( ), namevalue );
-}
-
-char *Properties::get_name( int index )
-{
- return mlt_properties_get_name( get_properties( ), index );
-}
-
-char *Properties::get( int index )
-{
- return mlt_properties_get_value( get_properties( ), index );
-}
-
-void *Properties::get_data( int index, int &size )
-{
- return mlt_properties_get_data_at( get_properties( ), index, &size );
-}
-
-void Properties::mirror( Properties &that )
-{
- mlt_properties_mirror( get_properties( ), that.get_properties( ) );
-}
-
-int Properties::inherit( Properties &that )
-{
- return mlt_properties_inherit( get_properties( ), that.get_properties( ) );
-}
-
-int Properties::rename( const char *source, const char *dest )
-{
- return mlt_properties_rename( get_properties( ), source, dest );
-}
-
-void Properties::dump( FILE *output )
-{
- mlt_properties_dump( get_properties( ), output );
-}
-
-void Properties::debug( const char *title, FILE *output )
-{
- mlt_properties_debug( get_properties( ), title, output );
-}
-
-void Properties::load( const char *file )
-{
- mlt_properties properties = mlt_properties_load( file );
- if ( properties != NULL )
- mlt_properties_pass( get_properties( ), properties, "" );
- mlt_properties_close( properties );
-}
-
-int Properties::save( const char *file )
-{
-#ifdef WIN32
- return mlt_properties_save( get_properties( ), file );
-#else
- int error = 0;
- FILE *f = fopen( file, "w" );
- if ( f != NULL )
- {
- dump( f );
- fclose( f );
- }
- else
- {
- error = 1;
- }
- return error;
-#endif
-}
-
-#if defined( __DARWIN__ ) && GCC_VERSION < 40000
-
-Event *Properties::listen( const char *id, void *object, void (*listener)( ... ) )
-{
- mlt_event event = mlt_events_listen( get_properties( ), object, id, ( mlt_listener )listener );
- return new Event( event );
-}
-
-#else
-
-Event *Properties::listen( const char *id, void *object, mlt_listener listener )
-{
- mlt_event event = mlt_events_listen( get_properties( ), object, id, listener );
- return new Event( event );
-}
-
-#endif
-
-Event *Properties::setup_wait_for( const char *id )
-{
- return new Event( mlt_events_setup_wait_for( get_properties( ), id ) );
-}
-
-void Properties::delete_event( Event *event )
-{
- delete event;
-}
-
-void Properties::wait_for( Event *event, bool destroy )
-{
- mlt_events_wait_for( get_properties( ), event->get_event( ) );
- if ( destroy )
- mlt_events_close_wait_for( get_properties( ), event->get_event( ) );
-}
-
+++ /dev/null
-/**
- * MltProperties.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_PROPERTIES_H_
-#define _MLTPP_PROPERTIES_H_
-
-#include "config.h"
-
-#include <stdio.h>
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class Event;
-
- /** Abstract Properties class.
- */
-
- class MLTPP_DECLSPEC Properties
- {
- private:
- mlt_properties instance;
- public:
- Properties( );
- Properties( bool dummy );
- Properties( Properties &properties );
- Properties( mlt_properties properties );
- Properties( const char *file );
- virtual ~Properties( );
- virtual mlt_properties get_properties( );
- int inc_ref( );
- int dec_ref( );
- int ref_count( );
- void block( void *object = NULL );
- void unblock( void *object = NULL );
- void fire_event( const char *event );
- bool is_valid( );
- int count( );
- char *get( const char *name );
- int get_int( const char *name );
- double get_double( const char *name );
- void *get_data( const char *name, int &size );
- void *get_data( const char *name );
- int set( const char *name, const char *value );
- int set( const char *name, int value );
- int set( const char *name, double value );
- int set( const char *name, void *value, int size, mlt_destructor destroy = NULL, mlt_serialiser serial = NULL );
- int pass_values( Properties &that, const char *prefix );
- int parse( const char *namevalue );
- char *get_name( int index );
- char *get( int index );
- void *get_data( int index, int &size );
- void mirror( Properties &that );
- int inherit( Properties &that );
- int rename( const char *source, const char *dest );
- void dump( FILE *output = stderr );
- void debug( const char *title = "Object", FILE *output = stderr );
- void load( const char *file );
- int save( const char *file );
- #if defined( __DARWIN__ ) && GCC_VERSION < 40000
- Event *listen( const char *id, void *object, void (*)( ... ) );
- #else
- Event *listen( const char *id, void *object, mlt_listener );
- #endif
- static void delete_event( Event * );
- Event *setup_wait_for( const char *id );
- void wait_for( Event *, bool destroy = true );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltPushConsumer.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltPushConsumer.h"
-#include "MltFilter.h"
-using namespace Mlt;
-
-namespace Mlt
-{
- class PushPrivate
- {
- public:
- PushPrivate( )
- {
- }
- };
-}
-
-static void filter_destructor( void *arg )
-{
- Filter *filter = ( Filter * )arg;
- delete filter;
-}
-
-PushConsumer::PushConsumer( Profile& profile, char *id , char *service ) :
- Consumer( profile, id, service ),
- m_private( new PushPrivate( ) )
-{
- if ( is_valid( ) )
- {
- // Set up push mode (known as put mode in mlt)
- set( "real_time", 0 );
- set( "put_mode", 1 );
- set( "terminate_on_pause", 0 );
- set( "buffer", 0 );
-
- // We might need resize and rescale filters so we'll create them now
- // NB: Try to use the best rescaler available here
- Filter *resize = new Filter( profile, "resize" );
- Filter *rescale = new Filter( profile, "mcrescale" );
- if ( !rescale->is_valid( ) )
- {
- delete rescale;
- rescale = new Filter( profile, "gtkrescale" );
- }
- if ( !rescale->is_valid( ) )
- {
- delete rescale;
- rescale = new Filter( profile, "rescale" );
- }
-
- Filter *convert = new Filter( profile, "avcolour_space" );
-
- set( "filter_convert", convert, 0, filter_destructor );
- set( "filter_resize", resize, 0, filter_destructor );
- set( "filter_rescale", rescale, 0, filter_destructor );
- }
-}
-
-PushConsumer::~PushConsumer( )
-{
-}
-
-void PushConsumer::set_render( int width, int height, double aspect_ratio )
-{
- set( "render_width", width );
- set( "render_height", height );
- set( "render_aspect_ratio", aspect_ratio );
-}
-
-int PushConsumer::connect( Service &/*service*/ )
-{
- return -1;
-}
-
-int PushConsumer::push( Frame *frame )
-{
- frame->inc_ref( );
-
- // Here we have the option to process the frame at a render resolution (this will
- // typically be PAL or NTSC) prior to scaling according to the consumers profile
- // This is done to optimise quality, esp. with regard to compositing positions
- if ( get_int( "render_width" ) )
- {
- // Process the projects render resolution first
- mlt_image_format format = mlt_image_yuv422;
- int w = get_int( "render_width" );
- int h = get_int( "render_height" );
- frame->set( "consumer_aspect_ratio", get_double( "render_aspect_ratio" ) );
- frame->set( "consumer_deinterlace", get_int( "deinterlace" ) );
- frame->set( "deinterlace_method", get_int( "deinterlace_method" ) );
- frame->set( "rescale.interp", get( "rescale" ) );
-
- // Render the frame
- frame->get_image( format, w, h );
-
- // Now set up the post image scaling
- Filter *convert = ( Filter * )get_data( "filter_convert" );
- mlt_filter_process( convert->get_filter( ), frame->get_frame( ) );
- Filter *rescale = ( Filter * )get_data( "filter_rescale" );
- mlt_filter_process( rescale->get_filter( ), frame->get_frame( ) );
- Filter *resize = ( Filter * )get_data( "filter_resize" );
- mlt_filter_process( resize->get_filter( ), frame->get_frame( ) );
- }
-
- return mlt_consumer_put_frame( ( mlt_consumer )get_service( ), frame->get_frame( ) );
-}
-
-int PushConsumer::push( Frame &frame )
-{
- return push( &frame );
-}
-
-int PushConsumer::drain( )
-{
- return 0;
-}
-
-// Convenience function - generates a frame with an image of a given size
-Frame *PushConsumer::construct( int size )
-{
- mlt_frame f = mlt_frame_init( get_service() );
- Frame *frame = new Frame( f );
- uint8_t *buffer = ( uint8_t * )mlt_pool_alloc( size );
- frame->set( "image", buffer, size, mlt_pool_release );
- mlt_frame_close( f );
- return frame;
-}
-
+++ /dev/null
-/**
- * MltPushConsumer.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef MLTPP_PUSH_CONSUMER_H
-#define MLTPP_PUSH_CONSUMER_H
-
-#include "config.h"
-
-#include "MltConsumer.h"
-
-namespace Mlt
-{
- class Frame;
- class Service;
- class PushPrivate;
- class Profile;
-
- class MLTPP_DECLSPEC PushConsumer : public Consumer
- {
- private:
- PushPrivate *m_private;
- public:
- PushConsumer( Profile& profile, char *id , char *service = NULL );
- virtual ~PushConsumer( );
- void set_render( int width, int height, double aspect_ratio );
- virtual int connect( Service &service );
- int push( Frame *frame );
- int push( Frame &frame );
- int drain( );
- Frame *construct( int );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltRepository.cpp - MLT Wrapper
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltRepository.h"
-#include "MltProfile.h"
-#include "MltProperties.h"
-using namespace Mlt;
-
-Repository::Repository( const char* directory ) :
- instance( NULL )
-{
- instance = mlt_repository_init( directory );
-}
-
-Repository::Repository( mlt_repository repository ) :
- instance( repository )
-{
-}
-
-Repository::~Repository( )
-{
- if ( instance )
- mlt_repository_close( instance );
- instance = NULL;
-}
-
-void Repository::register_service( mlt_service_type service_type, const char *service, mlt_register_callback symbol )
-{
- mlt_repository_register( instance, service_type, service, symbol );
-}
-
-void *Repository::create( Profile& profile, mlt_service_type type, const char *service, void *arg )
-{
- return mlt_repository_create( instance, profile.get_profile(), type, service, arg );
-}
-
-Properties *Repository::consumers( ) const
-{
- return new Properties( mlt_repository_consumers( instance ) );
-}
-
-Properties *Repository::filters( ) const
-{
- return new Properties( mlt_repository_filters( instance ) );
-}
-
-Properties *Repository::producers( ) const
-{
- return new Properties( mlt_repository_producers( instance ) );
-}
-
-Properties *Repository::transitions( ) const
-{
- return new Properties( mlt_repository_transitions( instance ) );
-}
-
-void Repository::register_metadata( mlt_service_type type, const char *service, mlt_metadata_callback callback, void *callback_data )
-{
- mlt_repository_register_metadata( instance, type, service, callback, callback_data );
-}
-
-Properties *Repository::metadata( mlt_service_type type, const char *service ) const
-{
- return new Properties( mlt_repository_metadata( instance, type, service ) );
-}
+++ /dev/null
-/**
- * MltRepository.h - MLT Wrapper
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_REPOSITORY_H_
-#define _MLTPP_REPOSITORY_H_
-
-#include "config.h"
-
-#ifdef SWIG
-#define MLTPP_DECLSPEC
-#endif
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class Profile;
- class Properties;
-
- class MLTPP_DECLSPEC Repository
- {
- private:
- mlt_repository instance;
- Repository( ) { }
- public:
- Repository( const char* directory );
- Repository( mlt_repository repository );
- ~Repository();
-
- void register_service( mlt_service_type service_type, const char *service, mlt_register_callback symbol );
- void *create( Profile& profile, mlt_service_type type, const char *service, void *arg );
- Properties *consumers( ) const;
- Properties *filters( ) const;
- Properties *producers( ) const;
- Properties *transitions( ) const;
- void register_metadata( mlt_service_type type, const char *service, mlt_metadata_callback, void *callback_data );
- Properties *metadata( mlt_service_type type, const char *service ) const;
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltService.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include "MltService.h"
-#include "MltFilter.h"
-#include "MltProfile.h"
-using namespace Mlt;
-
-Service::Service( ) :
- Properties( false ),
- instance( NULL )
-{
-}
-
-Service::Service( Service &service ) :
- Properties( false ),
- instance( service.get_service( ) )
-{
- inc_ref( );
-}
-
-Service::Service( mlt_service service ) :
- Properties( false ),
- instance( service )
-{
- inc_ref( );
-}
-
-Service::~Service( )
-{
- mlt_service_close( instance );
-}
-
-mlt_service Service::get_service( )
-{
- return instance;
-}
-
-mlt_properties Service::get_properties( )
-{
- return mlt_service_properties( get_service( ) );
-}
-
-void Service::lock( )
-{
- mlt_service_lock( get_service( ) );
-}
-
-void Service::unlock( )
-{
- mlt_service_unlock( get_service( ) );
-}
-
-int Service::connect_producer( Service &producer, int index )
-{
- return mlt_service_connect_producer( get_service( ), producer.get_service( ), index );
-}
-
-Service *Service::producer( )
-{
- return new Service( mlt_service_producer( get_service( ) ) );
-}
-
-Service *Service::consumer( )
-{
- return new Service( mlt_service_consumer( get_service( ) ) );
-}
-
-Profile *Service::profile( )
-{
- return new Profile( mlt_service_profile( get_service() ) );
-}
-
-Frame *Service::get_frame( int index )
-{
- mlt_frame frame = NULL;
- mlt_service_get_frame( get_service( ), &frame, index );
- Frame *result = new Frame( frame );
- mlt_frame_close( frame );
- return result;
-}
-
-mlt_service_type Service::type( )
-{
- return mlt_service_identify( get_service( ) );
-}
-
-int Service::attach( Filter &filter )
-{
- return mlt_service_attach( get_service( ), filter.get_filter( ) );
-}
-
-int Service::detach( Filter &filter )
-{
- return mlt_service_detach( get_service( ), filter.get_filter( ) );
-}
-
-Filter *Service::filter( int index )
-{
- mlt_filter result = mlt_service_filter( get_service( ), index );
- return result == NULL ? NULL : new Filter( result );
-}
-
+++ /dev/null
-/**
- * MltService.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_SERVICE_H_
-#define _MLTPP_SERVICE_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltProperties.h"
-#include "MltFrame.h"
-
-namespace Mlt
-{
- class Properties;
- class Filter;
- class Frame;
- class Profile;
-
- class MLTPP_DECLSPEC Service : public Properties
- {
- private:
- mlt_service instance;
- public:
- Service( );
- Service( Service &service );
- Service( mlt_service service );
- virtual ~Service( );
- virtual mlt_service get_service( );
- void lock( );
- void unlock( );
- virtual mlt_properties get_properties( );
- int connect_producer( Service &producer, int index = 0 );
- Service *consumer( );
- Service *producer( );
- Profile *profile( );
- Frame *get_frame( int index = 0 );
- mlt_service_type type( );
- int attach( Filter &filter );
- int detach( Filter &filter );
- Filter *filter( int index );
- };
-}
-
-#endif
+++ /dev/null
-/**
- * MltTokeniser.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include "MltTokeniser.h"
-using namespace Mlt;
-
-Tokeniser::Tokeniser( char *text, char *delimiter )
-{
- tokens = mlt_tokeniser_init( );
- if ( text != NULL )
- mlt_tokeniser_parse_new( tokens, text, delimiter );
-}
-
-Tokeniser::~Tokeniser( )
-{
- mlt_tokeniser_close( tokens );
-}
-
-int Tokeniser::parse( char *text, char *delimiter )
-{
- return mlt_tokeniser_parse_new( tokens, text, delimiter );
-}
-
-int Tokeniser::count( )
-{
- return mlt_tokeniser_count( tokens );
-}
-
-char *Tokeniser::get( int index )
-{
- return mlt_tokeniser_get_string( tokens, index );
-}
-
-char *Tokeniser::input( )
-{
- return mlt_tokeniser_get_input( tokens );
-}
-
+++ /dev/null
-/**
- * MltTokeniser.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_TOKENISER_H
-#define _MLTPP_TOKENISER_H
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-namespace Mlt
-{
- class MLTPP_DECLSPEC Tokeniser
- {
- private:
- mlt_tokeniser tokens;
- public:
- Tokeniser( char *text = NULL, char *delimiter = " " );
- ~Tokeniser( );
- int parse( char *text, char *delimiter = " " );
- int count( );
- char *get( int index );
- char *input( );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltTractor.cpp - Tractor wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "MltTractor.h"
-#include "MltMultitrack.h"
-#include "MltField.h"
-#include "MltTransition.h"
-#include "MltFilter.h"
-#include "MltPlaylist.h"
-using namespace Mlt;
-
-Tractor::Tractor( ) :
- instance( mlt_tractor_new( ) )
-{
-}
-
-Tractor::Tractor( Service &tractor ) :
- instance( NULL )
-{
- if ( tractor.type( ) == tractor_type )
- {
- instance = ( mlt_tractor )tractor.get_service( );
- inc_ref( );
- }
-}
-
-Tractor::Tractor( mlt_tractor tractor ) :
- instance( tractor )
-{
- inc_ref( );
-}
-
-Tractor::Tractor( Tractor &tractor ) :
- Mlt::Producer( tractor ),
- instance( tractor.get_tractor( ) )
-{
- inc_ref( );
-}
-
-Tractor::Tractor( Profile& profile, char *id, char *resource ) :
- instance( NULL )
-{
- Producer producer( profile, id, resource );
- if ( producer.is_valid( ) && producer.type( ) == tractor_type )
- {
- instance = ( mlt_tractor )producer.get_producer( );
- inc_ref( );
- }
- else if ( producer.is_valid( ) )
- {
- instance = mlt_tractor_new( );
- set_track( producer, 0 );
- }
-}
-
-Tractor::~Tractor( )
-{
- mlt_tractor_close( instance );
-}
-
-mlt_tractor Tractor::get_tractor( )
-{
- return instance;
-}
-
-mlt_producer Tractor::get_producer( )
-{
- return mlt_tractor_producer( get_tractor( ) );
-}
-
-Multitrack *Tractor::multitrack( )
-{
- return new Multitrack( mlt_tractor_multitrack( get_tractor( ) ) );
-}
-
-Field *Tractor::field( )
-{
- return new Field( mlt_tractor_field( get_tractor( ) ) );
-}
-
-void Tractor::refresh( )
-{
- return mlt_tractor_refresh( get_tractor( ) );
-}
-
-int Tractor::set_track( Producer &producer, int index )
-{
- return mlt_tractor_set_track( get_tractor( ), producer.get_producer( ), index );
-}
-
-Producer *Tractor::track( int index )
-{
- mlt_producer producer = mlt_tractor_get_track( get_tractor( ), index );
- return producer != NULL ? new Producer( producer ) : NULL;
-}
-
-int Tractor::count( )
-{
- return mlt_multitrack_count( mlt_tractor_multitrack( get_tractor( ) ) );
-}
-
-void Tractor::plant_transition( Transition &transition, int a_track, int b_track )
-{
- mlt_field_plant_transition( mlt_tractor_field( get_tractor( ) ), transition.get_transition( ), a_track, b_track );
-}
-
-void Tractor::plant_transition( Transition *transition, int a_track, int b_track )
-{
- if ( transition != NULL )
- mlt_field_plant_transition( mlt_tractor_field( get_tractor( ) ), transition->get_transition( ), a_track, b_track );
-}
-
-void Tractor::plant_filter( Filter &filter, int track )
-{
- mlt_field_plant_filter( mlt_tractor_field( get_tractor( ) ), filter.get_filter( ), track );
-}
-
-void Tractor::plant_filter( Filter *filter, int track )
-{
- mlt_field_plant_filter( mlt_tractor_field( get_tractor( ) ), filter->get_filter( ), track );
-}
-
-bool Tractor::locate_cut( Producer *producer, int &track, int &cut )
-{
- bool found = false;
-
- for ( track = 0; producer != NULL && !found && track < count( ); track ++ )
- {
- Playlist playlist( ( mlt_playlist )mlt_tractor_get_track( get_tractor( ), track ) );
- for ( cut = 0; !found && cut < playlist.count( ); cut ++ )
- {
- Producer *clip = playlist.get_clip( cut );
- found = producer->get_producer( ) == clip->get_producer( );
- delete clip;
- }
- }
-
- track --;
- cut --;
-
- return found;
-}
+++ /dev/null
-/**
- * MltTractor.h - Tractor wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_TRACTOR_H_
-#define _MLTPP_TRACTOR_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-
-#include "MltProducer.h"
-
-namespace Mlt
-{
- class Producer;
- class Field;
- class Multitrack;
- class Transition;
- class Filter;
- class Profile;
-
- class MLTPP_DECLSPEC Tractor : public Producer
- {
- private:
- mlt_tractor instance;
- public:
- Tractor( );
- Tractor( Service &tractor );
- Tractor( mlt_tractor tractor );
- Tractor( Tractor &tractor );
- Tractor( Profile& profile, char *id, char *arg = NULL );
- virtual ~Tractor( );
- virtual mlt_tractor get_tractor( );
- mlt_producer get_producer( );
- Multitrack *multitrack( );
- Field *field( );
- void refresh( );
- int set_track( Producer &producer, int index );
- Producer *track( int index );
- int count( );
- void plant_transition( Transition &transition, int a_track = 0, int b_track = 1 );
- void plant_transition( Transition *transition, int a_track = 0, int b_track = 1 );
- void plant_filter( Filter &filter, int track = 0 );
- void plant_filter( Filter *filter, int track = 0 );
- bool locate_cut( Producer *producer, int &track, int &cut );
- };
-}
-
-#endif
-
+++ /dev/null
-/**
- * MltTransition.cpp - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "MltTransition.h"
-#include "MltProfile.h"
-using namespace Mlt;
-
-Transition::Transition( Profile& profile, const char *id, const char *arg ) :
- instance( NULL )
-{
- if ( arg != NULL )
- {
- instance = mlt_factory_transition( profile.get_profile(), id, arg );
- }
- else
- {
- if ( strchr( id, ':' ) )
- {
- char *temp = strdup( id );
- char *arg = strchr( temp, ':' ) + 1;
- *( arg - 1 ) = '\0';
- instance = mlt_factory_transition( profile.get_profile(), temp, arg );
- free( temp );
- }
- else
- {
- instance = mlt_factory_transition( profile.get_profile(), id, NULL );
- }
- }
-}
-
-Transition::Transition( Service &transition ) :
- instance( NULL )
-{
- if ( transition.type( ) == transition_type )
- {
- instance = ( mlt_transition )transition.get_service( );
- inc_ref( );
- }
-}
-
-Transition::Transition( Transition &transition ) :
- Mlt::Service( transition ),
- instance( transition.get_transition( ) )
-{
- inc_ref( );
-}
-
-Transition::Transition( mlt_transition transition ) :
- instance( transition )
-{
- inc_ref( );
-}
-
-Transition::~Transition( )
-{
- mlt_transition_close( instance );
-}
-
-mlt_transition Transition::get_transition( )
-{
- return instance;
-}
-
-mlt_service Transition::get_service( )
-{
- return mlt_transition_service( get_transition( ) );
-}
-
-void Transition::set_in_and_out( int in, int out )
-{
- mlt_transition_set_in_and_out( get_transition( ), in, out );
-}
+++ /dev/null
-/**
- * MltTransition.h - MLT Wrapper
- * Copyright (C) 2004-2005 Charles Yates
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _MLTPP_TRANSITION_H_
-#define _MLTPP_TRANSITION_H_
-
-#include "config.h"
-
-#include <framework/mlt.h>
-#include "MltService.h"
-
-namespace Mlt
-{
- class Service;
- class Profile;
-
- class MLTPP_DECLSPEC Transition : public Service
- {
- private:
- mlt_transition instance;
- public:
- Transition( Profile& profile, const char *id, const char *arg = NULL );
- Transition( Service &transition );
- Transition( Transition &transition );
- Transition( mlt_transition transition );
- virtual ~Transition( );
- virtual mlt_transition get_transition( );
- mlt_service get_service( );
- void set_in_and_out( int in, int out );
- };
-}
-
-#endif
+++ /dev/null
-import net.sourceforge.mltpp.*;
-
-public class Play {
-
- static {
- System.loadLibrary("mltpp_java");
- }
-
- public static void main (String[] args) {
-
- // Start the mlt system
- Factory.init( null );
-
- // Set the output profile
- Profile profile = new Profile( "" );
-
- // Create the producer
- Producer p = new Producer( profile, args[0], null );
-
- if ( p.is_valid() ) {
-
- p.set ("eof", "loop");
-
- // Create the consumer
- Consumer c = new Consumer( profile, "sdl", null);
-
- // Turn off the default rescaling
- c.set("rescale", "none");
-
- // Connect the producer to the consumer
- c.connect(p);
-
- // Start the consumer
- c.start();
-
- // Wait until the user stops the consumer
- Object o = new Object();
- while ( !c.is_stopped() ) {
- synchronized (o) {
- try {
- o.wait(1000);
- } catch (InterruptedException e) {
- // ignored
- }
- }
- }
-
- // Stop it anyway
- c.stop();
- } else {
- System.out.println ("Unable to open " + args[0]);
- }
- }
-}
+++ /dev/null
-#!/usr/bin/env perl
-
-# Import required modules
-use mltpp;
-
-# Not sure why the mltpp::Factory.init method fails...
-mltpp::mlt_factory_init( undef );
-
-# Establish the MLT profile
-$profile = new mltpp::Profile( undef );
-
-# Create the producer
-$p = new mltpp::Producer( $profile, $ARGV[0] );
-
-if ( $p->is_valid( ) )
-{
- # Loop the video
- $p->set( "eof", "loop" );
-
- # Create the consumer
- $c = new mltpp::FilteredConsumer( $profile, "sdl" );
-
- # Turn of the default rescaling
- $c->set( "rescale", "none" );
-
- # Connect the producer to the consumer
- $c->connect( $p );
-
- $e = $c->setup_wait_for( "consumer-stopped" );
-
- # Start the consumer
- $c->start;
-
- # Wait until the user stops the consumer
- $c->wait_for( $e );
-
- $e = undef;
- $c = undef;
- $p = undef;
-}
-else
-{
- print "Unable to open $ARGV[0]\n";
-}
-
-mltpp::mlt_factory_close( );
+++ /dev/null
-<?php
-$filename = $argv[1];
-dl("mltpp.so");
-mlt_factory_init(NULL);
-$profile = new_profile("dv_ntsc");
-$p = new_producer( $profile, $filename );
-if ( $p ) {
- $c = new_consumer( $profile, "sdl" );
- consumer_connect( $c, $p );
- $e = properties_setup_wait_for( $c, "consumer-stopped" );
- consumer_start( $c );
- properties_wait_for( $c, $e );
- consumer_stop( $c );
- $e = NULL;
- $c = NULL;
-}
-$p = NULL;
-$profile = NULL;
-mlt_factory_close();
-?>
-
+++ /dev/null
-#!/usr/bin/env python
-
-# Import required modules
-import mltpp
-import time
-import sys
-
-# Start the mlt system
-mltpp.Factory().init( )
-
-# Establish a profile
-profile = mltpp.Profile( )
-
-# Create the producer
-p = mltpp.Producer( profile, sys.argv[1] )
-
-if p:
- # Create the consumer
- c = mltpp.Consumer( profile, "sdl" )
-
- # Turn off the default rescaling
- c.set( "rescale", "none" )
-
- # Connect the producer to the consumer
- c.connect( p )
-
- # Start the consumer
- c.start( )
-
- # Wait until the user stops the consumer
- while c.is_stopped( ) == 0:
- time.sleep( 1 )
-else:
- # Diagnostics
- print "Unable to open ", sys.argv[ 1 ]
-
+++ /dev/null
-#!/usr/bin/env ruby
-
-# Import required modules
-require 'mltpp'
-
-# Create the mlt system
-Mltpp::Factory::init
-
-# Establish the mlt profile
-profile = Mltpp::Profile.new
-
-# Get and check the argument
-file = ARGV.shift
-raise "Usage: test.rb file" if file.nil?
-
-# Create the producer
-producer = Mltpp::Factory::producer( profile, file )
-raise "Unable to load #{file}" if !producer.is_valid
-
-# Create the consumer
-consumer = Mltpp::Consumer.new( profile, "sdl" )
-raise "Unable to open sdl consumer" if !consumer.is_valid
-
-# Turn off the default rescaling
-consumer.set( "rescale", "none" )
-
-# Set up a 'wait for' event
-event = consumer.setup_wait_for( "consumer-stopped" )
-
-# Start the consumer
-consumer.start
-
-# Connect the producer to the consumer
-consumer.connect( producer )
-
-# Wait until the user stops the consumer
-consumer.wait_for( event )
-
-# Clean up consumer
-consumer.stop
-
+++ /dev/null
-#!/usr/bin/env ruby
-
-# Required modules
-require 'mltpp'
-
-# Create the mlt system
-Mltpp::Factory::init
-
-# Establish the mlt profile
-profile = Mltpp::Profile.new( "quarter_pal" )
-
-# Get and check the argument
-file = ARGV.shift
-name = ARGV.shift
-size = ARGV.shift
-size = "176x144" if size.nil?
-raise "Usage: thumbs.rb file name [ size ]" if file.nil? || name.nil?
-
-# Create the producer
-producer = Mltpp::Producer.new( profile, file )
-raise "Unable to load #{file}" if !producer.is_valid
-
-# Construct the playlist
-playlist = Mltpp::Playlist.new( )
-
-# Get the out point
-out = producer.get_int( "out" );
-
-# Calculate position of frames
-[ 0, 0.25, 0.5, 0.75, 1 ].each { |x| playlist.append( producer, Integer(x*out), Integer(x*out) ) }
-
-# Create the thumb nail generator
-generator = Mltpp::Consumer.new( profile, "avformat", "#{name}%d.jpg" )
-generator.set( "real_time", "0" )
-generator.set( "progressive", "1" )
-generator.set( "s", size )
-
-# Connect the consumer
-generator.connect( playlist );
-generator.run
-
+++ /dev/null
-#!/usr/bin/env tclsh
-
-load mltpp.so
-mltpp.Factory.init
-set profile [Profile]
-set arg1 [lindex $argv 0]
-set p [factory_producer $profile fezzik $arg1]
-set c [factory_consumer $profile sdl ""]
-set r [mlt_consumer_properties $c]
-mlt_properties_set $r "rescale" "none"
-consumer_connect $c $p
-mlt_consumer_start $c
-while { ![mlt_consumer_is_stopped $c] } {
- after 1000
-}
-mlt_consumer_close $c
-mlt_producer_close $p
-factory_close
+++ /dev/null
-
-#include <Mlt.h>
-using namespace Mlt;
-
-int main( int, char **argv )
-{
- Factory::init( NULL );
- Profile profile;
- Producer producer( profile, argv[ 1 ] );
- Consumer consumer( profile );
- consumer.set( "rescale", "none" );
- consumer.connect( producer );
- consumer.run( );
- return 0;
-}
+++ /dev/null
-
-Name: mlt-framework
-Description: MLT multimedia framework
-Version: ${version}
-Requires:
-Libs: -L${libdir} ${libs}
-Cflags: ${cflags}
+++ /dev/null
-include ../config.mak
-
-all:
-
-depend:
-
-distclean:
-
-clean:
-
-install: all uninstall
- install -d "$(DESTDIR)$(prefix)/share/mlt/profiles"
- install -m 644 * "$(DESTDIR)$(prefix)/share/mlt/profiles"
- rm -f "$(DESTDIR)$(prefix)/share/mlt/profiles/"*~
- rm -f "$(DESTDIR)$(prefix)/share/mlt/profiles/Makefile"
-
-uninstall:
- rm -rf "$(DESTDIR)$(prefix)/share/mlt/profiles"
+++ /dev/null
-description=ATSC 1080i 50Hz
-frame_rate_num=25
-frame_rate_den=1
-width=1920
-height=1080
-progressive=0
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080i 60Hz
-frame_rate_num=30000
-frame_rate_den=1001
-width=1920
-height=1080
-progressive=0
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080p 23.98Hz
-frame_rate_num=24000
-frame_rate_den=1001
-width=1920
-height=1080
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080p 24Hz
-frame_rate_num=24
-frame_rate_den=1
-width=1920
-height=1080
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080p 25Hz
-frame_rate_num=25
-frame_rate_den=1
-width=1920
-height=1080
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080p 29.97Hz
-frame_rate_num=30000
-frame_rate_den=1001
-width=1920
-height=1080
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 1080p 30Hz
-frame_rate_num=30
-frame_rate_den=1
-width=1920
-height=1080
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=ATSC 720p 30Hz
-frame_rate_num=30000
-frame_rate_den=1001
-width=1280
-height=720
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=CIF 15 fps
-frame_rate_num=15
-frame_rate_den=1
-width=352
-height=288
-progressive=1
-sample_aspect_num=59
-sample_aspect_den=54
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=CIF NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=352
-height=288
-progressive=1
-sample_aspect_num=10
-sample_aspect_den=11
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=CIF PAL
-frame_rate_num=25
-frame_rate_den=1
-width=352
-height=288
-progressive=1
-sample_aspect_num=59
-sample_aspect_den=54
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=CVD NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=352
-height=480
-progressive=0
-sample_aspect_num=20
-sample_aspect_den=11
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=CVD PAL
-frame_rate_num=25
-frame_rate_den=1
-width=352
-height=576
-progressive=0
-sample_aspect_num=59
-sample_aspect_den=27
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=DV NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=720
-height=480
-progressive=0
-sample_aspect_num=8
-sample_aspect_den=9
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=DV NTSC Widescreen
-frame_rate_num=30000
-frame_rate_den=1001
-width=720
-height=480
-progressive=0
-sample_aspect_num=32
-sample_aspect_den=27
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=DV PAL
-frame_rate_num=25
-frame_rate_den=1
-width=720
-height=576
-progressive=0
-sample_aspect_num=16
-sample_aspect_den=15
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=DV PAL Widescreen
-frame_rate_num=25
-frame_rate_den=1
-width=720
-height=576
-progressive=0
-sample_aspect_num=64
-sample_aspect_den=45
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 1080 25p
-frame_rate_num=25
-frame_rate_den=1
-width=1440
-height=1080
-progressive=1
-sample_aspect_num=4
-sample_aspect_den=3
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 1080 30p
-frame_rate_num=30000
-frame_rate_den=1001
-width=1440
-height=1080
-progressive=1
-sample_aspect_num=4
-sample_aspect_den=3
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 1080 50i
-frame_rate_num=25
-frame_rate_den=1
-width=1440
-height=1080
-progressive=0
-sample_aspect_num=4
-sample_aspect_den=3
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 1080 60i
-frame_rate_num=30000
-frame_rate_den=1001
-width=1440
-height=1080
-progressive=0
-sample_aspect_num=4
-sample_aspect_den=3
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 720 25p
-frame_rate_num=25
-frame_rate_den=1
-width=1280
-height=720
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 720 30p
-frame_rate_num=30000
-frame_rate_den=1001
-width=1280
-height=720
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 720 50p
-frame_rate_num=50
-frame_rate_den=1
-width=1280
-height=720
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=HDV 720 60p
-frame_rate_num=60000
-frame_rate_den=1001
-width=1280
-height=720
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=QCIF 15fps
-frame_rate_num=15
-frame_rate_den=1
-width=176
-height=144
-progressive=1
-sample_aspect_num=59
-sample_aspect_den=54
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=QCIF NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=176
-height=144
-progressive=1
-sample_aspect_num=10
-sample_aspect_den=11
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=QCIF PAL
-frame_rate_num=25
-frame_rate_den=1
-width=176
-height=144
-progressive=1
-sample_aspect_num=59
-sample_aspect_den=54
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=QVGA 15fps
-frame_rate_num=15
-frame_rate_den=1
-width=320
-height=240
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=Quarter Square NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=320
-height=240
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=Quarter Square NTSC Widescreen
-frame_rate_num=30000
-frame_rate_den=1001
-width=426
-height=240
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=Quarter Square PAL
-frame_rate_num=25
-frame_rate_den=1
-width=384
-height=288
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=Quarter Square PAL Widescreen
-frame_rate_num=25
-frame_rate_den=1
-width=512
-height=288
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=Square NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=640
-height=480
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=Square NTSC Widescreen
-frame_rate_num=30000
-frame_rate_den=1001
-width=854
-height=480
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=Square PAL
-frame_rate_num=25
-frame_rate_den=1
-width=768
-height=576
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=Square PAL Widescreen
-frame_rate_num=25
-frame_rate_den=1
-width=1024
-height=576
-progressive=1
-sample_aspect_num=1
-sample_aspect_den=1
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=SVCD NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=480
-height=480
-progressive=0
-sample_aspect_num=15
-sample_aspect_den=11
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=SVCD NTSC Widescreen
-frame_rate_num=30000
-frame_rate_den=1001
-width=480
-height=480
-progressive=0
-sample_aspect_num=20
-sample_aspect_den=11
-display_aspect_num=16
-display_aspect_den=9
+++ /dev/null
-description=SVCD PAL
-frame_rate_num=25
-frame_rate_den=1
-width=480
-height=576
-progressive=0
-sample_aspect_num=59
-sample_aspect_den=36
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=SVCD PAL Widescreen
-frame_rate_num=25
-frame_rate_den=1
-width=480
-height=576
-progressive=0
-sample_aspect_num=59
-sample_aspect_den=27
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=VCD NTSC
-frame_rate_num=30000
-frame_rate_den=1001
-width=352
-height=240
-progressive=1
-sample_aspect_num=10
-sample_aspect_den=11
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-description=VCD PAL
-frame_rate_num=25
-frame_rate_den=1
-width=352
-height=288
-progressive=1
-sample_aspect_num=59
-sample_aspect_den=54
-display_aspect_num=4
-display_aspect_den=3
+++ /dev/null
-
-# Environment variable settings to allow execution without install
-
-export MLT_REPOSITORY=`pwd`/src/modules
-export MLT_DATA=`pwd`/src/modules
-export MLT_PROFILES_PATH=`pwd`/profiles
-
-export LD_LIBRARY_PATH=\
-`pwd`/src/framework:\
-`pwd`/src/valerie:\
-`pwd`/src/miracle:\
-`pwd`/src/modules/bluefish:\
-`pwd`/../BlueLinuxDriver/install/lib:\
-`pwd`/../mpeg_sdk_release/bin:\
-`pwd`/../dvcpro_sdk_release/lib:\
-`pwd`/../sr_sdk_release:\
-$LD_LIBRARY_PATH
-
-[ $(uname -s) = Darwin ] && export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
-
-export PATH=\
-`pwd`/src/albino:\
-`pwd`/src/inigo:\
-`pwd`/src/humperdink:\
-`pwd`/src/miracle:\
-$PATH
+++ /dev/null
-
-# Environment variable settings to allow execution without install
-
-export LD_LIBRARY_PATH=\
-`pwd`/../mpeg_sdk_release/bin:\
-`pwd`/../dvcpro_sdk_release/lib:\
-`pwd`/../sr_sdk_release/lib:\
-$LD_LIBRARY_PATH
-
+++ /dev/null
-include ../../config.mak
-
-NAME = libmlt$(LIBSUF)
-TARGET = $(NAME).$(version)
-
-ifneq ($(targetos), Darwin)
-NAME = libmlt$(LIBSUF)
-TARGET = $(NAME).$(version)
-SONAME = $(NAME).$(soversion)
-SHFLAGS += -Wl,-soname,$(SONAME)
-else
-NAME = libmlt$(LIBSUF)
-TARGET = libmlt.$(version)$(LIBSUF)
-SONAME = libmlt.$(soversion)$(LIBSUF)
-SHFLAGS += -install_name $(libdir)/$(SONAME) -current_version $(version) -compatibility_version $(soversion)
-endif
-
-OBJS = mlt_frame.o \
- mlt_geometry.o \
- mlt_deque.o \
- mlt_property.o \
- mlt_properties.o \
- mlt_events.o \
- mlt_parser.o \
- mlt_service.o \
- mlt_producer.o \
- mlt_multitrack.o \
- mlt_playlist.o \
- mlt_consumer.o \
- mlt_filter.o \
- mlt_transition.o \
- mlt_field.o \
- mlt_tractor.o \
- mlt_factory.o \
- mlt_repository.o \
- mlt_pool.o \
- mlt_tokeniser.o \
- mlt_profile.o \
- mlt_log.o \
- mlt_cache.o
-
-INCS = mlt_consumer.h \
- mlt_factory.h \
- mlt_filter.h \
- mlt.h \
- mlt_multitrack.h \
- mlt_pool.h \
- mlt_properties.h \
- mlt_events.h \
- mlt_parser.h \
- mlt_repository.h \
- mlt_tractor.h \
- mlt_types.h \
- mlt_deque.h \
- mlt_field.h \
- mlt_frame.h \
- mlt_geometry.h \
- mlt_playlist.h \
- mlt_producer.h \
- mlt_property.h \
- mlt_service.h \
- mlt_transition.h \
- mlt_tokeniser.h \
- mlt_profile.h \
- mlt_log.h \
- mlt_cache.h
-
-SRCS := $(OBJS:.o=.c)
-
-CFLAGS += $(RDYNAMIC) -DPREFIX="\"$(prefix)\"" -DLIBDIR="\"$(libdir)\""
-
-LDFLAGS += -lm $(LIBDL) -lpthread
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
- ln -sf $(TARGET) $(NAME)
- ln -sf $(TARGET) $(SONAME)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET) $(NAME)
-
-install:
- install -d $(DESTDIR)$(libdir)
- install -m 755 $(TARGET) $(DESTDIR)$(libdir)
- ln -sf $(TARGET) $(DESTDIR)$(libdir)/$(SONAME)
- ln -sf $(TARGET) $(DESTDIR)$(libdir)/$(NAME)
- install -d "$(DESTDIR)$(prefix)/include/mlt/framework"
- install -m 644 $(INCS) "$(DESTDIR)$(prefix)/include/mlt/framework"
- install -d "$(DESTDIR)$(prefix)/share/mlt"
- install -m 644 metaschema.yaml "$(DESTDIR)$(prefix)/share/mlt/"
-
-uninstall:
- rm -f "$(DESTDIR)$(libdir)/$(TARGET)"
- rm -f "$(DESTDIR)$(libdir)/$(SONAME)"
- rm -f "$(DESTDIR)$(libdir)/$(NAME)"
- rm -rf "$(DESTDIR)$(prefix)/include/mlt/framework"
- rm "$(DESTDIR)$(prefix)/share/mlt/metaschema.yaml"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-echo "framework -I$prefix/include -I$prefix/include/mlt -D_REENTRANT -L$libdir -lmlt" >> ../../packages.dat
+++ /dev/null
---- # A metadata schema in Kwalify: http://www.kuwata-lab.com/kwalify/
-# Version: 0.1
-type: map
-mapping:
- "schema_version": # This should match the version comment above
- type: float
- required: yes
- "type": # A service type
- type: str
- required: yes
- enum: [consumer, filter, producer, transition]
- "identifier": # The same value used to register and create the service
- type: str
- required: yes
- unique: yes
- "title": # The UI can use this for a field label
- type: str
- "copyright": # Who owns the rights to the module and/or service?
- type: str
- "version": # The version of the service implementation
- type: text
- "license": # The software license for the service implementation
- type: str
- "language": # A 2 character ISO 639-1 language code
- type: str
- required: yes
- "url": # A hyperlink to a related website
- type: str
- "creator": # The name and/or e-mail address of the original author
- type: str
- "contributor": # The name and/or e-mail of all source code contributors
- type: seq
- sequence:
- - type: str
- "tags": # A set of categories, this might become an enum
- type: seq
- sequence:
- - type: str
- "description": # A slightly longer description than title
- type: str
- "icon": # A graphical representation of the effect
- type: map
- mapping:
- "filename":
- type: str
- "content-type":
- type: str
- "content-encoding":
- type: str
- "content":
- type: str
- "notes": # Details about the usage and/or implementation - can be long
- type: str
- "bugs": # A list of known problems that users can try to avoid
- type: seq
- sequence:
- - type: str # Can be a sentence or paragraph, preferably not a hyperlink
- "parameters": # A list of all of the options for the service
- type: seq
- sequence:
- - type: map
- mapping:
- "identifier": # The key that must be used to set the mlt_property
- type: str
- required: yes
- "type": # An mlt_property_type
- type: str
- enum:
- - float
- - geometry
- - integer
- - properties # for passing options to encapsulated services
- - string
- - time # currently, mlt_position (frame), soon to be a time value
- "service-name": # for type: properties, a reference to another service
- type: str # format: type.service, e.g. transition.composite
- "title": # A UI can use this for a field label
- type: str
- "description": # A UI can use this for a tool tip or what's-this
- type: str
- "readonly": # If you set this property, it will be ignored
- type: bool
- default: no
- "required": # Is this property required?
- type: bool
- default: no
- "mutable": # The service will change behavior if this is set after
- # processing the first frame
- type: bool
- default: no
- "widget": # A hint to the UI about how to let the user set this
- type: str
- enum:
- - checkbox
- - color
- - combo
- - curve
- - directory
- - fileopen
- - filesave
- - font
- - knob
- - listbox
- - dropdown # aka HTML select or GtkOptionMenu
- - radio
- - rectangle # for use with type: geometry
- - slider
- - spinner
- - text
- - textbox # multi-line
- - timecode
- "minimum": # For numeric types, the minimal value
- type: number
- "maximum": # For numeric types, the maximal value
- type: number
- "default": # The default value to be used in a UI
- type: scalar # If not specified, the UI might be able to display
- # this as blank
- "unit": # A UI can display this as a label after the widget (e.g. %)
- type: str
- "scale": # the number of digits after decimal point when type: float
- type: int
- "format": # A hint about a custom string encoding, possibly scanf
- "values": # A list of acceptable string values
- type: seq # A UI can allow something outside the list with
- # widget: combo or if "other" is in this sequence
- sequence:
- - type: scalar
-
+++ /dev/null
-/**
- * \file mlt.h
- * \brief header file for lazy client and implementation code :-)
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_H_
-#define _MLT_H_
-
-#define LIBMLT_VERSION_INT ((0<<16)+(3<<8)+9)
-#define LIBMLT_VERSION 0.3.9
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "mlt_factory.h"
-#include "mlt_frame.h"
-#include "mlt_deque.h"
-#include "mlt_multitrack.h"
-#include "mlt_producer.h"
-#include "mlt_transition.h"
-#include "mlt_consumer.h"
-#include "mlt_filter.h"
-#include "mlt_playlist.h"
-#include "mlt_properties.h"
-#include "mlt_field.h"
-#include "mlt_tractor.h"
-#include "mlt_tokeniser.h"
-#include "mlt_parser.h"
-#include "mlt_geometry.h"
-#include "mlt_profile.h"
-#include "mlt_repository.h"
-#include "mlt_log.h"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_profile.c
- * \brief least recently used cache
- * \see mlt_profile_s
- *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_types.h"
-#include "mlt_log.h"
-#include "mlt_properties.h"
-#include "mlt_cache.h"
-
-#include <stdlib.h>
-#include <pthread.h>
-
-/** the maximum number of data objects to cache per line */
-#define CACHE_SIZE (10)
-
-/** \brief Cache item class
- *
- * A cache item is a structure holding information about a data object including
- * a reference count that is used to control its lifetime. When you get a
- * a cache item from the cache, you hold a reference that prevents the data
- * from being released when the cache is full and something new is added.
- * When you close the cache item, the reference count is decremented.
- * The data object is destroyed when all cache items are closed and the cache
- * releases its reference.
- */
-
-typedef struct mlt_cache_item_s
-{
- mlt_cache cache; /**< a reference to the cache to which this belongs */
- void *object; /**< a parent object to the cache data that uniquely identifies this cached item */
- void *data; /**< the opaque pointer to the cached data */
- int size; /**< the size of the cached data */
- int refcount; /**< a reference counter to control when destructor is called */
- mlt_destructor destructor; /**< a function to release or destroy the cached data */
-} mlt_cache_item_s;
-
-/** \brief Cache class
- *
- * This is a utility class for implementing a Least Recently Used (LRU) cache
- * of data blobs indexed by the address of some other object (e.g., a service).
- * Instead of sorting and manipulating linked lists, it tries to be simple and
- * elegant by copying pointers between two arrays of fixed size to shuffle the
- * order of elements.
- *
- * This class is useful if you have a service that wants to cache something
- * somewhat large, but will not scale if there are many instances of the service.
- * Of course, the service will need to know how to recreate the cached element
- * if it gets flushed from the cache,
- *
- * The most obvious examples are the pixbuf and qimage producers that cache their
- * respective objects representing a picture read from a file. If the picture
- * is no longer in the cache, it can simply re-read it from file. However, a
- * picture is often repeated over many frames and makes sense to cache instead
- * of continually reading, parsing, and decoding. On the other hand, you might
- * want to load hundreds of pictures as individual producers, which would use
- * a lot of memory if every picture is held in memory!
- */
-
-struct mlt_cache_s
-{
- int count; /**< the number of items currently in the cache */
- void* *current; /**< pointer to the current array of pointers */
- void* A[ CACHE_SIZE ];
- void* B[ CACHE_SIZE ];
- pthread_mutex_t mutex; /**< a mutex to prevent multi-threaded race conditions */
- mlt_properties active; /**< a list of cache items some of which may no longer
- be in \p current but to which there are
- outstanding references */
- mlt_properties garbage;/**< a list cache items pending release. A cache item
- is copied to this list when it is updated but there
- are outstanding references to the old data object. */
-};
-
-/** Get the data pointer from the cache item.
- *
- * \public \memberof mlt_cache_s
- * \param item a cache item
- * \param[out] size the number of bytes pointed at, if supplied when putting the data into the cache
- * \return the data pointer
- */
-
-void *mlt_cache_item_data( mlt_cache_item item, int *size )
-{
- if ( size && item )
- *size = item->size;
- return item? item->data : NULL;
-}
-
-/** Close a cache item given its parent object pointer.
- *
- * \private \memberof mlt_cache_s
- * \param cache a cache
- * \param object the object to which the data object belongs
- * \param data the data object, which might be in the garbage list (optional)
- */
-
-static void cache_object_close( mlt_cache cache, void *object, void* data )
-{
- char key[19];
-
- // Fetch the cache item from the active list by its owner's address
- sprintf( key, "%p", object );
- pthread_mutex_lock( &cache->mutex );
- mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
- if ( item )
- {
- mlt_log( NULL, MLT_LOG_DEBUG, "%s: item %p object %p data %p refcount %d\n", __FUNCTION__,
- item, item->object, item->data, item->refcount );
- if ( item->destructor && --item->refcount <= 0 )
- {
- // Destroy the data object
- item->destructor( item->data );
- item->data = NULL;
- item->destructor = NULL;
- // Do not dispose of the cache item because it could likely be used
- // again.
- }
- }
-
- // Fetch the cache item from the garbage collection by its data address
- if ( data )
- {
- sprintf( key, "%p", data );
- item = mlt_properties_get_data( cache->garbage, key, NULL );
- if ( item )
- {
- mlt_log( NULL, MLT_LOG_DEBUG, "collecting garbage item %p object %p data %p refcount %d\n",
- item, item->object, item->data, item->refcount );
- if ( item->destructor && --item->refcount <= 0 )
- {
- item->destructor( item->data );
- item->data = NULL;
- item->destructor = NULL;
- // We do not need the garbage-collected cache item
- mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL );
- }
- }
- }
- pthread_mutex_unlock( &cache->mutex );
-}
-
-/** Close a cache item.
- *
- * Release a reference and call the destructor on the data object when all
- * references are released.
- *
- * \public \memberof mlt_cache_item_s
- * \param item a cache item
- */
-
-void mlt_cache_item_close( mlt_cache_item item )
-{
- if ( item )
- cache_object_close( item->cache, item->object, item->data );
-}
-
-/** Create a new cache.
- *
- * \public \memberof mlt_cache_s
- * \return a new cache or NULL if there was an error
- */
-
-mlt_cache mlt_cache_init()
-{
- mlt_cache result = calloc( 1, sizeof( struct mlt_cache_s ) );
- if ( result )
- {
- result->current = result->A;
- pthread_mutex_init( &result->mutex, NULL );
- result->active = mlt_properties_new();
- result->garbage = mlt_properties_new();
- }
- return result;
-}
-
-/** Destroy a cache.
- *
- * \public \memberof mlt_cache_s
- * \param cache the cache to detroy
- */
-
-void mlt_cache_close( mlt_cache cache )
-{
- if ( cache )
- {
- while ( cache->count-- )
- {
- void *object = cache->current[ cache->count ];
- mlt_log( NULL, MLT_LOG_DEBUG, "%s: %d = %p\n", __FUNCTION__, cache->count, object );
- cache_object_close( cache, object, NULL );
- }
- mlt_properties_close( cache->active );
- mlt_properties_close( cache->garbage );
- pthread_mutex_destroy( &cache->mutex );
- free( cache );
- }
-}
-
-/** Remove cache entries for an object.
- *
- * \public \memberof mlt_cache_s
- * \param cache a cache
- * \param object the object that owns the cached data
- */
-
-void mlt_cache_purge( mlt_cache cache, void *object )
-{
- pthread_mutex_lock( &cache->mutex );
- if ( cache && object )
- {
- int i, j;
- void **alt = cache->current == cache->A ? cache->B : cache->A;
-
- for ( i = 0, j = 0; i < cache->count; i++ )
- {
- void *o = cache->current[ i ];
-
- if ( o == object )
- {
- pthread_mutex_unlock( &cache->mutex );
- cache_object_close( cache, o, NULL );
- pthread_mutex_lock( &cache->mutex );
- }
- else
- {
- alt[ j++ ] = o;
- }
- }
- cache->count = j;
- cache->current = alt;
-
- // Remove the object's data from the active list regardless of refcount
- char key[19];
- sprintf( key, "%p", object );
- mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
- if ( item && item->destructor )
- {
- item->destructor( item->data );
- item->data = NULL;
- item->destructor = NULL;
- mlt_properties_set_data( cache->active, key, NULL, 0, NULL, NULL );
- }
-
- // Remove the object's items from the garbage collection regardless of refcount
- i = mlt_properties_count( cache->garbage );
- while ( i-- )
- {
- item = mlt_properties_get_data_at( cache->garbage, i, NULL );
- if ( object == item->object && item->destructor )
- {
- sprintf( key, "%p", item->data );
- item->destructor( item->data );
- item->data = NULL;
- item->destructor = NULL;
- mlt_properties_set_data( cache->garbage, key, NULL, 0, NULL, NULL );
- }
- }
- }
- pthread_mutex_unlock( &cache->mutex );
-}
-
-/** Shuffle the cache entries between the two arrays and return the cache entry for an object.
- *
- * \private \memberof mlt_cache_s
- * \param cache a cache object
- * \param object the object that owns the cached data
- * \return a cache entry if there was a hit or NULL for a miss
- */
-
-static void** shuffle_get_hit( mlt_cache cache, void *object )
-{
- int i = cache->count;
- int j = cache->count - 1;
- void **hit = NULL;
- void **alt = cache->current == cache->A ? cache->B : cache->A;
-
- if ( cache->count > 0 && cache->count < CACHE_SIZE )
- {
- // first determine if we have a hit
- while ( i-- && !hit )
- {
- void **o = &cache->current[ i ];
- if ( *o == object )
- hit = o;
- }
- // if there was no hit, we will not be shuffling out an entry
- // and are still filling the cache
- if ( !hit )
- ++j;
- // reset these
- i = cache->count;
- hit = NULL;
- }
-
- // shuffle the existing entries to the alternate array
- while ( i-- )
- {
- void **o = &cache->current[ i ];
-
- if ( !hit && *o == object )
- {
- hit = o;
- }
- else if ( j > 0 )
- {
- alt[ --j ] = *o;
-// mlt_log( NULL, MLT_LOG_DEBUG, "%s: shuffle %d = %p\n", __FUNCTION__, j, alt[j] );
- }
- }
- return hit;
-}
-
-/** Put a chunk of data in the cache.
- *
- * \public \memberof mlt_cache_s
- * \param cache a cache object
- * \param object the object to which this data belongs
- * \param data an opaque pointer to the data to cache
- * \param size the size of the data in bytes
- * \param destructor a pointer to a function that can destroy or release a reference to the data.
- */
-
-void mlt_cache_put( mlt_cache cache, void *object, void* data, int size, mlt_destructor destructor )
-{
- pthread_mutex_lock( &cache->mutex );
- void **hit = shuffle_get_hit( cache, object );
- void **alt = cache->current == cache->A ? cache->B : cache->A;
-
- // add the object to the cache
- if ( hit )
- {
- // release the old data
- pthread_mutex_unlock( &cache->mutex );
- cache_object_close( cache, *hit, NULL );
- pthread_mutex_lock( &cache->mutex );
- // the MRU end gets the updated data
- hit = &alt[ cache->count - 1 ];
- }
- else if ( cache->count < CACHE_SIZE )
- {
- // more room in cache, add it to MRU end
- hit = &alt[ cache->count++ ];
- }
- else
- {
- // release the entry at the LRU end
- pthread_mutex_unlock( &cache->mutex );
- cache_object_close( cache, cache->current[0], NULL );
- pthread_mutex_lock( &cache->mutex );
-
- // The MRU end gets the new item
- hit = &alt[ cache->count - 1 ];
- }
- *hit = object;
- mlt_log( NULL, MLT_LOG_DEBUG, "%s: put %d = %p, %p\n", __FUNCTION__, cache->count - 1, object, data );
-
- // Fetch the cache item
- char key[19];
- sprintf( key, "%p", object );
- mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
- if ( !item )
- {
- item = calloc( 1, sizeof( mlt_cache_item_s ) );
- if ( item )
- mlt_properties_set_data( cache->active, key, item, 0, free, NULL );
- }
- if ( item )
- {
- // If updating the cache item but not all references are released
- // copy the item to the garbage collection.
- if ( item->refcount > 0 && item->data )
- {
- mlt_cache_item orphan = calloc( 1, sizeof( mlt_cache_item_s ) );
- if ( orphan )
- {
- mlt_log( NULL, MLT_LOG_DEBUG, "adding to garbage collection object %p data %p\n", item->object, item->data );
- *orphan = *item;
- sprintf( key, "%p", orphan->data );
- // We store in the garbage collection by data address, not the owner's!
- mlt_properties_set_data( cache->garbage, key, orphan, 0, free, NULL );
- }
- }
-
- // Set/update the cache item
- item->cache = cache;
- item->object = object;
- item->data = data;
- item->size = size;
- item->destructor = destructor;
- item->refcount = 1;
- }
-
- // swap the current array
- cache->current = alt;
- pthread_mutex_unlock( &cache->mutex );
-}
-
-/** Get a chunk of data from the cache.
- *
- * \public \memberof mlt_cache_s
- * \param cache a cache object
- * \param object the object for which you are trying to locate the data
- * \return a mlt_cache_item if found or NULL if not found or has been flushed from the cache
- */
-
-mlt_cache_item mlt_cache_get( mlt_cache cache, void *object )
-{
- mlt_cache_item result = NULL;
- pthread_mutex_lock( &cache->mutex );
- void **hit = shuffle_get_hit( cache, object );
- void **alt = cache->current == cache->A ? cache->B : cache->A;
-
- if ( hit )
- {
- // copy the hit to the MRU end
- alt[ cache->count - 1 ] = *hit;
- hit = &alt[ cache->count - 1 ];
-
- char key[19];
- sprintf( key, "%p", *hit );
- result = mlt_properties_get_data( cache->active, key, NULL );
- if ( result && result->data )
- result->refcount++;
- mlt_log( NULL, MLT_LOG_DEBUG, "%s: get %d = %p, %p\n", __FUNCTION__, cache->count - 1, *hit, result->data );
-
- // swap the current array
- cache->current = alt;
- }
- pthread_mutex_unlock( &cache->mutex );
-
- return result;
-}
+++ /dev/null
-/**
- * \file mlt_cache.h
- * \brief least recently used cache
- * \see mlt_cache_s
- *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_CACHE_H
-#define _MLT_CACHE_H
-
-#include "mlt_types.h"
-
-extern void *mlt_cache_item_data( mlt_cache_item item, int *size );
-extern void mlt_cache_item_close( mlt_cache_item item );
-
-extern mlt_cache mlt_cache_init();
-extern void mlt_cache_close( mlt_cache cache );
-extern void mlt_cache_purge( mlt_cache cache, void *object );
-extern void mlt_cache_put( mlt_cache cache, void *object, void* data, int size, mlt_destructor destructor );
-extern mlt_cache_item mlt_cache_get( mlt_cache cache, void *object );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_consumer.c
- * \brief abstraction for all consumer services
- * \see mlt_consumer_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_consumer.h"
-#include "mlt_factory.h"
-#include "mlt_producer.h"
-#include "mlt_frame.h"
-#include "mlt_profile.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-
-/** Define this if you want an automatic deinterlace (if necessary) when the
- * consumer's producer is not running at normal speed.
- */
-#undef DEINTERLACE_ON_NOT_NORMAL_SPEED
-
-static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args );
-static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service this, void **args );
-static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name );
-static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties );
-
-/** Initialize a consumer service.
- *
- * \public \memberof mlt_consumer_s
- * \param this the consumer to initialize
- * \param child a pointer to the object for the subclass
- * \param profile the \p mlt_profile_s to use (optional but recommended,
- * uses the environment variable MLT if this is NULL)
- * \return true if there was an error
- */
-
-int mlt_consumer_init( mlt_consumer this, void *child, mlt_profile profile )
-{
- int error = 0;
- memset( this, 0, sizeof( struct mlt_consumer_s ) );
- this->child = child;
- error = mlt_service_init( &this->parent, this );
- if ( error == 0 )
- {
- // Get the properties from the service
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
-
- // Apply profile to properties
- if ( profile == NULL )
- {
- // Normally the application creates the profile and controls its lifetime
- // This is the fallback exception handling
- profile = mlt_profile_init( NULL );
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_properties_set_data( properties, "_profile", profile, 0, (mlt_destructor)mlt_profile_close, NULL );
- }
- apply_profile_properties( this, profile, properties );
-
- // Default rescaler for all consumers
- mlt_properties_set( properties, "rescale", "bilinear" );
-
- // Default read ahead buffer size
- mlt_properties_set_int( properties, "buffer", 25 );
-
- // Default audio frequency and channels
- mlt_properties_set_int( properties, "frequency", 48000 );
- mlt_properties_set_int( properties, "channels", 2 );
-
- // Default of all consumers is real time
- mlt_properties_set_int( properties, "real_time", 1 );
-
- // Default to environment test card
- mlt_properties_set( properties, "test_card", mlt_environment( "MLT_TEST_CARD" ) );
-
- // Hmm - default all consumers to yuv422 :-/
- this->format = mlt_image_yuv422;
-
- 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 );
- mlt_events_register( properties, "consumer-stopped", NULL );
-
- // Register a property-changed listener to handle the profile property -
- // subsequent properties can override the profile
- this->event_listener = mlt_events_listen( properties, this, "property-changed", ( mlt_listener )mlt_consumer_property_changed );
-
- // Create the push mutex and condition
- pthread_mutex_init( &this->put_mutex, NULL );
- pthread_cond_init( &this->put_cond, NULL );
-
- }
- return error;
-}
-
-/** Convert the profile into properties on the consumer.
- *
- * \private \memberof mlt_consumer_s
- * \param this a consumer
- * \param profile a profile
- * \param properties a properties list (typically, the consumer's)
- */
-
-static void apply_profile_properties( mlt_consumer this, mlt_profile profile, mlt_properties properties )
-{
- mlt_event_block( this->event_listener );
- mlt_properties_set_double( properties, "fps", mlt_profile_fps( profile ) );
- mlt_properties_set_int( properties, "frame_rate_num", profile->frame_rate_num );
- mlt_properties_set_int( properties, "frame_rate_den", profile->frame_rate_den );
- mlt_properties_set_int( properties, "width", profile->width );
- mlt_properties_set_int( properties, "height", profile->height );
- mlt_properties_set_int( properties, "progressive", profile->progressive );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
- mlt_properties_set_int( properties, "sample_aspect_num", profile->sample_aspect_num );
- mlt_properties_set_int( properties, "sample_aspect_den", profile->sample_aspect_den );
- mlt_properties_set_double( properties, "display_ratio", mlt_profile_dar( profile ) );
- mlt_properties_set_int( properties, "display_aspect_num", profile->display_aspect_num );
- mlt_properties_set_int( properties, "display_aspect_num", profile->display_aspect_num );
- mlt_event_unblock( this->event_listener );
-}
-
-/** The property-changed event listener
- *
- * \private \memberof mlt_consumer_s
- * \param owner the service a service (ignored)
- * \param this the consumer
- * \param name the name of the property that changed
- */
-
-static void mlt_consumer_property_changed( mlt_service owner, mlt_consumer this, char *name )
-{
- if ( !strcmp( name, "profile" ) )
- {
- // Get the properies
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the current profile
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
-
- // Load the new profile
- mlt_profile new_profile = mlt_profile_init( mlt_properties_get( properties, name ) );
-
- if ( new_profile )
- {
- // Copy the profile
- if ( profile != NULL )
- {
- free( profile->description );
- memcpy( profile, new_profile, sizeof( struct mlt_profile_s ) );
- profile->description = strdup( new_profile->description );
- mlt_profile_close( new_profile );
- }
- else
- {
- profile = new_profile;
- }
-
- // Apply to properties
- apply_profile_properties( this, profile, properties );
- }
- }
- else if ( !strcmp( name, "frame_rate_num" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->frame_rate_num = mlt_properties_get_int( properties, "frame_rate_num" );
- mlt_properties_set_double( properties, "fps", mlt_profile_fps( profile ) );
- }
- }
- else if ( !strcmp( name, "frame_rate_den" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->frame_rate_den = mlt_properties_get_int( properties, "frame_rate_den" );
- mlt_properties_set_double( properties, "fps", mlt_profile_fps( profile ) );
- }
- }
- else if ( !strcmp( name, "width" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- profile->width = mlt_properties_get_int( properties, "width" );
- }
- else if ( !strcmp( name, "height" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- profile->height = mlt_properties_get_int( properties, "height" );
- }
- else if ( !strcmp( name, "progressive" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- profile->progressive = mlt_properties_get_int( properties, "progressive" );
- }
- else if ( !strcmp( name, "sample_aspect_num" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
- if ( profile )
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
- }
- else if ( !strcmp( name, "sample_aspect_den" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
- if ( profile )
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
- }
- else if ( !strcmp( name, "display_aspect_num" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->display_aspect_num = mlt_properties_get_int( properties, "display_aspect_num" );
- mlt_properties_set_double( properties, "display_ratio", mlt_profile_dar( profile ) );
- }
- }
- else if ( !strcmp( name, "display_aspect_den" ) )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->display_aspect_den = mlt_properties_get_int( properties, "display_aspect_den" );
- mlt_properties_set_double( properties, "display_ratio", mlt_profile_dar( profile ) );
- }
- }
-}
-
-/** The transmitter for the consumer-frame-show event
- *
- * Invokes the listener.
- *
- * \private \memberof mlt_consumer_s
- * \param listener a function pointer that will be invoked
- * \param owner a properties list that will be passed to \p listener
- * \param this 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
- */
-
-static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( mlt_frame )args[ 0 ] );
-}
-
-/** The transmitter for the consumer-frame-render event
- *
- * Invokes the listener.
- *
- * \private \memberof mlt_consumer_s
- * \param listener a function pointer that will be invoked
- * \param owner a properties list that will be passed to \p listener
- * \param this 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
- */
-
-static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( mlt_frame )args[ 0 ] );
-}
-
-/** Create a new consumer.
- *
- * \public \memberof mlt_consumer_s
- * \param profile a profile (optional, but recommended)
- * \return a new consumer
- */
-
-mlt_consumer mlt_consumer_new( mlt_profile profile )
-{
- // Create the memory for the structure
- mlt_consumer this = malloc( sizeof( struct mlt_consumer_s ) );
-
- // Initialise it
- if ( this != NULL )
- mlt_consumer_init( this, NULL, profile );
-
- // Return it
- return this;
-}
-
-/** Get the parent service object.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return the parent service class
- * \see MLT_CONSUMER_SERVICE
- */
-
-mlt_service mlt_consumer_service( mlt_consumer this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the consumer properties.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return the consumer's properties list
- * \see MLT_CONSUMER_PROPERTIES
- */
-
-mlt_properties mlt_consumer_properties( mlt_consumer this )
-{
- return this != NULL ? MLT_SERVICE_PROPERTIES( &this->parent ) : NULL;
-}
-
-/** Connect the consumer to the producer.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \param producer a producer
- * \return > 0 warning, == 0 success, < 0 serious error,
- * 1 = this service does not accept input,
- * 2 = the producer is invalid,
- * 3 = the producer is already registered with this consumer
- */
-
-int mlt_consumer_connect( mlt_consumer this, mlt_service producer )
-{
- return mlt_service_connect_producer( &this->parent, producer, 0 );
-}
-
-/** Start the consumer.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return true if there was an error
- */
-
-int mlt_consumer_start( mlt_consumer this )
-{
- // Stop listening to the property-changed event
- mlt_event_block( this->event_listener );
-
- // Get the properies
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Determine if there's a test card producer
- char *test_card = mlt_properties_get( properties, "test_card" );
-
- // Just to make sure nothing is hanging around...
- mlt_frame_close( this->put );
- this->put = NULL;
- this->put_active = 1;
-
- // Deal with it now.
- if ( test_card != NULL )
- {
- if ( mlt_properties_get_data( properties, "test_card_producer", NULL ) == NULL )
- {
- // Create a test card producer
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- mlt_producer producer = mlt_factory_producer( profile, NULL, test_card );
-
- // Do we have a producer
- if ( producer != NULL )
- {
- // Test card should loop I guess...
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "loop" );
- //mlt_producer_set_speed( producer, 0 );
- //mlt_producer_set_in_and_out( producer, 0, 0 );
-
- // Set the test card on the consumer
- mlt_properties_set_data( properties, "test_card_producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
- }
- }
- }
- else
- {
- // Allow the hash table to speed things up
- mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
- }
-
- // 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" );
- mlt_properties_set_int( properties, "frame_duration", frame_duration );
-
- // Check and run an ante command
- if ( mlt_properties_get( properties, "ante" ) )
- if ( system( mlt_properties_get( properties, "ante" ) ) == -1 )
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_ERROR, "system(%s) failed!\n", mlt_properties_get( properties, "ante" ) );
-
- // Set the real_time preference
- this->real_time = mlt_properties_get_int( properties, "real_time" );
-
- // Start the service
- if ( this->start != NULL )
- return this->start( this );
-
- return 0;
-}
-
-/** An alternative method to feed frames into the consumer.
- *
- * Only valid if the consumer itself is not connected.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \param frame a frame
- * \return true (ignore this for now)
- */
-
-int mlt_consumer_put_frame( mlt_consumer this, mlt_frame frame )
-{
- int error = 1;
-
- // Get the service assoicated to the consumer
- mlt_service service = MLT_CONSUMER_SERVICE( this );
-
- if ( mlt_service_producer( service ) == NULL )
- {
- struct timeval now;
- struct timespec tm;
- pthread_mutex_lock( &this->put_mutex );
- while ( this->put_active && this->put != NULL )
- {
- gettimeofday( &now, NULL );
- tm.tv_sec = now.tv_sec + 1;
- tm.tv_nsec = now.tv_usec * 1000;
- pthread_cond_timedwait( &this->put_cond, &this->put_mutex, &tm );
- }
- if ( this->put_active && this->put == NULL )
- this->put = frame;
- else
- mlt_frame_close( frame );
- pthread_cond_broadcast( &this->put_cond );
- pthread_mutex_unlock( &this->put_mutex );
- }
- else
- {
- mlt_frame_close( frame );
- }
-
- return error;
-}
-
-/** Protected method for consumer to get frames from connected service
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return a frame
- */
-
-mlt_frame mlt_consumer_get_frame( mlt_consumer this )
-{
- // Frame to return
- mlt_frame frame = NULL;
-
- // Get the service assoicated to the consumer
- mlt_service service = MLT_CONSUMER_SERVICE( this );
-
- // Get the consumer properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the frame
- if ( mlt_service_producer( service ) == NULL && mlt_properties_get_int( properties, "put_mode" ) )
- {
- struct timeval now;
- struct timespec tm;
- pthread_mutex_lock( &this->put_mutex );
- while ( this->put_active && this->put == NULL )
- {
- gettimeofday( &now, NULL );
- tm.tv_sec = now.tv_sec + 1;
- tm.tv_nsec = now.tv_usec * 1000;
- pthread_cond_timedwait( &this->put_cond, &this->put_mutex, &tm );
- }
- frame = this->put;
- this->put = NULL;
- pthread_cond_broadcast( &this->put_cond );
- pthread_mutex_unlock( &this->put_mutex );
- if ( frame != NULL )
- mlt_service_apply_filters( service, frame, 0 );
- }
- else if ( mlt_service_producer( service ) != NULL )
- {
- mlt_service_get_frame( service, &frame, 0 );
- }
- else
- {
- frame = mlt_frame_init( service );
- }
-
- if ( frame != NULL )
- {
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the test card producer
- mlt_producer test_card = mlt_properties_get_data( properties, "test_card_producer", NULL );
-
- // Attach the test frame producer to it.
- if ( test_card != NULL )
- mlt_properties_set_data( frame_properties, "test_card_producer", test_card, 0, NULL, NULL );
-
- // Attach the rescale property
- 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" ) );
- }
-
- // Return the frame
- return frame;
-}
-
-/** Compute the time difference between now and a time value.
- *
- * \private \memberof mlt_consumer_s
- * \param time1 a time value to be compared against now
- * \return the difference in microseconds
- */
-
-static inline long time_difference( struct timeval *time1 )
-{
- struct timeval time2;
- time2.tv_sec = time1->tv_sec;
- time2.tv_usec = time1->tv_usec;
- gettimeofday( time1, NULL );
- return time1->tv_sec * 1000000 + time1->tv_usec - time2.tv_sec * 1000000 - time2.tv_usec;
-}
-
-/** The thread procedure for asynchronously pulling frames through the service
- * network connected to a consumer.
- *
- * \private \memberof mlt_consumer_s
- * \param arg a consumer
- */
-
-static void *consumer_read_ahead_thread( void *arg )
-{
- // The argument is the consumer
- mlt_consumer this = arg;
-
- // Get the properties of the consumer
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the width and height
- int width = mlt_properties_get_int( properties, "width" );
- int height = mlt_properties_get_int( properties, "height" );
-
- // See if video is turned off
- int video_off = mlt_properties_get_int( properties, "video_off" );
- int preview_off = mlt_properties_get_int( properties, "preview_off" );
- int preview_format = mlt_properties_get_int( properties, "preview_format" );
-
- // Get the audio settings
- mlt_audio_format afmt = mlt_audio_pcm;
- int counter = 0;
- double fps = mlt_properties_get_double( properties, "fps" );
- int channels = mlt_properties_get_int( properties, "channels" );
- int frequency = mlt_properties_get_int( properties, "frequency" );
- int samples = 0;
- int16_t *pcm = NULL;
-
- // See if audio is turned off
- int audio_off = mlt_properties_get_int( properties, "audio_off" );
-
- // Get the maximum size of the buffer
- int buffer = mlt_properties_get_int( properties, "buffer" ) + 1;
-
- // General frame variable
- mlt_frame frame = NULL;
- uint8_t *image = NULL;
-
- // Time structures
- struct timeval ante;
-
- // Average time for get_frame and get_image
- int count = 1;
- int skipped = 0;
- int64_t time_wait = 0;
- int64_t time_frame = 0;
- int64_t time_process = 0;
- int skip_next = 0;
- mlt_service lock_object = NULL;
-
- if ( preview_off && preview_format != 0 )
- this->format = preview_format;
-
- // Get the first frame
- frame = mlt_consumer_get_frame( this );
-
- // Get the lock object
- lock_object = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "consumer_lock_service", NULL );
-
- // Lock it
- if ( lock_object ) mlt_service_lock( lock_object );
-
- // Get the image of the first frame
- if ( !video_off )
- {
- mlt_events_fire( MLT_CONSUMER_PROPERTIES( this ), "consumer-frame-render", frame, NULL );
- mlt_frame_get_image( frame, &image, &this->format, &width, &height, 0 );
- }
-
- if ( !audio_off )
- {
- samples = mlt_sample_calculator( fps, frequency, counter++ );
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
- }
-
- // Unlock the lock object
- if ( lock_object ) mlt_service_unlock( lock_object );
-
- // Mark as rendered
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );
-
- // Get the starting time (can ignore the times above)
- gettimeofday( &ante, NULL );
-
- // Continue to read ahead
- while ( this->ahead )
- {
- // Fetch width/height again
- width = mlt_properties_get_int( properties, "width" );
- height = mlt_properties_get_int( properties, "height" );
-
- // Put the current frame into the queue
- pthread_mutex_lock( &this->mutex );
- while( this->ahead && mlt_deque_count( this->queue ) >= buffer )
- pthread_cond_wait( &this->cond, &this->mutex );
- mlt_deque_push_back( this->queue, frame );
- pthread_cond_broadcast( &this->cond );
- pthread_mutex_unlock( &this->mutex );
-
- time_wait += time_difference( &ante );
-
- // Get the next frame
- frame = mlt_consumer_get_frame( this );
- time_frame += time_difference( &ante );
-
- // If there's no frame, we're probably stopped...
- if ( frame == NULL )
- continue;
-
- // Attempt to fetch the lock object
- lock_object = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "consumer_lock_service", NULL );
-
- // Increment the count
- count ++;
-
- // Lock if there's a lock object
- if ( lock_object ) mlt_service_lock( lock_object );
-
- // All non normal playback frames should be shown
- if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "_speed" ) != 1 )
- {
-#ifdef DEINTERLACE_ON_NOT_NORMAL_SPEED
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "consumer_deinterlace", 1 );
-#endif
- skipped = 0;
- time_frame = 0;
- time_process = 0;
- time_wait = 0;
- count = 1;
- skip_next = 0;
- }
-
- // Get the image
- if ( !skip_next || this->real_time == -1 )
- {
- // Get the image, mark as rendered and time it
- if ( !video_off )
- {
- mlt_events_fire( MLT_CONSUMER_PROPERTIES( this ), "consumer-frame-render", frame, NULL );
- mlt_frame_get_image( frame, &image, &this->format, &width, &height, 0 );
- }
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );
- }
- else
- {
- // Increment the number of sequentially skipped frames
- skipped ++;
- skip_next = 0;
-
- // If we've reached an unacceptable level, reset everything
- if ( skipped > 5 )
- {
- skipped = 0;
- time_frame = 0;
- time_process = 0;
- time_wait = 0;
- count = 1;
- }
- }
-
- // Always process audio
- if ( !audio_off )
- {
- samples = mlt_sample_calculator( fps, frequency, counter++ );
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
- }
-
- // Increment the time take for this frame
- time_process += time_difference( &ante );
-
- // Determine if the next frame should be skipped
- if ( mlt_deque_count( this->queue ) <= 5 )
- {
- int frame_duration = mlt_properties_get_int( properties, "frame_duration" );
- if ( ( ( time_wait + time_frame + time_process ) / count ) > frame_duration )
- skip_next = 1;
- }
-
- // Unlock if there's a lock object
- if ( lock_object ) mlt_service_unlock( lock_object );
- }
-
- // Remove the last frame
- mlt_frame_close( frame );
-
- return NULL;
-}
-
-/** Start the read/render thread.
- *
- * \private \memberof mlt_consumer_s
- * \param this a consumer
- */
-
-static void consumer_read_ahead_start( mlt_consumer this )
-{
- // We're running now
- this->ahead = 1;
-
- // Create the frame queue
- this->queue = mlt_deque_init( );
-
- // Create the mutex
- pthread_mutex_init( &this->mutex, NULL );
-
- // Create the condition
- pthread_cond_init( &this->cond, NULL );
-
- // Create the read ahead
- if ( mlt_properties_get( MLT_CONSUMER_PROPERTIES( this ), "priority" ) )
- {
- struct sched_param priority;
- priority.sched_priority = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( this ), "priority" );
- pthread_attr_t thread_attributes;
- pthread_attr_init( &thread_attributes );
- pthread_attr_setschedpolicy( &thread_attributes, SCHED_OTHER );
- pthread_attr_setschedparam( &thread_attributes, &priority );
- pthread_attr_setinheritsched( &thread_attributes, PTHREAD_EXPLICIT_SCHED );
- pthread_attr_setscope( &thread_attributes, PTHREAD_SCOPE_SYSTEM );
- if ( pthread_create( &this->ahead_thread, &thread_attributes, consumer_read_ahead_thread, this ) < 0 )
- pthread_create( &this->ahead_thread, NULL, consumer_read_ahead_thread, this );
- pthread_attr_destroy( &thread_attributes );
- }
- else
- {
- pthread_create( &this->ahead_thread, NULL, consumer_read_ahead_thread, this );
- }
-}
-
-/** Stop the read/render thread.
- *
- * \private \memberof mlt_consumer_s
- * \param this a consumer
- */
-
-static void consumer_read_ahead_stop( mlt_consumer this )
-{
- // Make sure we're running
- if ( this->ahead )
- {
- // Inform thread to stop
- this->ahead = 0;
-
- // Broadcast to the condition in case it's waiting
- pthread_mutex_lock( &this->mutex );
- pthread_cond_broadcast( &this->cond );
- pthread_mutex_unlock( &this->mutex );
-
- // Broadcast to the put condition in case it's waiting
- pthread_mutex_lock( &this->put_mutex );
- pthread_cond_broadcast( &this->put_cond );
- pthread_mutex_unlock( &this->put_mutex );
-
- // Join the thread
- pthread_join( this->ahead_thread, NULL );
-
- // Destroy the mutex
- pthread_mutex_destroy( &this->mutex );
-
- // Destroy the condition
- pthread_cond_destroy( &this->cond );
-
- // Wipe the queue
- while ( mlt_deque_count( this->queue ) )
- mlt_frame_close( mlt_deque_pop_back( this->queue ) );
-
- // Close the queue
- mlt_deque_close( this->queue );
- }
-}
-
-/** Flush the read/render thread's buffer.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- */
-
-void mlt_consumer_purge( mlt_consumer this )
-{
- if ( this->ahead )
- {
- pthread_mutex_lock( &this->mutex );
- while ( mlt_deque_count( this->queue ) )
- mlt_frame_close( mlt_deque_pop_back( this->queue ) );
- pthread_cond_broadcast( &this->cond );
- pthread_mutex_unlock( &this->mutex );
- }
-}
-
-/** Get the next frame from the producer connected to a consumer.
- *
- * Typically, one uses this instead of \p mlt_consumer_get_frame to make
- * the asynchronous/real-time behavior configurable at runtime.
- * You should close the frame returned from this when you are done with it.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return a frame
- */
-
-mlt_frame mlt_consumer_rt_frame( mlt_consumer this )
-{
- // Frame to return
- mlt_frame frame = NULL;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Check if the user has requested real time or not
- if ( this->real_time )
- {
- int size = 1;
-
- // Is the read ahead running?
- if ( this->ahead == 0 )
- {
- int buffer = mlt_properties_get_int( properties, "buffer" );
- int prefill = mlt_properties_get_int( properties, "prefill" );
- consumer_read_ahead_start( this );
- if ( buffer > 1 )
- size = prefill > 0 && prefill < buffer ? prefill : buffer;
- }
-
- // Get frame from queue
- pthread_mutex_lock( &this->mutex );
- while( this->ahead && mlt_deque_count( this->queue ) < size )
- pthread_cond_wait( &this->cond, &this->mutex );
- frame = mlt_deque_pop_front( this->queue );
- pthread_cond_broadcast( &this->cond );
- pthread_mutex_unlock( &this->mutex );
- }
- else
- {
- // Get the frame in non real time
- frame = mlt_consumer_get_frame( this );
-
- // This isn't true, but from the consumers perspective it is
- if ( frame != NULL )
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 1 );
- }
-
- return frame;
-}
-
-/** Callback for the implementation to indicate a stopped condition.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- */
-
-void mlt_consumer_stopped( mlt_consumer this )
-{
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "running", 0 );
- mlt_events_fire( MLT_CONSUMER_PROPERTIES( this ), "consumer-stopped", NULL );
- mlt_event_unblock( this->event_listener );
-}
-
-/** Stop the consumer.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return true if there was an error
- */
-
-int mlt_consumer_stop( mlt_consumer this )
-{
- // Get the properies
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Just in case...
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping put waiting\n" );
- pthread_mutex_lock( &this->put_mutex );
- this->put_active = 0;
- pthread_cond_broadcast( &this->put_cond );
- pthread_mutex_unlock( &this->put_mutex );
-
- // Stop the consumer
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping consumer\n" );
- if ( this->stop != NULL )
- this->stop( this );
-
- // Check if the user has requested real time or not and stop if necessary
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopping read_ahead\n" );
- if ( mlt_properties_get_int( properties, "real_time" ) )
- consumer_read_ahead_stop( this );
-
- // Kill the test card
- mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
-
- // Check and run a post command
- if ( mlt_properties_get( properties, "post" ) )
- if (system( mlt_properties_get( properties, "post" ) ) == -1 )
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_ERROR, "system(%s) failed!\n", mlt_properties_get( properties, "post" ) );
-
- mlt_log( MLT_CONSUMER_SERVICE( this ), MLT_LOG_DEBUG, "stopped\n" );
-
- return 0;
-}
-
-/** Determine if the consumer is stopped.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- * \return true if the consumer is stopped
- */
-
-int mlt_consumer_is_stopped( mlt_consumer this )
-{
- // Check if the consumer is stopped
- if ( this->is_stopped != NULL )
- return this->is_stopped( this );
-
- return 0;
-}
-
-/** Close and destroy the consumer.
- *
- * \public \memberof mlt_consumer_s
- * \param this a consumer
- */
-
-void mlt_consumer_close( mlt_consumer this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_CONSUMER_PROPERTIES( this ) ) <= 0 )
- {
- // Get the childs close function
- void ( *consumer_close )( ) = this->close;
-
- if ( consumer_close )
- {
- // Just in case...
- //mlt_consumer_stop( this );
-
- this->close = NULL;
- consumer_close( this );
- }
- else
- {
- // Make sure it only gets called once
- this->parent.close = NULL;
-
- // Destroy the push mutex and condition
- pthread_mutex_destroy( &this->put_mutex );
- pthread_cond_destroy( &this->put_cond );
-
- mlt_service_close( &this->parent );
- }
- }
-}
+++ /dev/null
-/**
- * \file mlt_consumer.h
- * \brief abstraction for all consumer services
- * \see mlt_consumer_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_CONSUMER_H_
-#define _MLT_CONSUMER_H_
-
-#include "mlt_service.h"
-#include "mlt_events.h"
-#include <pthread.h>
-
-/** \brief Consumer abstract service class
- *
- * A consumer is a service that pulls audio and video from the connected
- * producers, filters, and transitions. Typically a consumer is used to
- * output audio and/or video to a device, file, or socket.
- *
- * \extends mlt_service_s
- * \properties \em rescale the scaling algorithm to pass on to all scaling
- * filters, defaults to "bilinear"
- * \properties \em buffer the number of frames to use in the asynchronous
- * render thread, defaults to 25
- * \properties \em frequency the audio sample rate to use in Hertz, defaults to 48000
- * \properties \em channels the number of audio channels to use, defaults to 2
- * \properties \em real_time the asynchronous behavior: 1 (default) for asynchronous
- * with frame dropping, -1 for asynchronous without frame dropping, 0 to disable (synchronous)
- * \properties \em test_card the name of a resource to use as the test card, defaults to
- * environment variable MLT_TEST_CARD. If undefined, the hard-coded default test card is
- * white silence. A test card is what appears when nothing is produced.
- * \event \em consumer-frame-show Subclass implementations should fire this.
- * \event \em consumer-frame-render The abstract class fires this.
- * \event \em consumer-stopped
- * \properties \em fps video frames per second as floating point (read only)
- * \properties \em frame_rate_num the numerator of the video frame rate, overrides \p mlt_profile_s
- * \properties \em frame_rate_den the denominator of the video frame rate, overrides \p mlt_profile_s
- * \properties \em width the horizontal video resolution, overrides \p mlt_profile_s
- * \properties \em height the vertical video resolution, overrides \p mlt_profile_s
- * \properties \em progressive a flag that indicates if the video is interlaced
- * or progressive, overrides \p mlt_profile_s
- * \properties \em aspect_ratio the video sample (pixel) aspect ratio as floating point (read only)
- * \properties \em sample_aspect_num the numerator of the sample aspect ratio, overrides \p mlt_profile_s
- * \properties \em sample_aspect_den the denominator of the sample aspect ratio, overrides \p mlt_profile_s
- * \properties \em display_ratio the video frame aspect ratio as floating point (read only)
- * \properties \em display_aspect_num the numerator of the video frame aspect ratio, overrides \p mlt_profile_s
- * \properties \em display_aspect_den the denominator of the video frame aspect ratio, overrides \p mlt_profile_s
- *
- */
-
-struct mlt_consumer_s
-{
- /** A consumer is a service. */
- struct mlt_service_s parent;
-
- /** Start the consumer to pull frames (virtual function).
- *
- * \param mlt_consumer a consumer
- * \return true if there was an error
- */
- int ( *start )( mlt_consumer );
-
- /** Stop the consumer (virtual function).
- *
- * \param mlt_consumer a consumer
- * \return true if there was an error
- */
- int ( *stop )( mlt_consumer );
-
- /** Get whether the consumer is running or stopped (virtual function).
- *
- * \param mlt_consumer a consumer
- * \return true if the consumer is stopped
- */
- int ( *is_stopped )( mlt_consumer );
-
- /** The destructor virtual function
- *
- * \param mlt_consumer a consumer
- */
- void ( *close )( mlt_consumer );
-
- void *local; /**< \private instance object */
- void *child; /**< \private the object of a subclass */
-
- int real_time;
- int ahead;
- mlt_image_format format;
- mlt_deque queue;
- pthread_t ahead_thread;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- pthread_mutex_t put_mutex;
- pthread_cond_t put_cond;
- mlt_frame put;
- int put_active;
- mlt_event event_listener;
-};
-
-#define MLT_CONSUMER_SERVICE( consumer ) ( &( consumer )->parent )
-#define MLT_CONSUMER_PROPERTIES( consumer ) MLT_SERVICE_PROPERTIES( MLT_CONSUMER_SERVICE( consumer ) )
-
-extern int mlt_consumer_init( mlt_consumer self, void *child, mlt_profile profile );
-extern mlt_consumer mlt_consumer_new( mlt_profile profile );
-extern mlt_service mlt_consumer_service( mlt_consumer self );
-extern mlt_properties mlt_consumer_properties( mlt_consumer self );
-extern int mlt_consumer_connect( mlt_consumer self, mlt_service producer );
-extern int mlt_consumer_start( mlt_consumer self );
-extern void mlt_consumer_purge( mlt_consumer self );
-extern int mlt_consumer_put_frame( mlt_consumer self, mlt_frame frame );
-extern mlt_frame mlt_consumer_get_frame( mlt_consumer self );
-extern mlt_frame mlt_consumer_rt_frame( mlt_consumer self );
-extern int mlt_consumer_stop( mlt_consumer self );
-extern int mlt_consumer_is_stopped( mlt_consumer self );
-extern void mlt_consumer_stopped( mlt_consumer self );
-extern void mlt_consumer_close( mlt_consumer );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_deque.c
- * \brief double ended queue
- * \see mlt_deque_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// Local header files
-#include "mlt_deque.h"
-
-// System header files
-#include <stdlib.h>
-#include <string.h>
-
-/** \brief Deque entry class
- *
- */
-
-typedef union
-{
- void *addr;
- int value;
- double floating;
-}
-deque_entry;
-
-/** \brief Double-Ended Queue (deque) class
- *
- * The double-ended queue is a very versatile data structure. MLT uses it as
- * list, stack, and circular queue.
- */
-
-struct mlt_deque_s
-{
- deque_entry *list;
- int size;
- int count;
-};
-
-/** Create a deque.
- *
- * \public \memberof mlt_deque_s
- * \return a new deque
- */
-
-mlt_deque mlt_deque_init( )
-{
- mlt_deque this = malloc( sizeof( struct mlt_deque_s ) );
- if ( this != NULL )
- {
- this->list = NULL;
- this->size = 0;
- this->count = 0;
- }
- return this;
-}
-
-/** Return the number of items in the deque.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return the number of items
- */
-
-int mlt_deque_count( mlt_deque this )
-{
- return this->count;
-}
-
-/** Allocate space on the deque.
- *
- * \private \memberof mlt_deque_s
- * \param this a deque
- * \return true if there was an error
- */
-
-static int mlt_deque_allocate( mlt_deque this )
-{
- if ( this->count == this->size )
- {
- this->list = realloc( this->list, sizeof( deque_entry ) * ( this->size + 20 ) );
- this->size += 20;
- }
- return this->list == NULL;
-}
-
-/** Push an item to the end.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item an opaque pointer
- * \return true if there was an error
- */
-
-int mlt_deque_push_back( mlt_deque this, void *item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- this->list[ this->count ++ ].addr = item;
-
- return error;
-}
-
-/** Pop an item.
- *
- * \public \memberof mlt_deque_s
- * \param this a pointer
- * \return an opaque pointer
- */
-
-void *mlt_deque_pop_back( mlt_deque this )
-{
- return this->count > 0 ? this->list[ -- this->count ].addr : NULL;
-}
-
-/** Queue an item at the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item an opaque pointer
- * \return true if there was an error
- */
-
-int mlt_deque_push_front( mlt_deque this, void *item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- {
- memmove( &this->list[ 1 ], this->list, ( this->count ++ ) * sizeof( deque_entry ) );
- this->list[ 0 ].addr = item;
- }
-
- return error;
-}
-
-/** Remove an item from the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a pointer
- * \return an opaque pointer
- */
-
-void *mlt_deque_pop_front( mlt_deque this )
-{
- void *item = NULL;
-
- if ( this->count > 0 )
- {
- item = this->list[ 0 ].addr;
- memmove( this->list, &this->list[ 1 ], ( -- this->count ) * sizeof( deque_entry ) );
- }
-
- return item;
-}
-
-/** Inquire on item at back of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an opaque pointer
- */
-
-void *mlt_deque_peek_back( mlt_deque this )
-{
- return this->count > 0 ? this->list[ this->count - 1 ].addr : NULL;
-}
-
-/** Inquire on item at front of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an opaque pointer
- */
-
-void *mlt_deque_peek_front( mlt_deque this )
-{
- return this->count > 0 ? this->list[ 0 ].addr : NULL;
-}
-
-/** Push an integer to the end.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item an integer
- * \return true if there was an error
- */
-
-int mlt_deque_push_back_int( mlt_deque this, int item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- this->list[ this->count ++ ].value = item;
-
- return error;
-}
-
-/** Pop an integer.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an integer
- */
-
-int mlt_deque_pop_back_int( mlt_deque this )
-{
- return this->count > 0 ? this->list[ -- this->count ].value : 0;
-}
-
-/** Queue an integer at the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item an integer
- * \return true if there was an error
- */
-
-int mlt_deque_push_front_int( mlt_deque this, int item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- {
- memmove( &this->list[ 1 ], this->list, ( this->count ++ ) * sizeof( deque_entry ) );
- this->list[ 0 ].value = item;
- }
-
- return error;
-}
-
-/** Remove an integer from the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an integer
- */
-
-int mlt_deque_pop_front_int( mlt_deque this )
-{
- int item = 0;
-
- if ( this->count > 0 )
- {
- item = this->list[ 0 ].value;
- memmove( this->list, &this->list[ 1 ], ( -- this->count ) * sizeof( deque_entry ) );
- }
-
- return item;
-}
-
-/** Inquire on an integer at back of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an integer
- */
-
-int mlt_deque_peek_back_int( mlt_deque this )
-{
- return this->count > 0 ? this->list[ this->count - 1 ].value : 0;
-}
-
-/** Inquire on an integer at front of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return an integer
- */
-
-int mlt_deque_peek_front_int( mlt_deque this )
-{
- return this->count > 0 ? this->list[ 0 ].value : 0;
-}
-
-/** Push a double float to the end.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item a double float
- * \return true if there was an error
- */
-
-int mlt_deque_push_back_double( mlt_deque this, double item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- this->list[ this->count ++ ].floating = item;
-
- return error;
-}
-
-/** Pop a double float.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return a double float
- */
-
-double mlt_deque_pop_back_double( mlt_deque this )
-{
- return this->count > 0 ? this->list[ -- this->count ].floating : 0;
-}
-
-/** Queue a double float at the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \param item a double float
- * \return true if there was an error
- */
-
-int mlt_deque_push_front_double( mlt_deque this, double item )
-{
- int error = mlt_deque_allocate( this );
-
- if ( error == 0 )
- {
- memmove( &this->list[ 1 ], this->list, ( this->count ++ ) * sizeof( deque_entry ) );
- this->list[ 0 ].floating = item;
- }
-
- return error;
-}
-
-/** Remove a double float from the start.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return a double float
- */
-
-double mlt_deque_pop_front_double( mlt_deque this )
-{
- double item = 0;
-
- if ( this->count > 0 )
- {
- item = this->list[ 0 ].floating;
- memmove( this->list, &this->list[ 1 ], ( -- this->count ) * sizeof( deque_entry ) );
- }
-
- return item;
-}
-
-/** Inquire on a double float at back of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return a double float
- */
-
-double mlt_deque_peek_back_double( mlt_deque this )
-{
- return this->count > 0 ? this->list[ this->count - 1 ].floating : 0;
-}
-
-/** Inquire on a double float at front of deque but don't remove.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- * \return a double float
- */
-
-double mlt_deque_peek_front_double( mlt_deque this )
-{
- return this->count > 0 ? this->list[ 0 ].floating : 0;
-}
-
-/** Destroy the queue.
- *
- * \public \memberof mlt_deque_s
- * \param this a deque
- */
-
-void mlt_deque_close( mlt_deque this )
-{
- free( this->list );
- free( this );
-}
+++ /dev/null
-/**
- * \file mlt_deque.h
- * \brief double ended queue
- * \see mlt_deque_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_DEQUE_H_
-#define _MLT_DEQUE_H_
-
-#include "mlt_types.h"
-
-extern mlt_deque mlt_deque_init( );
-extern int mlt_deque_count( mlt_deque self );
-extern int mlt_deque_push_back( mlt_deque self, void *item );
-extern void *mlt_deque_pop_back( mlt_deque self );
-extern int mlt_deque_push_front( mlt_deque self, void *item );
-extern void *mlt_deque_pop_front( mlt_deque self );
-extern void *mlt_deque_peek_back( mlt_deque self );
-extern void *mlt_deque_peek_front( mlt_deque self );
-
-extern int mlt_deque_push_back_int( mlt_deque self, int item );
-extern int mlt_deque_pop_back_int( mlt_deque self );
-extern int mlt_deque_push_front_int( mlt_deque self, int item );
-extern int mlt_deque_pop_front_int( mlt_deque self );
-extern int mlt_deque_peek_back_int( mlt_deque self );
-extern int mlt_deque_peek_front_int( mlt_deque self );
-
-extern int mlt_deque_push_back_double( mlt_deque self, double item );
-extern double mlt_deque_pop_back_double( mlt_deque self );
-extern int mlt_deque_push_front_double( mlt_deque self, double item );
-extern double mlt_deque_pop_front_double( mlt_deque self );
-extern double mlt_deque_peek_back_double( mlt_deque self );
-extern double mlt_deque_peek_front_double( mlt_deque self );
-
-extern void mlt_deque_close( mlt_deque self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_events.c
- * \brief event handling
- * \see mlt_events_struct
- *
- * Copyright (C) 2004-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <pthread.h>
-
-#include "mlt_properties.h"
-#include "mlt_events.h"
-
-/* Memory leak checks. */
-
-#undef _MLT_EVENT_CHECKS_
-
-#ifdef _MLT_EVENT_CHECKS_
-static int events_created = 0;
-static int events_destroyed = 0;
-#endif
-
-/** \brief Events class
- *
- * Events provide messages and notifications between services and the application.
- * A service can register an event and fire/send it upon certain conditions or times.
- * Likewise, a service or an application can listen/receive specific events on specific
- * services.
- */
-
-struct mlt_events_struct
-{
- mlt_properties owner;
- mlt_properties list;
-};
-
-typedef struct mlt_events_struct *mlt_events;
-
-/** \brief Event class
- *
- */
-
-struct mlt_event_struct
-{
- mlt_events owner;
- int ref_count;
- int block_count;
- mlt_listener listener;
- void *service;
-};
-
-/** Increment the reference count on this event.
- *
- * \public \memberof mlt_event_struct
- * \param this an event
- */
-
-void mlt_event_inc_ref( mlt_event this )
-{
- if ( this != NULL )
- this->ref_count ++;
-}
-
-/** Increment the block count on this event.
- *
- * \public \memberof mlt_event_struct
- * \param this an event
- */
-
-void mlt_event_block( mlt_event this )
-{
- if ( this != NULL && this->owner != NULL )
- this->block_count ++;
-}
-
-/** Decrement the block count on this event.
- *
- * \public \memberof mlt_event_struct
- * \param this an event
- */
-
-void mlt_event_unblock( mlt_event this )
-{
- if ( this != NULL && this->owner != NULL )
- this->block_count --;
-}
-
-/** Close this event.
- *
- * \public \memberof mlt_event_struct
- * \param this an event
- */
-
-void mlt_event_close( mlt_event this )
-{
- if ( this != NULL )
- {
- if ( -- this->ref_count == 1 )
- this->owner = NULL;
- if ( this->ref_count <= 0 )
- {
-#ifdef _MLT_EVENT_CHECKS_
- mlt_log( NULL, MLT_LOG_DEBUG, "Events created %d, destroyed %d\n", events_created, ++events_destroyed );
-#endif
- free( this );
- }
- }
-}
-
-/* Forward declaration to private functions.
-*/
-
-static mlt_events mlt_events_fetch( mlt_properties );
-static void mlt_events_store( mlt_properties, mlt_events );
-static void mlt_events_close( mlt_events );
-
-/** Initialise the events structure.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- */
-
-void mlt_events_init( mlt_properties this )
-{
- mlt_events events = mlt_events_fetch( this );
- if ( events == NULL )
- {
- events = malloc( sizeof( struct mlt_events_struct ) );
- events->list = mlt_properties_new( );
- mlt_events_store( this, events );
- }
-}
-
-/** Register an event and transmitter.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param id the name of an event
- * \param transmitter the callback function to send an event message
- * \return true if there was an error
- */
-
-int mlt_events_register( mlt_properties this, const char *id, mlt_transmitter transmitter )
-{
- int error = 1;
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- mlt_properties list = events->list;
- char temp[ 128 ];
- error = mlt_properties_set_data( list, id, transmitter, 0, NULL, NULL );
- sprintf( temp, "list:%s", id );
- if ( mlt_properties_get_data( list, temp, NULL ) == NULL )
- mlt_properties_set_data( list, temp, mlt_properties_new( ), 0, ( mlt_destructor )mlt_properties_close, NULL );
- }
- return error;
-}
-
-/** Fire an event.
- *
- * This takes a variable number of arguments to supply to the listener.
-
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param id the name of an event
- */
-
-void mlt_events_fire( mlt_properties this, const char *id, ... )
-{
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- int i = 0;
- va_list alist;
- void *args[ 10 ];
- mlt_properties list = events->list;
- mlt_properties listeners = NULL;
- char temp[ 128 ];
- mlt_transmitter transmitter = mlt_properties_get_data( list, id, NULL );
- sprintf( temp, "list:%s", id );
- listeners = mlt_properties_get_data( list, temp, NULL );
-
- va_start( alist, id );
- do
- args[ i ] = va_arg( alist, void * );
- while( args[ i ++ ] != NULL );
- va_end( alist );
-
- if ( listeners != NULL )
- {
- for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
- {
- mlt_event event = mlt_properties_get_data_at( listeners, i, NULL );
- if ( event != NULL && event->owner != NULL && event->block_count == 0 )
- {
- if ( transmitter != NULL )
- transmitter( event->listener, event->owner, event->service, args );
- else
- event->listener( event->owner, event->service );
- }
- }
- }
- }
-}
-
-/** Register a listener.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param service an opaque pointer
- * \param id the name of the event to listen for
- * \param listener the callback to receive an event message
- * \return
- */
-
-mlt_event mlt_events_listen( mlt_properties this, void *service, const char *id, mlt_listener listener )
-{
- mlt_event event = NULL;
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- mlt_properties list = events->list;
- mlt_properties listeners = NULL;
- char temp[ 128 ];
- sprintf( temp, "list:%s", id );
- listeners = mlt_properties_get_data( list, temp, NULL );
- if ( listeners != NULL )
- {
- int first_null = -1;
- int i = 0;
- for ( i = 0; event == NULL && i < mlt_properties_count( listeners ); i ++ )
- {
- mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
- if ( entry != NULL && entry->owner != NULL )
- {
- if ( entry->service == service && entry->listener == listener )
- event = entry;
- }
- else if ( ( entry == NULL || entry->owner == NULL ) && first_null == -1 )
- {
- first_null = i;
- }
- }
-
- if ( event == NULL )
- {
- event = malloc( sizeof( struct mlt_event_struct ) );
- if ( event != NULL )
- {
-#ifdef _MLT_EVENT_CHECKS_
- events_created ++;
-#endif
- sprintf( temp, "%d", first_null == -1 ? mlt_properties_count( listeners ) : first_null );
- event->owner = events;
- event->ref_count = 0;
- event->block_count = 0;
- event->listener = listener;
- event->service = service;
- mlt_properties_set_data( listeners, temp, event, 0, ( mlt_destructor )mlt_event_close, NULL );
- mlt_event_inc_ref( event );
- }
- }
-
- }
- }
- return event;
-}
-
-/** Block all events for a given service.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param service an opaque pointer
- */
-
-void mlt_events_block( mlt_properties this, void *service )
-{
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- int i = 0, j = 0;
- mlt_properties list = events->list;
- for ( j = 0; j < mlt_properties_count( list ); j ++ )
- {
- char *temp = mlt_properties_get_name( list, j );
- if ( !strncmp( temp, "list:", 5 ) )
- {
- mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
- for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
- {
- mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
- if ( entry != NULL && entry->service == service )
- mlt_event_block( entry );
- }
- }
- }
- }
-}
-
-/** Unblock all events for a given service.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param service an opaque pointer
- */
-
-void mlt_events_unblock( mlt_properties this, void *service )
-{
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- int i = 0, j = 0;
- mlt_properties list = events->list;
- for ( j = 0; j < mlt_properties_count( list ); j ++ )
- {
- char *temp = mlt_properties_get_name( list, j );
- if ( !strncmp( temp, "list:", 5 ) )
- {
- mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
- for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
- {
- mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
- if ( entry != NULL && entry->service == service )
- mlt_event_unblock( entry );
- }
- }
- }
- }
-}
-
-/** Disconnect all events for a given service.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param service an opaque pointer
- */
-
-void mlt_events_disconnect( mlt_properties this, void *service )
-{
- mlt_events events = mlt_events_fetch( this );
- if ( events != NULL )
- {
- int i = 0, j = 0;
- mlt_properties list = events->list;
- for ( j = 0; j < mlt_properties_count( list ); j ++ )
- {
- char *temp = mlt_properties_get_name( list, j );
- if ( !strncmp( temp, "list:", 5 ) )
- {
- mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
- for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
- {
- mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
- char *name = mlt_properties_get_name( listeners, i );
- if ( entry != NULL && entry->service == service )
- mlt_properties_set_data( listeners, name, NULL, 0, NULL, NULL );
- }
- }
- }
- }
-}
-
-/** \brief private to mlt_events_struct, used by mlt_events_wait_for() */
-
-typedef struct
-{
- int done;
- pthread_cond_t cond;
- pthread_mutex_t mutex;
-}
-condition_pair;
-
-/** The event listener callback for the wait functions.
- *
- * \private \memberof mlt_events_struct
- * \param this a properties list
- * \param pair a condition pair
- */
-
-static void mlt_events_listen_for( mlt_properties this, condition_pair *pair )
-{
- pthread_mutex_lock( &pair->mutex );
- if ( pair->done == 0 )
- {
- pthread_cond_signal( &pair->cond );
- pthread_mutex_unlock( &pair->mutex );
- }
-}
-
-/** Prepare to wait for an event.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param id the name of the event to wait for
- * \return an event
- */
-
-mlt_event mlt_events_setup_wait_for( mlt_properties this, const char *id )
-{
- condition_pair *pair = malloc( sizeof( condition_pair ) );
- pair->done = 0;
- pthread_cond_init( &pair->cond, NULL );
- pthread_mutex_init( &pair->mutex, NULL );
- pthread_mutex_lock( &pair->mutex );
- return mlt_events_listen( this, pair, id, ( mlt_listener )mlt_events_listen_for );
-}
-
-/** Wait for an event.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param event an event
- */
-
-void mlt_events_wait_for( mlt_properties this, mlt_event event )
-{
- if ( event != NULL )
- {
- condition_pair *pair = event->service;
- pthread_cond_wait( &pair->cond, &pair->mutex );
- }
-}
-
-/** Cleanup after waiting for an event.
- *
- * \public \memberof mlt_events_struct
- * \param this a properties list
- * \param event an event
- */
-
-void mlt_events_close_wait_for( mlt_properties this, mlt_event event )
-{
- if ( event != NULL )
- {
- condition_pair *pair = event->service;
- event->owner = NULL;
- pair->done = 0;
- pthread_mutex_unlock( &pair->mutex );
- pthread_mutex_destroy( &pair->mutex );
- pthread_cond_destroy( &pair->cond );
- }
-}
-
-/** Fetch the events object.
- *
- * \private \memberof mlt_events_struct
- * \param this a properties list
- * \return an events object
- */
-
-static mlt_events mlt_events_fetch( mlt_properties this )
-{
- mlt_events events = NULL;
- if ( this != NULL )
- events = mlt_properties_get_data( this, "_events", NULL );
- return events;
-}
-
-/** Store the events object.
- *
- * \private \memberof mlt_events_struct
- * \param this a properties list
- * \param events an events object
- */
-
-static void mlt_events_store( mlt_properties this, mlt_events events )
-{
- if ( this != NULL && events != NULL )
- mlt_properties_set_data( this, "_events", events, 0, ( mlt_destructor )mlt_events_close, NULL );
-}
-
-/** Close the events object.
- *
- * \private \memberof mlt_events_struct
- * \param events an events object
- */
-
-static void mlt_events_close( mlt_events events )
-{
- if ( events != NULL )
- {
- mlt_properties_close( events->list );
- free( events );
- }
-}
+++ /dev/null
-/**
- * \file mlt_events.h
- * \brief event handling
- * \see mlt_events_struct
- *
- * Copyright (C) 2004-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_EVENTS_H_
-#define _MLT_EVENTS_H_
-
-#include "mlt_types.h"
-
-#if GCC_VERSION >= 40000
-typedef void ( *mlt_transmitter )( void *, ... );
-typedef void ( *mlt_listener )( void *, ... );
-#else
-/** callback function to send an event message
- *
- */
-typedef void ( *mlt_transmitter )( );
-/** event handler when receiving an event message
- * \param the properties object on which the event was registered
- * \param an opaque pointer to a service or really an object
- * \param variable args supplied by the transmitter
- */
-typedef void ( *mlt_listener )( );
-#endif
-
-extern void mlt_events_init( mlt_properties self );
-extern int mlt_events_register( mlt_properties self, const char *id, mlt_transmitter transmitter );
-extern void mlt_events_fire( mlt_properties self, const char *id, ... );
-extern mlt_event mlt_events_listen( mlt_properties self, void *service, const char *id, mlt_listener listener );
-extern void mlt_events_block( mlt_properties self, void *service );
-extern void mlt_events_unblock( mlt_properties self, void *service );
-extern void mlt_events_disconnect( mlt_properties self, void *service );
-
-extern mlt_event mlt_events_setup_wait_for( mlt_properties self, const char *id );
-extern void mlt_events_wait_for( mlt_properties self, mlt_event event );
-extern void mlt_events_close_wait_for( mlt_properties self, mlt_event event );
-
-extern void mlt_event_inc_ref( mlt_event self );
-extern void mlt_event_block( mlt_event self );
-extern void mlt_event_unblock( mlt_event self );
-extern void mlt_event_close( mlt_event self );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_factory.c
- * \brief the factory method interfaces
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt.h"
-#include "mlt_repository.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** the default subdirectory of the libdir for holding modules (plugins) */
-#define PREFIX_LIB LIBDIR "/mlt"
-/** the default subdirectory of the install prefix for holding module (plugin) data */
-#define PREFIX_DATA PREFIX "/share/mlt"
-
-
-/** holds the full path to the modules directory - initialized and retained for the entire session */
-static char *mlt_directory = NULL;
-/** a global properties list for holding environment config data and things needing session-oriented cleanup */
-static mlt_properties global_properties = NULL;
-/** the global repository singleton */
-static mlt_repository repository = NULL;
-/** the events object for the factory events */
-static mlt_properties event_object = NULL;
-/** for tracking the unique_id set on each constructed service */
-static int unique_id = 0;
-
-/* Event transmitters. */
-
-/** the -create-request event transmitter
- *
- * \param listener
- * \param owner
- * \param this
- * \param args
- */
-
-static void mlt_factory_create_request( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service * )args[ 2 ] );
-}
-
-/** the -create-done event transmitter
- *
- * \param listener
- * \param owner
- * \param this
- * \param args
- */
-
-static void mlt_factory_create_done( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service )args[ 2 ] );
-}
-
-/** Construct the repository and factories.
- *
- * The environment variable MLT_PRODUCER is the name of a default producer often used by other services, defaults to "fezzil".
- *
- * The environment variable MLT_CONSUMER is the name of a default consumer, defaults to "sdl".
- *
- * The environment variable MLT_TEST_CARD is the name of a producer or file to be played when nothing is available (all tracks blank).
- *
- * The environment variable MLT_DATA overrides the default full path to the MLT and module supplemental data files, defaults to \p PREFIX_DATA.
- *
- * The environment variable MLT_PROFILE defaults to "dv_pal."
- *
- * The environment variable MLT_REPOSITORY overrides the default location of the plugin modules, defaults to \p PREFIX_LIB.
- *
- * \param directory an optional full path to a directory containing the modules that overrides the default and
- * the MLT_REPOSITORY environment variable
- * \return the repository
- */
-
-mlt_repository mlt_factory_init( const char *directory )
-{
- // Only initialise once
- if ( mlt_directory == NULL )
- {
- // Allow user over rides
- if ( directory == NULL || !strcmp( directory, "" ) )
- directory = getenv( "MLT_REPOSITORY" );
-
- // If no directory is specified, default to install directory
- if ( directory == NULL )
- directory = PREFIX_LIB;
-
- // Store the prefix for later retrieval
- mlt_directory = strdup( directory );
-
- // Initialise the pool
- mlt_pool_init( );
-
- // Create and set up the events object
- event_object = mlt_properties_new( );
- mlt_events_init( event_object );
- mlt_events_register( event_object, "producer-create-request", ( mlt_transmitter )mlt_factory_create_request );
- mlt_events_register( event_object, "producer-create-done", ( mlt_transmitter )mlt_factory_create_done );
- mlt_events_register( event_object, "filter-create-request", ( mlt_transmitter )mlt_factory_create_request );
- mlt_events_register( event_object, "filter-create-done", ( mlt_transmitter )mlt_factory_create_done );
- mlt_events_register( event_object, "transition-create-request", ( mlt_transmitter )mlt_factory_create_request );
- mlt_events_register( event_object, "transition-create-done", ( mlt_transmitter )mlt_factory_create_done );
- mlt_events_register( event_object, "consumer-create-request", ( mlt_transmitter )mlt_factory_create_request );
- mlt_events_register( event_object, "consumer-create-done", ( mlt_transmitter )mlt_factory_create_done );
-
- // Create the global properties
- global_properties = mlt_properties_new( );
-
- // Create the repository of services
- repository = mlt_repository_init( directory );
-
- // Force a clean up when app closes
- atexit( mlt_factory_close );
- }
-
- // Allow property refresh on a subsequent initialisation
- if ( global_properties != NULL )
- {
- mlt_properties_set_or_default( global_properties, "MLT_NORMALISATION", getenv( "MLT_NORMALISATION" ), "PAL" );
- mlt_properties_set_or_default( global_properties, "MLT_PRODUCER", getenv( "MLT_PRODUCER" ), "fezzik" );
- mlt_properties_set_or_default( global_properties, "MLT_CONSUMER", getenv( "MLT_CONSUMER" ), "sdl" );
- mlt_properties_set( global_properties, "MLT_TEST_CARD", getenv( "MLT_TEST_CARD" ) );
- mlt_properties_set_or_default( global_properties, "MLT_PROFILE", getenv( "MLT_PROFILE" ), "dv_pal" );
- mlt_properties_set_or_default( global_properties, "MLT_DATA", getenv( "MLT_DATA" ), PREFIX_DATA );
- }
-
-
- return repository;
-}
-
-/** Fetch the events object.
- *
- * \return the global factory event object
- */
-
-mlt_properties mlt_factory_event_object( )
-{
- return event_object;
-}
-
-/** Fetch the module directory used in this instance.
- *
- * \return the full path to the module directory that this session is using
- */
-
-const char *mlt_factory_directory( )
-{
- return mlt_directory;
-}
-
-/** Get a value from the environment.
- *
- * \param name the name of a MLT (runtime configuration) environment variable
- * \return the value of the variable
- */
-
-char *mlt_environment( const char *name )
-{
- if ( global_properties )
- return mlt_properties_get( global_properties, name );
- else
- return NULL;
-}
-
-/** Set a value in the environment.
- *
- * \param name the name of a MLT environment variable
- * \param value the value of the variable
- * \return true on error
- */
-
-int mlt_environment_set( const char *name, const char *value )
-{
- if ( global_properties )
- return mlt_properties_set( global_properties, name, value );
- else
- return -1;
-}
-
-/** Set some properties common to all services.
- *
- * This sets _unique_id, \p mlt_type, \p mlt_service (unless _mlt_service_hidden), and _profile.
- *
- * \param properties a service's properties list
- * \param profile the \p mlt_profile supplied to the factory function
- * \param type the MLT service class
- * \param service the name of the service
- */
-
-static void set_common_properties( mlt_properties properties, mlt_profile profile, const char *type, const char *service )
-{
- mlt_properties_set_int( properties, "_unique_id", ++ unique_id );
- mlt_properties_set( properties, "mlt_type", type );
- if ( mlt_properties_get_int( properties, "_mlt_service_hidden" ) == 0 )
- mlt_properties_set( properties, "mlt_service", service );
- if ( profile != NULL )
- mlt_properties_set_data( properties, "_profile", profile, 0, NULL, NULL );
-}
-
-/** Fetch a producer from the repository.
- *
- * \param profile the \p mlt_profile to use
- * \param service the name of the producer (optional, defaults to MLT_PRODUCER)
- * \param input an optional argument to the producer constructor, typically a string
- * \return a new producer
- */
-
-mlt_producer mlt_factory_producer( mlt_profile profile, const char *service, const void *input )
-{
- mlt_producer obj = NULL;
-
- // Pick up the default normalising producer if necessary
- if ( service == NULL )
- service = mlt_environment( "MLT_PRODUCER" );
-
- // Offer the application the chance to 'create'
- mlt_events_fire( event_object, "producer-create-request", service, input, &obj, NULL );
-
- // Try to instantiate via the specified service
- if ( obj == NULL )
- {
- obj = mlt_repository_create( repository, profile, producer_type, service, input );
- mlt_events_fire( event_object, "producer-create-done", service, input, obj, NULL );
- if ( obj != NULL )
- {
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( obj );
- set_common_properties( properties, profile, "producer", service );
- }
- }
- return obj;
-}
-
-/** Fetch a filter from the repository.
- *
- * \param profile the \p mlt_profile to use
- * \param service the name of the filter
- * \param input an optional argument to the filter constructor, typically a string
- * \return a new filter
- */
-
-mlt_filter mlt_factory_filter( mlt_profile profile, const char *service, const void *input )
-{
- mlt_filter obj = NULL;
-
- // Offer the application the chance to 'create'
- mlt_events_fire( event_object, "filter-create-request", service, input, &obj, NULL );
-
- if ( obj == NULL )
- {
- obj = mlt_repository_create( repository, profile, filter_type, service, input );
- mlt_events_fire( event_object, "filter-create-done", service, input, obj, NULL );
- }
-
- if ( obj != NULL )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( obj );
- set_common_properties( properties, profile, "filter", service );
- }
- return obj;
-}
-
-/** Fetch a transition from the repository.
- *
- * \param profile the \p mlt_profile to use
- * \param service the name of the transition
- * \param input an optional argument to the transition constructor, typically a string
- * \return a new transition
- */
-
-mlt_transition mlt_factory_transition( mlt_profile profile, const char *service, const void *input )
-{
- mlt_transition obj = NULL;
-
- // Offer the application the chance to 'create'
- mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL );
-
- if ( obj == NULL )
- {
- obj = mlt_repository_create( repository, profile, transition_type, service, input );
- mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL );
- }
-
- if ( obj != NULL )
- {
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( obj );
- set_common_properties( properties, profile, "transition", service );
- }
- return obj;
-}
-
-/** Fetch a consumer from the repository.
- *
- * \param profile the \p mlt_profile to use
- * \param service the name of the consumer (optional, defaults to MLT_CONSUMER)
- * \param input an optional argument to the consumer constructor, typically a string
- * \return a new consumer
- */
-
-mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *service, const void *input )
-{
- mlt_consumer obj = NULL;
-
- if ( service == NULL )
- service = mlt_environment( "MLT_CONSUMER" );
-
- // Offer the application the chance to 'create'
- mlt_events_fire( event_object, "consumer-create-request", service, input, &obj, NULL );
-
- if ( obj == NULL )
- {
- obj = mlt_repository_create( repository, profile, consumer_type, service, input );
- mlt_events_fire( event_object, "consumer-create-done", service, input, obj, NULL );
- }
-
- if ( obj != NULL )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( obj );
- set_common_properties( properties, profile, "consumer", service );
- }
- return obj;
-}
-
-/** Register an object for clean up.
- *
- * \param ptr an opaque pointer to anything allocated on the heap
- * \param destructor the function pointer of the deallocation subroutine (e.g., free or \p mlt_pool_release)
- */
-
-void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor )
-{
- char unique[ 256 ];
- sprintf( unique, "%08d", mlt_properties_count( global_properties ) );
- mlt_properties_set_data( global_properties, unique, ptr, 0, destructor, NULL );
-}
-
-/** Close the factory.
- *
- * Cleanup all resources for the session.
- */
-
-void mlt_factory_close( )
-{
- if ( mlt_directory != NULL )
- {
- mlt_properties_close( event_object );
- mlt_properties_close( global_properties );
- mlt_repository_close( repository );
- free( mlt_directory );
- mlt_directory = NULL;
- mlt_pool_close( );
- }
-}
-
-mlt_properties mlt_global_properties( )
-{
- return global_properties;
-}
+++ /dev/null
-/**
- * \file mlt_factory.h
- * \brief the factory method interfaces
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_FACTORY_H
-#define _MLT_FACTORY_H
-
-#include "mlt_types.h"
-#include "mlt_profile.h"
-#include "mlt_repository.h"
-
-/**
- * \event \em producer-create-request fired when mlt_factory_producer is called
- * \event \em producer-create-done fired when a producer registers itself
- * \event \em filter-create-request fired when mlt_factory_filter is called
- * \event \em filter-create-done fired when a filter registers itself
- * \event \em transition-create-request fired when mlt_factory_transition is called
- * \event \em transition-create-done fired when a transition registers itself
- * \event \em consumer-create-request fired when mlt_factory_consumer is called
- * \event \em consumer-create-done fired when a consumer registers itself
- */
-
-extern mlt_repository mlt_factory_init( const char *directory );
-extern const char *mlt_factory_directory( );
-extern char *mlt_environment( const char *name );
-extern int mlt_environment_set( const char *name, const char *value );
-extern mlt_properties mlt_factory_event_object( );
-extern mlt_producer mlt_factory_producer( mlt_profile profile, const char *name, const void *input );
-extern mlt_filter mlt_factory_filter( mlt_profile profile, const char *name, const void *input );
-extern mlt_transition mlt_factory_transition( mlt_profile profile, const char *name, const void *input );
-extern mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *name, const void *input );
-extern void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor );
-extern void mlt_factory_close( );
-extern mlt_properties mlt_global_properties( );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_field.c
- * \brief a field for planting multiple transitions and filters
- * \see mlt_field_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_field.h"
-#include "mlt_service.h"
-#include "mlt_filter.h"
-#include "mlt_transition.h"
-#include "mlt_multitrack.h"
-#include "mlt_tractor.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/** \brief Field class
- *
- * The field is a convenience class that works with the tractor and multitrack classes to manage track filters and transitions.
- */
-
-struct mlt_field_s
-{
- /// This is the producer we're connected to
- mlt_service producer;
-
- /// Multitrack
- mlt_multitrack multitrack;
-
- /// Tractor
- mlt_tractor tractor;
-};
-
-/** Construct a field, mulitrack, and tractor.
- *
- * \public \memberof mlt_field_s
- * \return a new field
- */
-
-mlt_field mlt_field_init( )
-{
- // Initialise the field
- mlt_field this = calloc( sizeof( struct mlt_field_s ), 1 );
-
- // Initialise it
- if ( this != NULL )
- {
- // Construct a multitrack
- this->multitrack = mlt_multitrack_init( );
-
- // Construct a tractor
- this->tractor = mlt_tractor_init( );
-
- // The first plant will be connected to the mulitrack
- this->producer = MLT_MULTITRACK_SERVICE( this->multitrack );
-
- // Connect the tractor to the multitrack
- mlt_tractor_connect( this->tractor, this->producer );
- }
-
- // Return this
- return this;
-}
-
-/** Construct a field and initialize with supplied multitrack and tractor.
- *
- * \public \memberof mlt_field_s
- * \param multitrack a multitrack
- * \param tractor a tractor
- * \return a new field
- */
-
-mlt_field mlt_field_new( mlt_multitrack multitrack, mlt_tractor tractor )
-{
- // Initialise the field
- mlt_field this = calloc( sizeof( struct mlt_field_s ), 1 );
-
- // Initialise it
- if ( this != NULL )
- {
- // Construct a multitrack
- this->multitrack = multitrack;
-
- // Construct a tractor
- this->tractor = tractor;
-
- // The first plant will be connected to the mulitrack
- this->producer = MLT_MULTITRACK_SERVICE( this->multitrack );
-
- // Connect the tractor to the multitrack
- mlt_tractor_connect( this->tractor, this->producer );
- }
-
- // Return this
- return this;
-}
-
-/** Get the service associated to this field.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \return the tractor as a service
- */
-
-mlt_service mlt_field_service( mlt_field this )
-{
- return MLT_TRACTOR_SERVICE( this->tractor );
-}
-
-/** Get the multitrack.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \return the multitrack
- */
-
-mlt_multitrack mlt_field_multitrack( mlt_field this )
-{
- return this != NULL ? this->multitrack : NULL;
-}
-
-/** Get the tractor.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \return the tractor
- */
-
-mlt_tractor mlt_field_tractor( mlt_field this )
-{
- return this != NULL ? this->tractor : NULL;
-}
-
-/** Get the properties associated to this field.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \return a properties list
- */
-
-mlt_properties mlt_field_properties( mlt_field this )
-{
- return MLT_SERVICE_PROPERTIES( mlt_field_service( this ) );
-}
-
-/** Plant a filter.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \param that a filter
- * \param track the track index
- * \return true if there was an error
- */
-
-int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track )
-{
- // Connect the filter to the last producer
- int result = mlt_filter_connect( that, this->producer, track );
-
- // If sucessful, then we'll use this for connecting in the future
- if ( result == 0 )
- {
- // This is now the new producer
- this->producer = MLT_FILTER_SERVICE( that );
-
- // Reconnect tractor to new producer
- mlt_tractor_connect( this->tractor, this->producer );
-
- // Fire an event
- mlt_events_fire( mlt_field_properties( this ), "service-changed", NULL );
- }
-
- return result;
-}
-
-/** Plant a transition.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- * \param that a transition
- * \param a_track input A's track index
- * \param b_track input B's track index
- * \return true if there was an error
- */
-
-int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track, int b_track )
-{
- // Connect the transition to the last producer
- int result = mlt_transition_connect( that, this->producer, a_track, b_track );
-
- // If sucessful, then we'll use this for connecting in the future
- if ( result == 0 )
- {
- // This is now the new producer
- this->producer = MLT_TRANSITION_SERVICE( that );
-
- // Reconnect tractor to new producer
- mlt_tractor_connect( this->tractor, this->producer );
-
- // Fire an event
- mlt_events_fire( mlt_field_properties( this ), "service-changed", NULL );
- }
-
- return 0;
-}
-
-/** Close the field.
- *
- * \public \memberof mlt_field_s
- * \param this a field
- */
-
-void mlt_field_close( mlt_field this )
-{
- if ( this != NULL && mlt_properties_dec_ref( mlt_field_properties( this ) ) <= 0 )
- {
- //mlt_tractor_close( this->tractor );
- //mlt_multitrack_close( this->multitrack );
- free( this );
- }
-}
-
-/** Remove a filter or transition from the field.
- *
- * \public \memberof mlt_field_s
- * \param self a field
- * \param service the filter or transition to remove
- */
-
-void mlt_field_disconnect_service( mlt_field self, mlt_service service )
-{
- mlt_service p = mlt_service_producer( service );
- mlt_service c = mlt_service_consumer( service);
- int i;
- switch ( mlt_service_identify(c) )
- {
- case filter_type:
- i = mlt_filter_get_track( MLT_FILTER(c) );
- mlt_service_connect_producer( c, p, i );
- break;
- case transition_type:
- i = mlt_transition_get_a_track ( MLT_TRANSITION(c) );
- mlt_service_connect_producer( c, p, i );
- MLT_TRANSITION(c)->producer = p;
- break;
- case tractor_type:
- self->producer = p;
- mlt_tractor_connect( MLT_TRACTOR(c), p );
- default:
- break;
- }
- mlt_events_fire( mlt_field_properties( self ), "service-changed", NULL );
-}
+++ /dev/null
-/**
- * \file mlt_field.h
- * \brief a field for planting multiple transitions and services
- * \see mlt_field_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_FIELD_H_
-#define _MLT_FIELD_H_
-
-#include "mlt_types.h"
-
-extern mlt_field mlt_field_init( );
-extern mlt_field mlt_field_new( mlt_multitrack multitrack, mlt_tractor tractor );
-extern mlt_service mlt_field_service( mlt_field self );
-extern mlt_tractor mlt_field_tractor( mlt_field self );
-extern mlt_multitrack mlt_field_multitrack( mlt_field self );
-extern mlt_properties mlt_field_properties( mlt_field self );
-extern int mlt_field_plant_filter( mlt_field self, mlt_filter that, int track );
-extern int mlt_field_plant_transition( mlt_field self, mlt_transition that, int a_track, int b_track );
-extern void mlt_field_close( mlt_field self );
-extern void mlt_field_disconnect_service( mlt_field self, mlt_service service );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_filter.c
- * \brief abstraction for all filter services
- * \see mlt_filter_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_filter.h"
-#include "mlt_frame.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static int filter_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-
-/** Initialize a new filter.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \param child the object of a subclass
- * \return true if there was an error
- */
-
-int mlt_filter_init( mlt_filter this, void *child )
-{
- mlt_service service = &this->parent;
- memset( this, 0, sizeof( struct mlt_filter_s ) );
- this->child = child;
- if ( mlt_service_init( service, this ) == 0 )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- // Override the get_frame method
- service->get_frame = filter_get_frame;
-
- // Define the destructor
- service->close = ( mlt_destructor )mlt_filter_close;
- service->close_object = this;
-
- // Default in, out, track properties
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 0 );
- mlt_properties_set_int( properties, "track", 0 );
-
- return 0;
- }
- return 1;
-}
-
-/** Create a new filter and initialize it.
- *
- * \public \memberof mlt_filter_s
- * \return a new filter
- */
-
-mlt_filter mlt_filter_new( )
-{
- mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
- if ( this != NULL )
- mlt_filter_init( this, NULL );
- return this;
-}
-
-/** Get the service class interface.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \return the service parent class
- * \see MLT_FILTER_SERVICE
- */
-
-mlt_service mlt_filter_service( mlt_filter this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the filter properties.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \return the properties list for the filter
- * \see MLT_FILTER_PROPERTIES
- */
-
-mlt_properties mlt_filter_properties( mlt_filter this )
-{
- return MLT_SERVICE_PROPERTIES( MLT_FILTER_SERVICE( this ) );
-}
-
-/** Connect this filter to a producers track. Note that a filter only operates
- * on a single track, and by default it operates on the entirety of that track.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \param producer the producer to which to connect this filter
- * \param index which of potentially multiple producers to this service (0 based)
- */
-
-int mlt_filter_connect( mlt_filter this, mlt_service producer, int index )
-{
- int ret = mlt_service_connect_producer( &this->parent, producer, index );
-
- // If the connection was successful, grab the producer, track and reset in/out
- if ( ret == 0 )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 0 );
- mlt_properties_set_int( properties, "track", index );
- }
-
- return ret;
-}
-
-/** Set the starting and ending time.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \param in the time relative to the producer at which start applying the filter
- * \param out the time relative to the producer at which to stop applying the filter
- */
-
-
-void mlt_filter_set_in_and_out( mlt_filter this, mlt_position in, mlt_position out )
-{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
- mlt_properties_set_position( properties, "in", in );
- mlt_properties_set_position( properties, "out", out );
-}
-
-/** Return the track that this filter is operating on.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \return true on error
- */
-
-
-int mlt_filter_get_track( mlt_filter this )
-{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
- return mlt_properties_get_int( properties, "track" );
-}
-
-/** Get the in point.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \return the start time for the filter relative to the producer
- */
-
-
-mlt_position mlt_filter_get_in( mlt_filter this )
-{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
- return mlt_properties_get_position( properties, "in" );
-}
-
-/** Get the out point.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \return the ending time for the filter relative to the producer
- */
-
-
-mlt_position mlt_filter_get_out( mlt_filter this )
-{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( &this->parent );
- return mlt_properties_get_position( properties, "out" );
-}
-
-/** Process the frame.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- * \param frame a frame
- * \return a frame
- */
-
-
-mlt_frame mlt_filter_process( mlt_filter this, mlt_frame frame )
-{
- int disable = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "disable" );
- if ( disable || this->process == NULL )
- return frame;
- else
- return this->process( this, frame );
-}
-
-/** Get a frame from this filter.
- *
- * \private \memberof mlt_filter_s
- * \param service a service
- * \param[out] frame a frame by reference
- * \param index as determined by the producer
- * \return true on error
- */
-
-
-static int filter_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
-{
- mlt_filter this = service->child;
-
- // Get coords in/out/track
- int track = mlt_filter_get_track( this );
- int in = mlt_filter_get_in( this );
- int out = mlt_filter_get_out( this );
-
- // Get the producer this is connected to
- mlt_service producer = mlt_service_producer( &this->parent );
-
- // If the frame request is for this filters track, we need to process it
- if ( index == track || track == -1 )
- {
- int ret = mlt_service_get_frame( producer, frame, index );
- if ( ret == 0 )
- {
- mlt_position position = mlt_frame_get_position( *frame );
- if ( position >= in && ( out == 0 || position <= out ) )
- *frame = mlt_filter_process( this, *frame );
- return 0;
- }
- else
- {
- *frame = mlt_frame_init( service );
- return 0;
- }
- }
- else
- {
- return mlt_service_get_frame( producer, frame, index );
- }
-}
-
-/** Close and destroy the filter.
- *
- * \public \memberof mlt_filter_s
- * \param this a filter
- */
-
-
-void mlt_filter_close( mlt_filter this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_FILTER_PROPERTIES( this ) ) <= 0 )
- {
- if ( this->close != NULL )
- {
- this->close( this );
- }
- else
- {
- this->parent.close = NULL;
- mlt_service_close( &this->parent );
- }
- free( this );
- }
-}
+++ /dev/null
-/**
- * \file mlt_filter.h
- * \brief abstraction for all filter services
- * \see mlt_filter_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_FILTER_H_
-#define _MLT_FILTER_H_
-
-#include "mlt_service.h"
-
-/** \brief Filter abstract service class
- *
- * A filter is a service that may modify the output of a single producer.
- *
- * \extends mlt_service_s
- * \properties \em track the index of the track of a multitrack on which the filter is applied
- */
-
-struct mlt_filter_s
-{
- /** We're implementing service here */
- struct mlt_service_s parent;
-
- /** public virtual */
- void ( *close )( mlt_filter );
-
- /** protected filter method */
- mlt_frame ( *process )( mlt_filter, mlt_frame );
-
- /** Protected */
- void *child;
-};
-
-#define MLT_FILTER_SERVICE( filter ) ( &( filter )->parent )
-#define MLT_FILTER_PROPERTIES( filter ) MLT_SERVICE_PROPERTIES( MLT_FILTER_SERVICE( filter ) )
-
-extern int mlt_filter_init( mlt_filter self, void *child );
-extern mlt_filter mlt_filter_new( );
-extern mlt_service mlt_filter_service( mlt_filter self );
-extern mlt_properties mlt_filter_properties( mlt_filter self );
-extern mlt_frame mlt_filter_process( mlt_filter self, mlt_frame that );
-extern int mlt_filter_connect( mlt_filter self, mlt_service producer, int index );
-extern void mlt_filter_set_in_and_out( mlt_filter self, mlt_position in, mlt_position out );
-extern int mlt_filter_get_track( mlt_filter self );
-extern mlt_position mlt_filter_get_in( mlt_filter self );
-extern mlt_position mlt_filter_get_out( mlt_filter self );
-extern void mlt_filter_close( mlt_filter );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_frame.c
- * \brief interface for all frame classes
- * \see mlt_frame_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_frame.h"
-#include "mlt_producer.h"
-#include "mlt_factory.h"
-#include "mlt_profile.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-/** Constructor for a frame.
-*/
-
-mlt_frame mlt_frame_init( mlt_service service )
-{
- // Allocate a frame
- mlt_frame this = calloc( sizeof( struct mlt_frame_s ), 1 );
-
- if ( this != NULL )
- {
- mlt_profile profile = mlt_service_profile( service );
-
- // Initialise the properties
- mlt_properties properties = &this->parent;
- mlt_properties_init( properties, this );
-
- // Set default properties on the frame
- mlt_properties_set_position( properties, "_position", 0.0 );
- mlt_properties_set_data( properties, "image", NULL, 0, NULL, NULL );
- mlt_properties_set_int( properties, "width", profile? profile->width : 720 );
- mlt_properties_set_int( properties, "height", profile? profile->height : 576 );
- mlt_properties_set_int( properties, "normalised_width", profile? profile->width : 720 );
- mlt_properties_set_int( properties, "normalised_height", profile? profile->height : 576 );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) );
- mlt_properties_set_data( properties, "audio", NULL, 0, NULL, NULL );
- mlt_properties_set_data( properties, "alpha", NULL, 0, NULL, NULL );
-
- // Construct stacks for frames and methods
- this->stack_image = mlt_deque_init( );
- this->stack_audio = mlt_deque_init( );
- this->stack_service = mlt_deque_init( );
- }
-
- return this;
-}
-
-/** Fetch the frames properties.
-*/
-
-mlt_properties mlt_frame_properties( mlt_frame this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Check if we have a way to derive something other than a test card.
-*/
-
-int mlt_frame_is_test_card( mlt_frame this )
-{
- return mlt_deque_count( this->stack_image ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_image" );
-}
-
-/** Check if we have a way to derive something other than test audio.
-*/
-
-int mlt_frame_is_test_audio( mlt_frame this )
-{
- return mlt_deque_count( this->stack_audio ) == 0 || mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "test_audio" );
-}
-
-/** Get the aspect ratio of the frame.
-*/
-
-double mlt_frame_get_aspect_ratio( mlt_frame this )
-{
- return mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio" );
-}
-
-/** Set the aspect ratio of the frame.
-*/
-
-int mlt_frame_set_aspect_ratio( mlt_frame this, double value )
-{
- return mlt_properties_set_double( MLT_FRAME_PROPERTIES( this ), "aspect_ratio", value );
-}
-
-/** Get the position of this frame.
-*/
-
-mlt_position mlt_frame_get_position( mlt_frame this )
-{
- int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( this ), "_position" );
- return pos < 0 ? 0 : pos;
-}
-
-/** Set the position of this frame.
-*/
-
-int mlt_frame_set_position( mlt_frame this, mlt_position value )
-{
- return mlt_properties_set_position( MLT_FRAME_PROPERTIES( this ), "_position", value );
-}
-
-/** Stack a get_image callback.
-*/
-
-int mlt_frame_push_get_image( mlt_frame this, mlt_get_image get_image )
-{
- return mlt_deque_push_back( this->stack_image, get_image );
-}
-
-/** Pop a get_image callback.
-*/
-
-mlt_get_image mlt_frame_pop_get_image( mlt_frame this )
-{
- return mlt_deque_pop_back( this->stack_image );
-}
-
-/** Push a frame.
-*/
-
-int mlt_frame_push_frame( mlt_frame this, mlt_frame that )
-{
- return mlt_deque_push_back( this->stack_image, that );
-}
-
-/** Pop a frame.
-*/
-
-mlt_frame mlt_frame_pop_frame( mlt_frame this )
-{
- return mlt_deque_pop_back( this->stack_image );
-}
-
-/** Push a service.
-*/
-
-int mlt_frame_push_service( mlt_frame this, void *that )
-{
- return mlt_deque_push_back( this->stack_image, that );
-}
-
-/** Pop a service.
-*/
-
-void *mlt_frame_pop_service( mlt_frame this )
-{
- return mlt_deque_pop_back( this->stack_image );
-}
-
-/** Push a service.
-*/
-
-int mlt_frame_push_service_int( mlt_frame this, int that )
-{
- return mlt_deque_push_back_int( this->stack_image, that );
-}
-
-/** Pop a service.
-*/
-
-int mlt_frame_pop_service_int( mlt_frame this )
-{
- return mlt_deque_pop_back_int( this->stack_image );
-}
-
-/** Push an audio item on the stack.
-*/
-
-int mlt_frame_push_audio( mlt_frame this, void *that )
-{
- return mlt_deque_push_back( this->stack_audio, that );
-}
-
-/** Pop an audio item from the stack
-*/
-
-void *mlt_frame_pop_audio( mlt_frame this )
-{
- return mlt_deque_pop_back( this->stack_audio );
-}
-
-/** Return the service stack
-*/
-
-mlt_deque mlt_frame_service_stack( mlt_frame this )
-{
- return this->stack_service;
-}
-
-/** Replace image stack with the information provided.
-
- This might prove to be unreliable and restrictive - the idea is that a transition
- which normally uses two images may decide to only use the b frame (ie: in the case
- of a composite where the b frame completely obscures the a frame).
-
- The image must be writable and the destructor for the image itself must be taken
- care of on another frame and that frame cannot have a replace applied to it...
- Further it assumes that no alpha mask is in use.
-
- For these reasons, it can only be used in a specific situation - when you have
- multiple tracks each with their own transition and these transitions are applied
- in a strictly reversed order (ie: highest numbered [lowest track] is processed
- first).
-
- More reliable approach - the cases should be detected during the process phase
- and the upper tracks should simply not be invited to stack...
-*/
-
-void mlt_frame_replace_image( mlt_frame this, uint8_t *image, mlt_image_format format, int width, int height )
-{
- // Remove all items from the stack
- while( mlt_deque_pop_back( this->stack_image ) ) ;
-
- // Update the information
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image, 0, NULL, NULL );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "width", width );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "height", height );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "format", format );
- this->get_alpha_mask = NULL;
-}
-
-/** Get the image associated to the frame.
-*/
-
-int mlt_frame_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- mlt_get_image get_image = mlt_frame_pop_get_image( this );
- mlt_producer producer = mlt_properties_get_data( properties, "test_card_producer", NULL );
- int error = 0;
-
- if ( get_image != NULL )
- {
- mlt_properties_set_int( properties, "image_count", mlt_properties_get_int( properties, "image_count" ) - 1 );
- mlt_position position = mlt_frame_get_position( this );
- error = get_image( this, buffer, format, width, height, writable );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
- mlt_properties_set_int( properties, "format", *format );
- mlt_frame_set_position( this, position );
- }
- else if ( mlt_properties_get_data( properties, "image", NULL ) != NULL )
- {
- *format = mlt_properties_get_int( properties, "format" );
- *buffer = mlt_properties_get_data( properties, "image", NULL );
- *width = mlt_properties_get_int( properties, "width" );
- *height = mlt_properties_get_int( properties, "height" );
- }
- else if ( producer != NULL )
- {
- mlt_frame test_frame = NULL;
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &test_frame, 0 );
- if ( test_frame != NULL )
- {
- mlt_properties test_properties = MLT_FRAME_PROPERTIES( test_frame );
- mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
- mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
- mlt_frame_get_image( test_frame, buffer, format, width, height, writable );
- mlt_properties_set_data( properties, "test_card_frame", test_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
- mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
- mlt_properties_set_int( properties, "format", *format );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( test_frame ) );
- }
- else
- {
- mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
- mlt_frame_get_image( this, buffer, format, width, height, writable );
- }
- }
- else
- {
- register uint8_t *p;
- register uint8_t *q;
- int size = 0;
-
- *width = *width == 0 ? 720 : *width;
- *height = *height == 0 ? 576 : *height;
- size = *width * *height;
-
- mlt_properties_set_int( properties, "format", *format );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
- mlt_properties_set_int( properties, "aspect_ratio", 0 );
-
- switch( *format )
- {
- case mlt_image_none:
- size = 0;
- *buffer = NULL;
- break;
- case mlt_image_rgb24:
- size *= 3;
- size += *width * 3;
- *buffer = mlt_pool_alloc( size );
- if ( *buffer )
- memset( *buffer, 255, size );
- break;
- case mlt_image_rgb24a:
- case mlt_image_opengl:
- size *= 4;
- size += *width * 4;
- *buffer = mlt_pool_alloc( size );
- if ( *buffer )
- memset( *buffer, 255, size );
- break;
- case mlt_image_yuv422:
- size *= 2;
- size += *width * 2;
- *buffer = mlt_pool_alloc( size );
- p = *buffer;
- q = p + size;
- while ( p != NULL && p != q )
- {
- *p ++ = 235;
- *p ++ = 128;
- }
- break;
- case mlt_image_yuv420p:
- size = size * 3 / 2;
- *buffer = mlt_pool_alloc( size );
- if ( *buffer )
- memset( *buffer, 255, size );
- break;
- }
-
- mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "test_image", 1 );
- }
-
- mlt_properties_set_int( properties, "scaled_width", *width );
- mlt_properties_set_int( properties, "scaled_height", *height );
-
- return error;
-}
-
-uint8_t *mlt_frame_get_alpha_mask( mlt_frame this )
-{
- uint8_t *alpha = NULL;
- if ( this != NULL )
- {
- if ( this->get_alpha_mask != NULL )
- alpha = this->get_alpha_mask( this );
- if ( alpha == NULL )
- alpha = mlt_properties_get_data( &this->parent, "alpha", NULL );
- if ( alpha == NULL )
- {
- int size = mlt_properties_get_int( &this->parent, "scaled_width" ) * mlt_properties_get_int( &this->parent, "scaled_height" );
- alpha = mlt_pool_alloc( size );
- memset( alpha, 255, size );
- mlt_properties_set_data( &this->parent, "alpha", alpha, size, mlt_pool_release, NULL );
- }
- }
- return alpha;
-}
-
-int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- mlt_get_audio get_audio = mlt_frame_pop_audio( this );
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- int hide = mlt_properties_get_int( properties, "test_audio" );
-
- if ( hide == 0 && get_audio != NULL )
- {
- mlt_position position = mlt_frame_get_position( this );
- get_audio( this, buffer, format, frequency, channels, samples );
- mlt_frame_set_position( this, position );
- }
- else if ( mlt_properties_get_data( properties, "audio", NULL ) )
- {
- *buffer = mlt_properties_get_data( properties, "audio", NULL );
- *frequency = mlt_properties_get_int( properties, "audio_frequency" );
- *channels = mlt_properties_get_int( properties, "audio_channels" );
- *samples = mlt_properties_get_int( properties, "audio_samples" );
- }
- else
- {
- int size = 0;
- *samples = *samples <= 0 ? 1920 : *samples;
- *channels = *channels <= 0 ? 2 : *channels;
- *frequency = *frequency <= 0 ? 48000 : *frequency;
- size = *samples * *channels * sizeof( int16_t );
- *buffer = mlt_pool_alloc( size );
- if ( *buffer != NULL )
- memset( *buffer, 0, size );
- mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "test_audio", 1 );
- }
-
- mlt_properties_set_int( properties, "audio_frequency", *frequency );
- mlt_properties_set_int( properties, "audio_channels", *channels );
- mlt_properties_set_int( properties, "audio_samples", *samples );
-
- if ( mlt_properties_get( properties, "meta.volume" ) )
- {
- double value = mlt_properties_get_double( properties, "meta.volume" );
-
- if ( value == 0.0 )
- {
- memset( *buffer, 0, *samples * *channels * 2 );
- }
- else if ( value != 1.0 )
- {
- int total = *samples * *channels;
- int16_t *p = *buffer;
- while ( total -- )
- {
- *p = *p * value;
- p ++;
- }
- }
-
- mlt_properties_set( properties, "meta.volume", NULL );
- }
-
- return 0;
-}
-
-unsigned char *mlt_frame_get_waveform( mlt_frame this, int w, int h )
-{
- int16_t *pcm = NULL;
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- mlt_audio_format format = mlt_audio_pcm;
- int frequency = 32000; // lower frequency available?
- int channels = 2;
- double fps = mlt_profile_fps( NULL );
- int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( this ) );
-
- // Get the pcm data
- mlt_frame_get_audio( this, &pcm, &format, &frequency, &channels, &samples );
-
- // Make an 8-bit buffer large enough to hold rendering
- int size = w * h;
- unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
- if ( bitmap != NULL )
- memset( bitmap, 0, size );
- mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Render vertical lines
- int16_t *ubound = pcm + samples * channels;
- int skip = samples / w - 1;
- int i, j, k;
-
- // Iterate sample stream and along x coordinate
- for ( i = 0; i < w && pcm < ubound; i++ )
- {
- // pcm data has channels interleaved
- for ( j = 0; j < channels; j++ )
- {
- // Determine sample's magnitude from 2s complement;
- int pcm_magnitude = *pcm < 0 ? ~(*pcm) + 1 : *pcm;
- // The height of a line is the ratio of the magnitude multiplied by
- // half the vertical resolution
- int height = ( int )( ( double )( pcm_magnitude ) / 32768 * h / 2 );
- // Determine the starting y coordinate - left channel above center,
- // right channel below - currently assumes 2 channels
- int displacement = ( h / 2 ) - ( 1 - j ) * height;
- // Position buffer pointer using y coordinate, stride, and x coordinate
- unsigned char *p = &bitmap[ i + displacement * w ];
-
- // Draw vertical line
- for ( k = 0; k < height; k++ )
- p[ w * k ] = 0xFF;
-
- pcm++;
- }
- pcm += skip * channels;
- }
-
- return bitmap;
-}
-
-mlt_producer mlt_frame_get_original_producer( mlt_frame this )
-{
- if ( this != NULL )
- return mlt_properties_get_data( MLT_FRAME_PROPERTIES( this ), "_producer", NULL );
- return NULL;
-}
-
-void mlt_frame_close( mlt_frame this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_FRAME_PROPERTIES( this ) ) <= 0 )
- {
- mlt_deque_close( this->stack_image );
- mlt_deque_close( this->stack_audio );
- while( mlt_deque_peek_back( this->stack_service ) )
- mlt_service_close( mlt_deque_pop_back( this->stack_service ) );
- mlt_deque_close( this->stack_service );
- mlt_properties_close( &this->parent );
- free( this );
- }
-}
-
-/***** convenience functions *****/
-
-int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total )
-{
- int ret = 0;
- int yy, uu, vv;
- int r,g,b;
- total /= 2;
- while (total--)
- {
- yy = yuv[0];
- uu = yuv[1];
- vv = yuv[3];
- YUV2RGB(yy, uu, vv, r, g, b);
- rgba[0] = r;
- rgba[1] = g;
- rgba[2] = b;
- rgba[3] = 255;
- yy = yuv[2];
- YUV2RGB(yy, uu, vv, r, g, b);
- rgba[4] = r;
- rgba[5] = g;
- rgba[6] = b;
- rgba[7] = 255;
- yuv += 4;
- rgba += 8;
- }
- return ret;
-}
-
-int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
-{
- int ret = 0;
- register int y0, y1, u0, u1, v0, v1;
- register int r, g, b;
- register uint8_t *d = yuv;
- register int i, j;
-
- if ( alpha )
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- r = *s++;
- g = *s++;
- b = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- else
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- r = *s++;
- g = *s++;
- b = *s++;
- s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
-
- return ret;
-}
-
-int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
-{
- int ret = 0;
- register int y0, y1, u0, u1, v0, v1;
- register int r, g, b;
- register uint8_t *d = yuv;
- register int i, j;
-
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgb + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- return ret;
-}
-
-int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
-{
- int ret = 0;
- register int y0, y1, u0, u1, v0, v1;
- register int r, g, b;
- register uint8_t *d = yuv;
- register int i, j;
-
- if ( alpha )
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- b = *s++;
- g = *s++;
- r = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- *alpha++ = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- else
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- b = *s++;
- g = *s++;
- r = *s++;
- s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- return ret;
-}
-
-int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv )
-{
- int ret = 0;
- register int y0, y1, u0, u1, v0, v1;
- register int r, g, b;
- register uint8_t *d = yuv;
- register int i, j;
-
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgb + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- b = *s++;
- g = *s++;
- r = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- b = *s++;
- g = *s++;
- r = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- return ret;
-}
-
-int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha )
-{
- int ret = 0;
- register int y0, y1, u0, u1, v0, v1;
- register int r, g, b;
- register uint8_t *d = yuv;
- register int i, j;
-
- if ( alpha )
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- *alpha++ = *s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *alpha++ = *s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- *alpha++ = *s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- else
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *s = rgba + ( stride * i );
- for ( j = 0; j < ( width / 2 ); j++ )
- {
- s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y1, u1 , v1);
- *d++ = y0;
- *d++ = (u0+u1) >> 1;
- *d++ = y1;
- *d++ = (v0+v1) >> 1;
- }
- if ( width % 2 )
- {
- s++;
- r = *s++;
- g = *s++;
- b = *s++;
- RGB2YUV (r, g, b, y0, u0 , v0);
- *d++ = y0;
- *d++ = u0;
- }
- }
- return ret;
-}
-
-int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv )
-{
- int ret = 0;
- register int i, j;
-
- int half = width >> 1;
-
- uint8_t *Y = yuv420p;
- uint8_t *U = Y + width * height;
- uint8_t *V = U + width * height / 4;
-
- register uint8_t *d = yuv;
-
- for ( i = 0; i < height; i++ )
- {
- register uint8_t *u = U + ( i / 2 ) * ( half );
- register uint8_t *v = V + ( i / 2 ) * ( half );
-
- for ( j = 0; j < half; j++ )
- {
- *d ++ = *Y ++;
- *d ++ = *u ++;
- *d ++ = *Y ++;
- *d ++ = *v ++;
- }
- }
- return ret;
-}
-
-uint8_t *mlt_resize_alpha( uint8_t *input, int owidth, int oheight, int iwidth, int iheight, uint8_t alpha_value )
-{
- uint8_t *output = NULL;
-
- if ( input != NULL && ( iwidth != owidth || iheight != oheight ) && ( owidth > 6 && oheight > 6 ) )
- {
- uint8_t *out_line;
- int offset_x = ( owidth - iwidth ) / 2;
- int offset_y = ( oheight - iheight ) / 2;
- int iused = iwidth;
-
- output = mlt_pool_alloc( owidth * oheight );
- memset( output, alpha_value, owidth * oheight );
-
- offset_x -= offset_x % 2;
-
- out_line = output + offset_y * owidth;
- out_line += offset_x;
-
- // Loop for the entirety of our output height.
- while ( iheight -- )
- {
- // We're in the input range for this row.
- memcpy( out_line, input, iused );
-
- // Move to next input line
- input += iwidth;
-
- // Move to next output line
- out_line += owidth;
- }
- }
-
- return output;
-}
-
-void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
-{
- // Calculate strides
- int istride = iwidth * 2;
- int ostride = owidth * 2;
- int offset_x = ( owidth - iwidth );
- int offset_y = ( oheight - iheight ) / 2;
- uint8_t *in_line = input;
- uint8_t *out_line;
- int size = owidth * oheight;
- uint8_t *p = output;
-
- // Optimisation point
- if ( output == NULL || input == NULL || ( owidth <= 6 || oheight <= 6 || iwidth <= 6 || oheight <= 6 ) )
- {
- return;
- }
- else if ( iwidth == owidth && iheight == oheight )
- {
- memcpy( output, input, iheight * istride );
- return;
- }
-
- while( size -- )
- {
- *p ++ = 16;
- *p ++ = 128;
- }
-
- offset_x -= offset_x % 4;
-
- out_line = output + offset_y * ostride;
- out_line += offset_x;
-
- // Loop for the entirety of our output height.
- while ( iheight -- )
- {
- // We're in the input range for this row.
- memcpy( out_line, in_line, iwidth * 2 );
-
- // Move to next input line
- in_line += istride;
-
- // Move to next output line
- out_line += ostride;
- }
-}
-
-/** A resizing function for yuv422 frames - this does not rescale, but simply
- resizes. It assumes yuv422 images available on the frame so use with care.
-*/
-
-uint8_t *mlt_frame_resize_yuv422( mlt_frame this, int owidth, int oheight )
-{
- // Get properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the input image, width and height
- uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
-
- int iwidth = mlt_properties_get_int( properties, "width" );
- int iheight = mlt_properties_get_int( properties, "height" );
-
- // If width and height are correct, don't do anything
- if ( iwidth != owidth || iheight != oheight )
- {
- uint8_t alpha_value = mlt_properties_get_int( properties, "resize_alpha" );
-
- // Create the output image
- uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- // Call the generic resize
- mlt_resize_yuv422( output, owidth, oheight, input, iwidth, iheight );
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- // We should resize the alpha too
- alpha = mlt_resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value );
- if ( alpha != NULL )
- {
- mlt_properties_set_data( properties, "alpha", alpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL );
- this->get_alpha_mask = NULL;
- }
-
- // Return the output
- return output;
- }
- // No change, return input
- return input;
-}
-
-/** A rescaling function for yuv422 frames - low quality, and provided for testing
- only. It assumes yuv422 images available on the frame so use with care.
-*/
-
-uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
-{
- // Get properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the input image, width and height
- uint8_t *input = mlt_properties_get_data( properties, "image", NULL );
- int iwidth = mlt_properties_get_int( properties, "width" );
- int iheight = mlt_properties_get_int( properties, "height" );
-
- // If width and height are correct, don't do anything
- if ( iwidth != owidth || iheight != oheight )
- {
- // Create the output image
- uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- // Calculate strides
- int istride = iwidth * 2;
- int ostride = owidth * 2;
-
- iwidth = iwidth - ( iwidth % 4 );
-
- // Derived coordinates
- int dy, dx;
-
- // Calculate ranges
- int out_x_range = owidth / 2;
- int out_y_range = oheight / 2;
- int in_x_range = iwidth / 2;
- int in_y_range = iheight / 2;
-
- // Output pointers
- register uint8_t *out_line = output;
- register uint8_t *out_ptr;
-
- // Calculate a middle pointer
- uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
- uint8_t *in_line;
-
- // Generate the affine transform scaling values
- register int scale_width = ( iwidth << 16 ) / owidth;
- register int scale_height = ( iheight << 16 ) / oheight;
- register int base = 0;
-
- int outer = out_x_range * scale_width;
- int bottom = out_y_range * scale_height;
-
- // Loop for the entirety of our output height.
- for ( dy = - bottom; dy < bottom; dy += scale_height )
- {
- // Start at the beginning of the line
- out_ptr = out_line;
-
- // Pointer to the middle of the input line
- in_line = in_middle + ( dy >> 16 ) * istride;
-
- // Loop for the entirety of our output row.
- for ( dx = - outer; dx < outer; dx += scale_width )
- {
- base = dx >> 15;
- base &= 0xfffffffe;
- *out_ptr ++ = *( in_line + base );
- base &= 0xfffffffc;
- *out_ptr ++ = *( in_line + base + 1 );
- dx += scale_width;
- base = dx >> 15;
- base &= 0xfffffffe;
- *out_ptr ++ = *( in_line + base );
- base &= 0xfffffffc;
- *out_ptr ++ = *( in_line + base + 3 );
- }
-
- // Move to next output line
- out_line += ostride;
- }
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- // Return the output
- return output;
- }
-
- // No change, return input
- return input;
-}
-
-int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- int ret = 0;
- int16_t *src, *dest;
- int frequency_src = *frequency, frequency_dest = *frequency;
- int channels_src = *channels, channels_dest = *channels;
- int samples_src = *samples, samples_dest = *samples;
- int i, j;
- double d = 0, s = 0;
-
- mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
- mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
- int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
- if ( silent )
- memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
- silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
- if ( silent )
- memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
- if ( channels_src > 6 )
- channels_src = 0;
- if ( channels_dest > 6 )
- channels_dest = 0;
- if ( samples_src > 4000 )
- samples_src = 0;
- if ( samples_dest > 4000 )
- samples_dest = 0;
-
- // determine number of samples to process
- *samples = samples_src < samples_dest ? samples_src : samples_dest;
- *channels = channels_src < channels_dest ? channels_src : channels_dest;
- *buffer = dest;
- *frequency = frequency_dest;
-
- // Compute a smooth ramp over start to end
- float weight = weight_start;
- float weight_step = ( weight_end - weight_start ) / *samples;
-
- if ( src == dest )
- {
- *samples = samples_src;
- *channels = channels_src;
- *buffer = src;
- *frequency = frequency_src;
- return ret;
- }
-
- // Mixdown
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- if ( j < channels_dest )
- d = (double) dest[ i * channels_dest + j ];
- if ( j < channels_src )
- s = (double) src[ i * channels_src + j ];
- dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
- }
- weight += weight_step;
- }
-
- return ret;
-}
-
-// Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
-// to allow mixing without volume hacking
-int mlt_frame_combine_audio( mlt_frame this, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- int ret = 0;
- int16_t *src, *dest;
- int frequency_src = *frequency, frequency_dest = *frequency;
- int channels_src = *channels, channels_dest = *channels;
- int samples_src = *samples, samples_dest = *samples;
- int i, j;
- double vp[ 6 ];
- double b_weight = 1.0;
-
- if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
- b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
-
- mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
- mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
- int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
- if ( silent )
- memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
- silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
- if ( silent )
- memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
- if ( src == dest )
- {
- *samples = samples_src;
- *channels = channels_src;
- *buffer = src;
- *frequency = frequency_src;
- return ret;
- }
-
- // determine number of samples to process
- *samples = samples_src < samples_dest ? samples_src : samples_dest;
- *channels = channels_src < channels_dest ? channels_src : channels_dest;
- *buffer = dest;
- *frequency = frequency_dest;
-
- for ( j = 0; j < *channels; j++ )
- vp[ j ] = ( double )dest[ j ];
-
- double Fc = 0.5;
- double B = exp(-2.0 * M_PI * Fc);
- double A = 1.0 - B;
- double v;
-
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
- v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
- vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
- }
- }
-
- return ret;
-}
-
-/* Will this break when mlt_position is converted to double? -Zach */
-int mlt_sample_calculator( float fps, int frequency, int64_t position )
-{
- int samples = 0;
-
- if ( ( int )( fps * 100 ) == 2997 )
- {
- samples = frequency / 30;
-
- switch ( frequency )
- {
- case 48000:
- if ( position % 5 != 0 )
- samples += 2;
- break;
- case 44100:
- if ( position % 300 == 0 )
- samples = 1471;
- else if ( position % 30 == 0 )
- samples = 1470;
- else if ( position % 2 == 0 )
- samples = 1472;
- else
- samples = 1471;
- break;
- case 32000:
- if ( position % 30 == 0 )
- samples = 1068;
- else if ( position % 29 == 0 )
- samples = 1067;
- else if ( position % 4 == 2 )
- samples = 1067;
- else
- samples = 1068;
- break;
- default:
- samples = 0;
- }
- }
- else if ( fps != 0 )
- {
- samples = frequency / fps;
- }
-
- return samples;
-}
-
-int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t frame )
-{
- int64_t samples = 0;
-
- // TODO: Correct rules for NTSC and drop the * 100 hack
- if ( ( int )( fps * 100 ) == 2997 )
- {
- samples = ( ( double )( frame * frequency ) / 30 );
- switch( frequency )
- {
- case 48000:
- samples += 2 * ( frame / 5 );
- break;
- case 44100:
- samples += frame + ( frame / 2 ) - ( frame / 30 ) + ( frame / 300 );
- break;
- case 32000:
- samples += ( 2 * frame ) - ( frame / 4 ) - ( frame / 29 );
- break;
- }
- }
- else if ( fps != 0 )
- {
- samples = ( ( frame * frequency ) / ( int )fps );
- }
-
- return samples;
-}
+++ /dev/null
-/**
- * \file mlt_frame.h
- * \brief interface for all frame classes
- * \see mlt_frame_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_FRAME_H_
-#define _MLT_FRAME_H_
-
-#include "mlt_properties.h"
-#include "mlt_deque.h"
-#include "mlt_service.h"
-
-/** callback function to get video data
- *
- */
-
-typedef int ( *mlt_get_image )( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
-
-/** callback function to get audio data
- *
- */
-
-typedef int ( *mlt_get_audio )( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
-
-/** \brief Frame class
- *
- * \properties \em test_image set if the frame holds a "test card" image
- * \properties \em test_audio set if the frame holds "test card" audio
- * \properties \em _producer holds a reference to the frame's end producer
- * \properties \em _speed the current speed of the producer that generated the frame
- * \properties \em _position the position of the frame
- * \properties \em meta.* holds metadata
- * \properties \em hide set to 1 to hide the video, 2 to mute the audio
- * \properties \em last_track a flag to indicate an end-of-tracks frame
- */
-
-struct mlt_frame_s
-{
- /* We're extending properties here */
- struct mlt_properties_s parent;
-
- /* Virtual methods */
- uint8_t * ( *get_alpha_mask )( mlt_frame self );
-
- /* Private properties */
- mlt_deque stack_image;
- mlt_deque stack_audio;
- mlt_deque stack_service;
-};
-
-#define MLT_FRAME_PROPERTIES( frame ) ( &( frame )->parent )
-#define MLT_FRAME_SERVICE_STACK( frame ) ( ( frame )->stack_service )
-#define MLT_FRAME_IMAGE_STACK( frame ) ( ( frame )->stack_image )
-#define MLT_FRAME_AUDIO_STACK( frame ) ( ( frame )->stack_audio )
-
-extern mlt_frame mlt_frame_init( mlt_service service );
-extern mlt_properties mlt_frame_properties( mlt_frame self );
-extern int mlt_frame_is_test_card( mlt_frame self );
-extern int mlt_frame_is_test_audio( mlt_frame self );
-extern double mlt_frame_get_aspect_ratio( mlt_frame self );
-extern int mlt_frame_set_aspect_ratio( mlt_frame self, double value );
-extern mlt_position mlt_frame_get_position( mlt_frame self );
-extern int mlt_frame_set_position( mlt_frame self, mlt_position value );
-extern void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height );
-extern int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
-extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame self );
-extern int mlt_frame_get_audio( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
-extern unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h );
-extern int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image );
-extern mlt_get_image mlt_frame_pop_get_image( mlt_frame self );
-extern int mlt_frame_push_frame( mlt_frame self, mlt_frame that );
-extern mlt_frame mlt_frame_pop_frame( mlt_frame self );
-extern int mlt_frame_push_service( mlt_frame self, void *that );
-extern void *mlt_frame_pop_service( mlt_frame self );
-extern int mlt_frame_push_service_int( mlt_frame self, int that );
-extern int mlt_frame_pop_service_int( mlt_frame self );
-extern int mlt_frame_push_audio( mlt_frame self, void *that );
-extern void *mlt_frame_pop_audio( mlt_frame self );
-extern mlt_deque mlt_frame_service_stack( mlt_frame self );
-extern mlt_producer mlt_frame_get_original_producer( mlt_frame self );
-extern void mlt_frame_close( mlt_frame self );
-
-/* convenience functions */
-extern int mlt_convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, unsigned int total );
-extern int mlt_convert_rgb24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha );
-extern int mlt_convert_rgb24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv );
-extern int mlt_convert_bgr24a_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha );
-extern int mlt_convert_argb_to_yuv422( uint8_t *rgba, int width, int height, int stride, uint8_t *yuv, uint8_t *alpha );
-extern int mlt_convert_bgr24_to_yuv422( uint8_t *rgb, int width, int height, int stride, uint8_t *yuv );
-extern int mlt_convert_yuv420p_to_yuv422( uint8_t *yuv420p, int width, int height, int stride, uint8_t *yuv );
-extern uint8_t *mlt_frame_resize_yuv422( mlt_frame self, int owidth, int oheight );
-extern uint8_t *mlt_frame_rescale_yuv422( mlt_frame self, int owidth, int oheight );
-extern void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight );
-extern int mlt_frame_mix_audio( mlt_frame self, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
-extern int mlt_frame_combine_audio( mlt_frame self, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
-extern int mlt_sample_calculator( float fps, int frequency, int64_t position );
-extern int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position );
-
-/** This macro scales rgb into the yuv gamut - y is scaled by 219/255 and uv by 224/255. */
-#define RGB2YUV(r, g, b, y, u, v)\
- y = ((263*r + 516*g + 100*b) >> 10) + 16;\
- u = ((-152*r - 298*g + 450*b) >> 10) + 128;\
- v = ((450*r - 377*g - 73*b) >> 10) + 128;
-
-/** This macro assumes the user has already scaled their rgb down into the broadcast limits. **/
-#define RGB2YUV_UNSCALED(r, g, b, y, u, v)\
- y = (299*r + 587*g + 114*b) >> 10;\
- u = ((-169*r - 331*g + 500*b) >> 10) + 128;\
- v = ((500*r - 419*g - 81*b) >> 10) + 128;\
- y = y < 16 ? 16 : y;\
- u = u < 16 ? 16 : u;\
- v = v < 16 ? 16 : v;\
- y = y > 235 ? 235 : y;\
- u = u > 240 ? 240 : u;\
- v = v > 240 ? 240 : v
-
-/** This macro converts a YUV value to the RGB color space. */
-#define YUV2RGB( y, u, v, r, g, b ) \
- r = ((1192 * ( y - 16 ) + 1634 * ( v - 128 ) ) >> 10 ); \
- g = ((1192 * ( y - 16 ) - 832 * ( v - 128 ) - 400 * ( u - 128 ) ) >> 10 ); \
- b = ((1192 * ( y - 16 ) + 2066 * ( u - 128 ) ) >> 10 ); \
- r = r < 0 ? 0 : r > 255 ? 255 : r; \
- g = g < 0 ? 0 : g > 255 ? 255 : g; \
- b = b < 0 ? 0 : b > 255 ? 255 : b;
-
-#endif
+++ /dev/null
-/*
- * mlt_geometry.c -- provides the geometry API
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_geometry.h"
-#include "mlt_tokeniser.h"
-#include "mlt_factory.h"
-#include "mlt_profile.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-typedef struct geometry_item_s
-{
- struct mlt_geometry_item_s data;
- struct geometry_item_s *next, *prev;
-}
-*geometry_item;
-
-typedef struct
-{
- char *data;
- int length;
- int nw;
- int nh;
- geometry_item item;
-}
-geometry_s, *geometry;
-
-// Create a new geometry structure
-mlt_geometry mlt_geometry_init( )
-{
- mlt_geometry this = calloc( 1, sizeof( struct mlt_geometry_s ) );
- if ( this != NULL )
- {
- this->local = calloc( 1, sizeof( geometry_s ) );
- if ( this->local != NULL )
- {
- geometry self = this->local;
- self->nw = 720;
- self->nh = 576;
- }
- else
- {
- free( this );
- this = NULL;
- }
- }
- return this;
-}
-
-/** A linear step
-*/
-
-static inline double linearstep( double start, double end, double position, int length )
-{
- double o = ( end - start ) / length;
- return start + position * o;
-}
-
-static void mlt_geometry_virtual_refresh( mlt_geometry this )
-{
- geometry self = this->local;
-
- // Parse of all items to ensure unspecified keys are calculated correctly
- if ( self->item != NULL )
- {
- int i = 0;
- for ( i = 0; i < 5; i ++ )
- {
- geometry_item current = self->item;
- while( current != NULL )
- {
- int fixed = current->data.f[ i ];
- if ( !fixed )
- {
- geometry_item prev = current->prev;
- geometry_item next = current->next;
-
- double prev_value = 0;
- double next_value = 0;
- double value = 0;
-
- while( prev != NULL && !prev->data.f[ i ] ) prev = prev->prev;
- while( next != NULL && !next->data.f[ i ] ) next = next->next;
-
- switch( i )
- {
- case 0:
- if ( prev ) prev_value = prev->data.x;
- if ( next ) next_value = next->data.x;
- break;
- case 1:
- if ( prev ) prev_value = prev->data.y;
- if ( next ) next_value = next->data.y;
- break;
- case 2:
- if ( prev ) prev_value = prev->data.w;
- if ( next ) next_value = next->data.w;
- break;
- case 3:
- if ( prev ) prev_value = prev->data.h;
- if ( next ) next_value = next->data.h;
- break;
- case 4:
- if ( prev ) prev_value = prev->data.mix;
- if ( next ) next_value = next->data.mix;
- break;
- }
-
- // This should never happen
- if ( prev == NULL )
- current->data.f[ i ] = 1;
- else if ( next == NULL )
- value = prev_value;
- else
- value = linearstep( prev_value, next_value, current->data.frame - prev->data.frame, next->data.frame - prev->data.frame );
-
- switch( i )
- {
- case 0: current->data.x = value; break;
- case 1: current->data.y = value; break;
- case 2: current->data.w = value; break;
- case 3: current->data.h = value; break;
- case 4: current->data.mix = value; break;
- }
- }
-
- // Move to the next item
- current = current->next;
- }
- }
- }
-}
-
-static int mlt_geometry_drop( mlt_geometry this, geometry_item item )
-{
- geometry self = this->local;
-
- if ( item == self->item )
- {
- self->item = item->next;
- if ( self->item != NULL )
- self->item->prev = NULL;
- // To ensure correct seeding, ensure all values are fixed
- if ( self->item != NULL )
- {
- self->item->data.f[0] = 1;
- self->item->data.f[1] = 1;
- self->item->data.f[2] = 1;
- self->item->data.f[3] = 1;
- self->item->data.f[4] = 1;
- }
- }
- else if ( item->next != NULL && item->prev != NULL )
- {
- item->prev->next = item->next;
- item->next->prev = item->prev;
- }
- else if ( item->next != NULL )
- {
- item->next->prev = item->prev;
- }
- else if ( item->prev != NULL )
- {
- item->prev->next = item->next;
- }
-
- free( item );
-
- return 0;
-}
-
-static void mlt_geometry_clean( mlt_geometry this )
-{
- geometry self = this->local;
- free( self->data );
- self->data = NULL;
- while( self->item )
- mlt_geometry_drop( this, self->item );
-}
-
-// Parse the geometry specification for a given length and normalised width/height (-1 for default)
-// data is constructed as: [frame=]X,Y:WxH[:mix][;[frame=]X,Y:WxH[:mix]]*
-// and X, Y, W and H can have trailing % chars to indicate percentage of normalised size
-int mlt_geometry_parse( mlt_geometry this, char *data, int length, int nw, int nh )
-{
- int i = 0;
-
- // Create a tokeniser
- mlt_tokeniser tokens = mlt_tokeniser_init( );
-
- // Get the local/private structure
- geometry self = this->local;
-
- // Clean the existing geometry
- mlt_geometry_clean( this );
-
- // Update the info on the data
- if ( length != -1 )
- self->length = length;
- if ( nw != -1 )
- self->nw = nw;
- if ( nh != -1 )
- self->nh = nh;
- if ( data != NULL )
- self->data = strdup( data );
-
- // Tokenise
- if ( data != NULL )
- mlt_tokeniser_parse_new( tokens, data, ";" );
-
- // Iterate through each token
- for ( i = 0; i < mlt_tokeniser_count( tokens ); i ++ )
- {
- struct mlt_geometry_item_s item;
- char *value = mlt_tokeniser_get_string( tokens, i );
-
- // Set item to 0
- memset( &item, 0, sizeof( struct mlt_geometry_item_s ) );
-
- // Now parse the item
- mlt_geometry_parse_item( this, &item, value );
-
- // Now insert into place
- mlt_geometry_insert( this, &item );
- }
-
- // Remove the tokeniser
- mlt_tokeniser_close( tokens );
-
- // ???
- return 0;
-}
-
-// Conditionally refresh in case of a change
-int mlt_geometry_refresh( mlt_geometry this, char *data, int length, int nw, int nh )
-{
- geometry self = this->local;
- int changed = ( length != -1 && length != self->length );
- changed = changed || ( nw != -1 && nw != self->nw );
- changed = changed || ( nh != -1 && nh != self->nh );
- changed = changed || ( data != NULL && ( self->data == NULL || strcmp( data, self->data ) ) );
- if ( changed )
- return mlt_geometry_parse( this, data, length, nw, nh );
- return -1;
-}
-
-int mlt_geometry_get_length( mlt_geometry this )
-{
- // Get the local/private structure
- geometry self = this->local;
-
- // return the length
- return self->length;
-}
-
-void mlt_geometry_set_length( mlt_geometry this, int length )
-{
- // Get the local/private structure
- geometry self = this->local;
-
- // set the length
- self->length = length;
-}
-
-int mlt_geometry_parse_item( mlt_geometry this, mlt_geometry_item item, char *value )
-{
- int ret = 0;
-
- // Get the local/private structure
- geometry self = this->local;
-
- if ( value != NULL && strcmp( value, "" ) )
- {
- char *p = strchr( value, '=' );
- int count = 0;
- double temp;
-
- // Determine if a position has been specified
- if ( p != NULL )
- {
- temp = atof( value );
- if ( temp > -1 && temp < 1 )
- item->frame = temp * self->length;
- else
- item->frame = temp;
- value = p + 1;
- }
-
- // Special case - frame < 0
- if ( item->frame < 0 )
- item->frame += self->length;
-
- // Obtain the current value at this position - this allows new
- // frames to be created which don't specify all values
- mlt_geometry_fetch( this, item, item->frame );
-
- // Special case - when an empty string is specified, all values are fixed
- // TODO: Check if this is logical - it's convenient, but it's also odd...
- if ( !*value )
- {
- item->f[0] = 1;
- item->f[1] = 1;
- item->f[2] = 1;
- item->f[3] = 1;
- item->f[4] = 1;
- }
-
- // Iterate through the remainder of value
- while( *value )
- {
- // Get the value
- temp = strtod( value, &p );
-
- // Check if a value was specified
- if ( p != value )
- {
- // Handle the % case
- if ( *p == '%' )
- {
- if ( count == 0 || count == 2 )
- temp *= self->nw / 100.0;
- else if ( count == 1 || count == 3 )
- temp *= self->nh / 100.0;
- p ++;
- }
-
- // Special case - distort token
- if ( *p == '!' || *p == '*' )
- {
- p ++;
- item->distort = 1;
- }
-
- // Actually, we don't care about the delimiter at all..
- if ( *p ) p ++;
-
- // Assign to the item
- switch( count )
- {
- case 0: item->x = temp; item->f[0] = 1; break;
- case 1: item->y = temp; item->f[1] = 1; break;
- case 2: item->w = temp; item->f[2] = 1; break;
- case 3: item->h = temp; item->f[3] = 1; break;
- case 4: item->mix = temp; item->f[4] = 1; break;
- }
- }
- else
- {
- p ++;
- }
-
- // Update the value pointer
- value = p;
- count ++;
- }
- }
- else
- {
- ret = 1;
- }
-
- return ret;
-}
-
-// Fetch a geometry item for an absolute position
-int mlt_geometry_fetch( mlt_geometry this, mlt_geometry_item item, float position )
-{
- // Get the local geometry
- geometry self = this->local;
-
- // Need to find the nearest key to the position specifed
- geometry_item key = self->item;
-
- // Iterate through the keys until we reach last or have
- while( key != NULL && key->next != NULL && position >= key->next->data.frame )
- key = key->next;
-
- if ( key != NULL )
- {
- // Position is situated before the first key - all zeroes
- if ( position < key->data.frame )
- {
- memset( item, 0, sizeof( struct mlt_geometry_item_s ) );
- item->mix = 100;
- }
- // Position is a key itself - no iterpolation need
- else if ( position == key->data.frame )
- {
- memcpy( item, &key->data, sizeof( struct mlt_geometry_item_s ) );
- }
- // Position is after the last key - no interpolation, but not a key frame
- else if ( key->next == NULL )
- {
- memcpy( item, &key->data, sizeof( struct mlt_geometry_item_s ) );
- item->key = 0;
- item->f[ 0 ] = 0;
- item->f[ 1 ] = 0;
- item->f[ 2 ] = 0;
- item->f[ 3 ] = 0;
- item->f[ 4 ] = 0;
- }
- // Interpolation is needed - position > key and there is a following key
- else
- {
- item->key = 0;
- item->frame = position;
- position -= key->data.frame;
- item->x = linearstep( key->data.x, key->next->data.x, position, key->next->data.frame - key->data.frame );
- item->y = linearstep( key->data.y, key->next->data.y, position, key->next->data.frame - key->data.frame );
- item->w = linearstep( key->data.w, key->next->data.w, position, key->next->data.frame - key->data.frame );
- item->h = linearstep( key->data.h, key->next->data.h, position, key->next->data.frame - key->data.frame );
- item->mix = linearstep( key->data.mix, key->next->data.mix, position, key->next->data.frame - key->data.frame );
- item->distort = key->data.distort;
- position += key->data.frame;
- }
-
- item->frame = position;
- }
- else
- {
- memset( item, 0, sizeof( struct mlt_geometry_item_s ) );
- item->frame = position;
- item->mix = 100;
- }
-
- return key == NULL;
-}
-
-// Specify a geometry item at an absolute position
-int mlt_geometry_insert( mlt_geometry this, mlt_geometry_item item )
-{
- // Get the local/private geometry structure
- geometry self = this->local;
-
- // Create a new local item (this may be removed if a key already exists at this position)
- geometry_item new = calloc( 1, sizeof( struct geometry_item_s ) );
- memcpy( &new->data, item, sizeof( struct mlt_geometry_item_s ) );
- new->data.key = 1;
-
- // Determine if we need to insert or append to the list, or if it's a new list
- if ( self->item != NULL )
- {
- // Get the first item
- geometry_item place = self->item;
-
- // Locate an existing nearby item
- while ( place->next != NULL && item->frame > place->data.frame )
- place = place->next;
-
- if ( item->frame < place->data.frame )
- {
- if ( place == self->item )
- self->item = new;
- if ( place->prev )
- place->prev->next = new;
- new->next = place;
- new->prev = place->prev;
- place->prev = new;
- }
- else if ( item->frame > place->data.frame )
- {
- if ( place->next )
- place->next->prev = new;
- new->next = place->next;
- new->prev = place;
- place->next = new;
- }
- else
- {
- memcpy( &place->data, &new->data, sizeof( struct mlt_geometry_item_s ) );
- free( new );
- }
- }
- else
- {
- // Set the first item
- self->item = new;
-
- // To ensure correct seeding, ensure all values are fixed
- self->item->data.f[0] = 1;
- self->item->data.f[1] = 1;
- self->item->data.f[2] = 1;
- self->item->data.f[3] = 1;
- self->item->data.f[4] = 1;
- }
-
- // Refresh all geometries
- mlt_geometry_virtual_refresh( this );
-
- // TODO: Error checking
- return 0;
-}
-
-// Remove the key at the specified position
-int mlt_geometry_remove( mlt_geometry this, int position )
-{
- int ret = 1;
-
- // Get the local/private geometry structure
- geometry self = this->local;
-
- // Get the first item
- geometry_item place = self->item;
-
- while( place != NULL && position != place->data.frame )
- place = place->next;
-
- if ( place != NULL && position == place->data.frame )
- ret = mlt_geometry_drop( this, place );
-
- // Refresh all geometries
- mlt_geometry_virtual_refresh( this );
-
- return ret;
-}
-
-// Get the key at the position or the next following
-int mlt_geometry_next_key( mlt_geometry this, mlt_geometry_item item, int position )
-{
- // Get the local/private geometry structure
- geometry self = this->local;
-
- // Get the first item
- geometry_item place = self->item;
-
- while( place != NULL && position > place->data.frame )
- place = place->next;
-
- if ( place != NULL )
- memcpy( item, &place->data, sizeof( struct mlt_geometry_item_s ) );
-
- return place == NULL;
-}
-
-// Get the key at the position or the previous key
-int mlt_geometry_prev_key( mlt_geometry this, mlt_geometry_item item, int position )
-{
- // Get the local/private geometry structure
- geometry self = this->local;
-
- // Get the first item
- geometry_item place = self->item;
-
- while( place != NULL && place->next != NULL && position >= place->next->data.frame )
- place = place->next;
-
- if ( place != NULL )
- memcpy( item, &place->data, sizeof( struct mlt_geometry_item_s ) );
-
- return place == NULL;
-}
-
-char *mlt_geometry_serialise_cut( mlt_geometry this, int in, int out )
-{
- geometry self = this->local;
- struct mlt_geometry_item_s item;
- char *ret = malloc( 1000 );
- int used = 0;
- int size = 1000;
-
- if ( in == -1 )
- in = 0;
- if ( out == -1 )
- out = mlt_geometry_get_length( this );
-
- if ( ret != NULL )
- {
- char temp[ 100 ];
-
- strcpy( ret, "" );
-
- item.frame = in;
-
- while( 1 )
- {
- strcpy( temp, "" );
-
- // If it's the first frame, then it's not necessarily a key
- if ( item.frame == in )
- {
- if ( mlt_geometry_fetch( this, &item, item.frame ) )
- break;
-
- // If the first key is larger than the current position
- // then do nothing here
- if ( self->item->data.frame > item.frame )
- {
- item.frame ++;
- continue;
- }
-
- // To ensure correct seeding, ensure all values are fixed
- item.f[0] = 1;
- item.f[1] = 1;
- item.f[2] = 1;
- item.f[3] = 1;
- item.f[4] = 1;
- }
- // Typically, we move from key to key
- else if ( item.frame < out )
- {
- if ( mlt_geometry_next_key( this, &item, item.frame ) )
- break;
-
- // Special case - crop at the out point
- if ( item.frame > out )
- mlt_geometry_fetch( this, &item, out );
- }
- // We've handled the last key
- else
- {
- break;
- }
-
- if ( item.frame - in != 0 )
- sprintf( temp, "%d=", item.frame - in );
-
- if ( item.f[0] )
- sprintf( temp + strlen( temp ), "%.0f", item.x );
- strcat( temp, "," );
- if ( item.f[1] )
- sprintf( temp + strlen( temp ), "%.0f", item.y );
- strcat( temp, ":" );
- if ( item.f[2] )
- sprintf( temp + strlen( temp ), "%.0f", item.w );
- strcat( temp, "x" );
- if ( item.f[3] )
- sprintf( temp + strlen( temp ), "%.0f", item.h );
- if ( item.f[4] )
- sprintf( temp + strlen( temp ), ":%.0f", item.mix );
-
- if ( used + strlen( temp ) > size )
- {
- size += 1000;
- ret = realloc( ret, size );
- }
-
- if ( ret != NULL && used != 0 )
- {
- used ++;
- strcat( ret, ";" );
- }
- if ( ret != NULL )
- {
- used += strlen( temp );
- strcat( ret, temp );
- }
-
- item.frame ++;
- }
- }
-
- return ret;
-}
-
-// Serialise the current geometry
-char *mlt_geometry_serialise( mlt_geometry this )
-{
- geometry self = this->local;
- char *ret = mlt_geometry_serialise_cut( this, 0, self->length );
- if ( ret )
- {
- free( self->data );
- self->data = ret;
- }
- return ret;
-}
-
-// Close the geometry
-void mlt_geometry_close( mlt_geometry this )
-{
- if ( this != NULL )
- {
- mlt_geometry_clean( this );
- free( this->local );
- free( this );
- }
-}
-
-
+++ /dev/null
-/*
- * mlt_geometry.h -- provides the geometry API
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_GEOMETRY_H
-#define _MLT_GEOMETRY_H
-
-#include "mlt_types.h"
-
-struct mlt_geometry_item_s
-{
- /* Will be 1 when this is a key frame */
- int key;
- /* The actual frame this corresponds to */
- int frame;
- /* Distort */
- int distort;
- /* x,y are upper left */
- float x, y, w, h, mix;
- /* Indicates which values are fixed */
- int f[ 5 ];
-};
-
-struct mlt_geometry_s
-{
- void *local;
-};
-
-/* Create a new geometry structure */
-extern mlt_geometry mlt_geometry_init( );
-/* Parse the geometry specification for a given length and normalised width/height (-1 for default) */
-extern int mlt_geometry_parse( mlt_geometry self, char *data, int length, int nw, int nh );
-/* Conditionally refresh the geometry if it's modified */
-extern int mlt_geometry_refresh( mlt_geometry self, char *data, int length, int nw, int nh );
-/* Get and set the length */
-extern int mlt_geometry_get_length( mlt_geometry self );
-extern void mlt_geometry_set_length( mlt_geometry self, int length );
-/* Parse an item - doesn't affect the geometry itself but uses current information for evaluation */
-/* (item->frame should be specified if not included in the data itself) */
-extern int mlt_geometry_parse_item( mlt_geometry self, mlt_geometry_item item, char *data );
-/* Fetch a geometry item for an absolute position */
-extern int mlt_geometry_fetch( mlt_geometry self, mlt_geometry_item item, float position );
-/* Specify a geometry item at an absolute position */
-extern int mlt_geometry_insert( mlt_geometry self, mlt_geometry_item item );
-/* Remove the key at the specified position */
-extern int mlt_geometry_remove( mlt_geometry self, int position );
-/* Get the key at the position or the next following */
-extern int mlt_geometry_next_key( mlt_geometry self, mlt_geometry_item item, int position );
-extern int mlt_geometry_prev_key( mlt_geometry self, mlt_geometry_item item, int position );
-/* Serialise the current geometry */
-extern char *mlt_geometry_serialise_cut( mlt_geometry self, int in, int out );
-extern char *mlt_geometry_serialise( mlt_geometry self );
-/* Close the geometry */
-extern void mlt_geometry_close( mlt_geometry self );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_log.c
- * \brief logging functions
- *
- * Copyright (c) 2003 Michel Bardiaux
- *
- * This file was a part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "mlt_log.h"
-#include "mlt_service.h"
-
-#include <string.h>
-
-static int log_level = MLT_LOG_INFO;
-
-void default_callback( void* ptr, int level, const char* fmt, va_list vl )
-{
- static int print_prefix = 1;
- mlt_properties properties = ptr ? MLT_SERVICE_PROPERTIES( ( mlt_service )ptr ) : NULL;
-
- if ( level > log_level )
- return;
- if ( print_prefix && properties )
- {
- char *mlt_type = mlt_properties_get( properties, "mlt_type" );
- char *resource = mlt_properties_get( properties, "resource" );
-
- if ( resource && *resource && resource[0] == '<' && resource[ strlen(resource) - 1 ] == '>' )
- mlt_type = resource;
- fprintf( stderr, "[%s @ %p]", mlt_type, ptr );
- }
- print_prefix = strstr( fmt, "\n" ) != NULL;
- vfprintf( stderr, fmt, vl );
-}
-
-static void ( *callback )( void*, int, const char*, va_list ) = default_callback;
-
-void mlt_log( void* service, int level, const char *fmt, ...)
-{
- va_list vl;
-
- va_start( vl, fmt );
- mlt_vlog( service, level, fmt, vl );
- va_end( vl );
-}
-
-void mlt_vlog( void* service, int level, const char *fmt, va_list vl )
-{
- if ( callback ) callback( service, level, fmt, vl );
-}
-
-int mlt_log_get_level( void )
-{
- return log_level;
-}
-
-void mlt_log_set_level( int level )
-{
- log_level = level;
-}
-
-void mlt_log_set_callback( void (*new_callback)( void*, int, const char*, va_list ) )
-{
- callback = new_callback;
-}
+++ /dev/null
-/**
- * \file mlt_log.h
- * \brief logging functions
- *
- * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
- *
- * This file was a part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef MLT_LOG_H
-#define MLT_LOG_H
-
-#include <stdarg.h>
-
-#define MLT_LOG_QUIET -8
-
-/**
- * something went really wrong and we will crash now
- */
-#define MLT_LOG_PANIC 0
-
-/**
- * something went wrong and recovery is not possible
- * like no header in a format which depends on it or a combination
- * of parameters which are not allowed
- */
-#define MLT_LOG_FATAL 8
-
-/**
- * something went wrong and cannot losslessly be recovered
- * but not all future data is affected
- */
-#define MLT_LOG_ERROR 16
-
-/**
- * something somehow does not look correct / something which may or may not
- * lead to some problems
- */
-#define MLT_LOG_WARNING 24
-
-#define MLT_LOG_INFO 32
-#define MLT_LOG_VERBOSE 40
-
-/**
- * stuff which is only useful for MLT developers
- */
-#define MLT_LOG_DEBUG 48
-
-/**
- * Send the specified message to the log if the level is less than or equal to
- * the current logging level. By default, all logging messages are sent to
- * stderr. This behavior can be altered by setting a different mlt_vlog callback
- * function.
- *
- * \param service An optional pointer to a \p mlt_service_s.
- * \param level The importance level of the message, lower values signifying
- * higher importance.
- * \param fmt The format string (printf-compatible) that specifies how
- * subsequent arguments are converted to output.
- * \see mlt_vlog
- */
-#ifdef __GNUC__
-void mlt_log( void *service, int level, const char *fmt, ... ) __attribute__ ((__format__ (__printf__, 3, 4)));
-#else
-void mlt_log( void *service, int level, const char *fmt, ... );
-#endif
-
-#define mlt_log_panic(service, format, args...) mlt_log((service), MLT_LOG_PANIC, (format), ## args)
-#define mlt_log_fatal(service, format, args...) mlt_log((service), MLT_LOG_FATAL, (format), ## args)
-#define mlt_log_error(service, format, args...) mlt_log((service), MLT_LOG_ERROR, (format), ## args)
-#define mlt_log_warning(service, format, args...) mlt_log((service), MLT_LOG_WARNING, (format), ## args)
-#define mlt_log_info(service, format, args...) mlt_log((service), MLT_LOG_INFO, (format), ## args)
-#define mlt_log_verbose(service, format, args...) mlt_log((service), MLT_LOG_VERBOSE, (format), ## args)
-#define mlt_log_debug(service, format, args...) mlt_log((service), MLT_LOG_DEBUG, (format), ## args)
-
-void mlt_vlog( void *service, int level, const char *fmt, va_list );
-int mlt_log_get_level( void );
-void mlt_log_set_level( int );
-void mlt_log_set_callback( void (*)( void*, int, const char*, va_list ) );
-
-#endif /* MLT_LOG_H */
+++ /dev/null
-/**
- * \file mlt_multitrack.c
- * \brief multitrack service class
- * \see mlt_multitrack_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_multitrack.h"
-#include "mlt_playlist.h"
-#include "mlt_frame.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/* Forward reference. */
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
-
-/** Construct and initialize a new multitrack.
- *
- * Sets the resource property to "<multitrack>".
- *
- * \public \memberof mlt_multitrack_s
- * \return a new multitrack
- */
-
-mlt_multitrack mlt_multitrack_init( )
-{
- // Allocate the multitrack object
- mlt_multitrack this = calloc( sizeof( struct mlt_multitrack_s ), 1 );
-
- if ( this != NULL )
- {
- mlt_producer producer = &this->parent;
- if ( mlt_producer_init( producer, this ) == 0 )
- {
- mlt_properties properties = MLT_MULTITRACK_PROPERTIES( this );
- producer->get_frame = producer_get_frame;
- mlt_properties_set_data( properties, "multitrack", this, 0, NULL, NULL );
- mlt_properties_set( properties, "log_id", "multitrack" );
- mlt_properties_set( properties, "resource", "<multitrack>" );
- mlt_properties_set_int( properties, "in", 0 );
- mlt_properties_set_int( properties, "out", -1 );
- mlt_properties_set_int( properties, "length", 0 );
- producer->close = ( mlt_destructor )mlt_multitrack_close;
- }
- else
- {
- free( this );
- this = NULL;
- }
- }
-
- return this;
-}
-
-/** Get the producer associated to this multitrack.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \return the producer object
- * \see MLT_MULTITRACK_PRODUCER
- */
-
-mlt_producer mlt_multitrack_producer( mlt_multitrack this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the service associated this multitrack.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \return the service object
- * \see MLT_MULTITRACK_SERVICE
- */
-
-mlt_service mlt_multitrack_service( mlt_multitrack this )
-{
- return MLT_MULTITRACK_SERVICE( this );
-}
-
-/** Get the properties associated this multitrack.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \return the multitrack's property list
- * \see MLT_MULTITRACK_PROPERTIES
- */
-
-mlt_properties mlt_multitrack_properties( mlt_multitrack this )
-{
- return MLT_MULTITRACK_PROPERTIES( this );
-}
-
-/** Initialize position related information.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- */
-
-void mlt_multitrack_refresh( mlt_multitrack this )
-{
- int i = 0;
-
- // Obtain the properties of this multitrack
- mlt_properties properties = MLT_MULTITRACK_PROPERTIES( this );
-
- // We need to ensure that the multitrack reports the longest track as its length
- mlt_position length = 0;
-
- // Obtain stats on all connected services
- for ( i = 0; i < this->count; i ++ )
- {
- // Get the producer from this index
- mlt_track track = this->list[ i ];
- mlt_producer producer = track->producer;
-
- // If it's allocated then, update our stats
- if ( producer != NULL )
- {
- // If we have more than 1 track, we must be in continue mode
- if ( this->count > 1 )
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "continue" );
-
- // Determine the longest length
- //if ( !mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "hide" ) )
- length = mlt_producer_get_playtime( producer ) > length ? mlt_producer_get_playtime( producer ) : length;
- }
- }
-
- // Update multitrack properties now - we'll not destroy the in point here
- mlt_events_block( properties, properties );
- mlt_properties_set_position( properties, "length", length );
- mlt_events_unblock( properties, properties );
- mlt_properties_set_position( properties, "out", length - 1 );
-}
-
-/** Listener for producers on the playlist.
- *
- * \private \memberof mlt_multitrack_s
- * \param producer a producer
- * \param this a multitrack
- */
-
-static void mlt_multitrack_listener( mlt_producer producer, mlt_multitrack this )
-{
- mlt_multitrack_refresh( this );
-}
-
-/** Connect a producer to a given track.
- *
- * Note that any producer can be connected here, but see special case treatment
- * of playlist in clip point determination below.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \param producer the producer to connect to the multitrack producer
- * \param track the 0-based index of the track on which to connect the multitrack
- * \return true on error
- */
-
-int mlt_multitrack_connect( mlt_multitrack this, mlt_producer producer, int track )
-{
- // Connect to the producer to ourselves at the specified track
- int result = mlt_service_connect_producer( MLT_MULTITRACK_SERVICE( this ), MLT_PRODUCER_SERVICE( producer ), track );
-
- if ( result == 0 )
- {
- // Resize the producer list if need be
- if ( track >= this->size )
- {
- int i;
- this->list = realloc( this->list, ( track + 10 ) * sizeof( mlt_track ) );
- for ( i = this->size; i < track + 10; i ++ )
- this->list[ i ] = NULL;
- this->size = track + 10;
- }
-
- if ( this->list[ track ] != NULL )
- {
- mlt_event_close( this->list[ track ]->event );
- mlt_producer_close( this->list[ track ]->producer );
- }
- else
- {
- this->list[ track ] = malloc( sizeof( struct mlt_track_s ) );
- }
-
- // Assign the track in our list here
- this->list[ track ]->producer = producer;
- this->list[ track ]->event = mlt_events_listen( MLT_PRODUCER_PROPERTIES( producer ), this,
- "producer-changed", ( mlt_listener )mlt_multitrack_listener );
- mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( producer ) );
- mlt_event_inc_ref( this->list[ track ]->event );
-
- // Increment the track count if need be
- if ( track >= this->count )
- this->count = track + 1;
-
- // Refresh our stats
- mlt_multitrack_refresh( this );
- }
-
- return result;
-}
-
-/** Get the number of tracks.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \return the number of tracks
- */
-
-int mlt_multitrack_count( mlt_multitrack this )
-{
- return this->count;
-}
-
-/** Get an individual track as a producer.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \param track the 0-based index of the producer to get
- * \return the producer or NULL if not valid
- */
-
-mlt_producer mlt_multitrack_track( mlt_multitrack this, int track )
-{
- mlt_producer producer = NULL;
-
- if ( this->list != NULL && track < this->count )
- producer = this->list[ track ]->producer;
-
- return producer;
-}
-
-/** Position comparison function for sorting.
- *
- * \private \memberof mlt_multitrack_s
- * \param p1 a position
- * \param p2 another position
- * \return <0 if \p p1 is less than \p p2, 0 if equal, >0 if greater
- */
-
-static int position_compare( const void *p1, const void *p2 )
-{
- return *( const mlt_position * )p1 - *( const mlt_position * )p2;
-}
-
-/** Add a position to a set.
- *
- * \private \memberof mlt_multitrack_s
- * \param array an array of positions (the set)
- * \param size the current number of positions in the array (not the capacity of the array)
- * \param position the position to add
- * \return the new size of the array
- */
-
-static int add_unique( mlt_position *array, int size, mlt_position position )
-{
- int i = 0;
- for ( i = 0; i < size; i ++ )
- if ( array[ i ] == position )
- break;
- if ( i == size )
- array[ size ++ ] = position;
- return size;
-}
-
-/** Determine the clip point.
- *
- * <pre>
- * Special case here: a 'producer' has no concept of multiple clips - only the
- * playlist and multitrack producers have clip functionality. Further to that a
- * multitrack determines clip information from any connected tracks that happen
- * to be playlists.
- *
- * Additionally, it must locate clips in the correct order, for example, consider
- * the following track arrangement:
- *
- * playlist1 |0.0 |b0.0 |0.1 |0.1 |0.2 |
- * playlist2 |b1.0 |1.0 |b1.1 |1.1 |
- *
- * Note - b clips represent blanks. They are also reported as clip positions.
- *
- * When extracting clip positions from these playlists, we should get a sequence of:
- *
- * 0.0, 1.0, b0.0, 0.1, b1.1, 1.1, 0.1, 0.2, [out of playlist2], [out of playlist1]
- * </pre>
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- * \param whence from where to extract
- * \param index the 0-based index of which clip to extract
- * \return the position of clip \p index relative to \p whence
- */
-
-mlt_position mlt_multitrack_clip( mlt_multitrack this, mlt_whence whence, int index )
-{
- mlt_position position = 0;
- int i = 0;
- int j = 0;
- mlt_position *map = malloc( 1000 * sizeof( mlt_position ) );
- int count = 0;
-
- for ( i = 0; i < this->count; i ++ )
- {
- // Get the producer for this track
- mlt_producer producer = this->list[ i ]->producer;
-
- // If it's assigned and not a hidden track
- if ( producer != NULL )
- {
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Determine if it's a playlist
- mlt_playlist playlist = mlt_properties_get_data( properties, "playlist", NULL );
-
- // Special case consideration of playlists
- if ( playlist != NULL )
- {
- for ( j = 0; j < mlt_playlist_count( playlist ); j ++ )
- count = add_unique( map, count, mlt_playlist_clip( playlist, mlt_whence_relative_start, j ) );
- count = add_unique( map, count, mlt_producer_get_out( producer ) + 1 );
- }
- else
- {
- count = add_unique( map, count, 0 );
- count = add_unique( map, count, mlt_producer_get_out( producer ) + 1 );
- }
- }
- }
-
- // Now sort the map
- qsort( map, count, sizeof( mlt_position ), position_compare );
-
- // Now locate the requested index
- switch( whence )
- {
- case mlt_whence_relative_start:
- if ( index < count )
- position = map[ index ];
- else
- position = map[ count - 1 ];
- break;
-
- case mlt_whence_relative_current:
- position = mlt_producer_position( MLT_MULTITRACK_PRODUCER( this ) );
- for ( i = 0; i < count - 2; i ++ )
- if ( position >= map[ i ] && position < map[ i + 1 ] )
- break;
- index += i;
- if ( index >= 0 && index < count )
- position = map[ index ];
- else if ( index < 0 )
- position = map[ 0 ];
- else
- position = map[ count - 1 ];
- break;
-
- case mlt_whence_relative_end:
- if ( index < count )
- position = map[ count - index - 1 ];
- else
- position = map[ 0 ];
- break;
- }
-
- // Free the map
- free( map );
-
- return position;
-}
-
-/** Get frame method.
- *
- * <pre>
- * Special case here: The multitrack must be used in a conjunction with a downstream
- * tractor-type service, ie:
- *
- * Producer1 \
- * Producer2 - multitrack - { filters/transitions } - tractor - consumer
- * Producer3 /
- *
- * The get_frame of a tractor pulls frames from it's connected service on all tracks and
- * will terminate as soon as it receives a test card with a last_track property. The
- * important case here is that the mulitrack does not move to the next frame until all
- * tracks have been pulled.
- *
- * Reasoning: In order to seek on a network such as above, the multitrack needs to ensure
- * that all producers are positioned on the same frame. It uses the 'last track' logic
- * to determine when to move to the next frame.
- *
- * Flaw: if a transition is configured to read from a b-track which happens to trigger
- * the last frame logic (ie: it's configured incorrectly), then things are going to go
- * out of sync.
- *
- * See playlist logic too.
- * </pre>
- *
- * \private \memberof mlt_multitrack_s
- * \param parent the producer interface to a mulitrack
- * \param[out] frame a frame by reference
- * \param index the 0-based track index
- * \return true if there was an error
- */
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index )
-{
- // Get the mutiltrack object
- mlt_multitrack this = parent->child;
-
- // Check if we have a track for this index
- if ( index < this->count && this->list[ index ] != NULL )
- {
- // Get the producer for this track
- mlt_producer producer = this->list[ index ]->producer;
-
- // Get the track hide property
- int hide = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) ), "hide" );
-
- // Obtain the current position
- mlt_position position = mlt_producer_frame( parent );
-
- // Get the parent properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( parent );
-
- // Get the speed
- double speed = mlt_properties_get_double( producer_properties, "_speed" );
-
- // Make sure we're at the same point
- mlt_producer_seek( producer, position );
-
- // Get the frame from the producer
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), frame, 0 );
-
- // Indicate speed of this producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
- mlt_properties_set_double( properties, "_speed", speed );
- mlt_properties_set_position( properties, "_position", position );
- mlt_properties_set_int( properties, "hide", hide );
- }
- else
- {
- // Generate a test frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );
-
- // Update position on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( parent ) );
-
- // Move on to the next frame
- if ( index >= this->count )
- {
- // Let tractor know if we've reached the end
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "last_track", 1 );
-
- // Move to the next frame
- mlt_producer_prepare_next( parent );
- }
- }
-
- return 0;
-}
-
-/** Close this instance and free its resources.
- *
- * \public \memberof mlt_multitrack_s
- * \param this a multitrack
- */
-
-void mlt_multitrack_close( mlt_multitrack this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_MULTITRACK_PROPERTIES( this ) ) <= 0 )
- {
- int i = 0;
- for ( i = 0; i < this->count; i ++ )
- {
- if ( this->list[ i ] != NULL )
- {
- mlt_event_close( this->list[ i ]->event );
- mlt_producer_close( this->list[ i ]->producer );
- free( this->list[ i ] );
- }
- }
-
- // Close the producer
- this->parent.close = NULL;
- mlt_producer_close( &this->parent );
-
- // Free the list
- free( this->list );
-
- // Free the object
- free( this );
- }
-}
+++ /dev/null
-/**
- * \file mlt_multitrack.h
- * \brief multitrack service class
- * \see mlt_multitrack_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_MULITRACK_H_
-#define _MLT_MULITRACK_H_
-
-#include "mlt_producer.h"
-
-/** \brief Track class used by mlt_multitrack_s
- */
-
-struct mlt_track_s
-{
- mlt_producer producer;
- mlt_event event;
-};
-
-typedef struct mlt_track_s *mlt_track;
-
-/** \brief Multitrack class
- *
- * A multitrack is a parallel container of producers that acts a single producer.
- *
- * \extends mlt_producer_s
- * \properties \em log_id not currently used, but sets it to "mulitrack"
- */
-
-struct mlt_multitrack_s
-{
- /** We're extending producer here */
- struct mlt_producer_s parent;
- mlt_track *list;
- int size;
- int count;
-};
-
-#define MLT_MULTITRACK_PRODUCER( multitrack ) ( &( multitrack )->parent )
-#define MLT_MULTITRACK_SERVICE( multitrack ) MLT_PRODUCER_SERVICE( MLT_MULTITRACK_PRODUCER( multitrack ) )
-#define MLT_MULTITRACK_PROPERTIES( multitrack ) MLT_SERVICE_PROPERTIES( MLT_MULTITRACK_SERVICE( multitrack ) )
-
-extern mlt_multitrack mlt_multitrack_init( );
-extern mlt_producer mlt_multitrack_producer( mlt_multitrack self );
-extern mlt_service mlt_multitrack_service( mlt_multitrack self );
-extern mlt_properties mlt_multitrack_properties( mlt_multitrack self );
-extern int mlt_multitrack_connect( mlt_multitrack self, mlt_producer producer, int track );
-extern mlt_position mlt_multitrack_clip( mlt_multitrack self, mlt_whence whence, int index );
-extern void mlt_multitrack_close( mlt_multitrack self );
-extern int mlt_multitrack_count( mlt_multitrack self );
-extern void mlt_multitrack_refresh( mlt_multitrack self );
-extern mlt_producer mlt_multitrack_track( mlt_multitrack self, int track );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_parser.c
- * \brief service parsing functionality
- * \see mlt_parser_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt.h"
-#include <stdlib.h>
-
-static int on_invalid( mlt_parser this, mlt_service object )
-{
- return 0;
-}
-
-static int on_unknown( mlt_parser this, mlt_service object )
-{
- return 0;
-}
-
-static int on_start_producer( mlt_parser this, mlt_producer object )
-{
- return 0;
-}
-
-static int on_end_producer( mlt_parser this, mlt_producer object )
-{
- return 0;
-}
-
-static int on_start_playlist( mlt_parser this, mlt_playlist object )
-{
- return 0;
-}
-
-static int on_end_playlist( mlt_parser this, mlt_playlist object )
-{
- return 0;
-}
-
-static int on_start_tractor( mlt_parser this, mlt_tractor object )
-{
- return 0;
-}
-
-static int on_end_tractor( mlt_parser this, mlt_tractor object )
-{
- return 0;
-}
-
-static int on_start_multitrack( mlt_parser this, mlt_multitrack object )
-{
- return 0;
-}
-
-static int on_end_multitrack( mlt_parser this, mlt_multitrack object )
-{
- return 0;
-}
-
-static int on_start_track( mlt_parser this )
-{
- return 0;
-}
-
-static int on_end_track( mlt_parser this )
-{
- return 0;
-}
-
-static int on_start_filter( mlt_parser this, mlt_filter object )
-{
- return 0;
-}
-
-static int on_end_filter( mlt_parser this, mlt_filter object )
-{
- return 0;
-}
-
-static int on_start_transition( mlt_parser this, mlt_transition object )
-{
- return 0;
-}
-
-static int on_end_transition( mlt_parser this, mlt_transition object )
-{
- return 0;
-}
-
-mlt_parser mlt_parser_new( )
-{
- mlt_parser this = calloc( 1, sizeof( struct mlt_parser_s ) );
- if ( this != NULL && mlt_properties_init( &this->parent, this ) == 0 )
- {
- this->on_invalid = on_invalid;
- this->on_unknown = on_unknown;
- this->on_start_producer = on_start_producer;
- this->on_end_producer = on_end_producer;
- this->on_start_playlist = on_start_playlist;
- this->on_end_playlist = on_end_playlist;
- this->on_start_tractor = on_start_tractor;
- this->on_end_tractor = on_end_tractor;
- this->on_start_multitrack = on_start_multitrack;
- this->on_end_multitrack = on_end_multitrack;
- this->on_start_track = on_start_track;
- this->on_end_track = on_end_track;
- this->on_start_filter = on_start_filter;
- this->on_end_filter = on_end_filter;
- this->on_start_transition = on_start_transition;
- this->on_end_transition = on_end_transition;
- }
- return this;
-}
-
-mlt_properties mlt_parser_properties( mlt_parser this )
-{
- return &this->parent;
-}
-
-int mlt_parser_start( mlt_parser this, mlt_service object )
-{
- int error = 0;
- mlt_service_type type = mlt_service_identify( object );
- switch( type )
- {
- case invalid_type:
- error = this->on_invalid( this, object );
- break;
- case unknown_type:
- error = this->on_unknown( this, object );
- break;
- case producer_type:
- if ( mlt_producer_is_cut( ( mlt_producer )object ) )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_cut_parent( ( mlt_producer )object ) );
- error = this->on_start_producer( this, ( mlt_producer )object );
- if ( error == 0 )
- {
- int i = 0;
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_producer( this, ( mlt_producer )object );
- break;
- case playlist_type:
- error = this->on_start_playlist( this, ( mlt_playlist )object );
- if ( error == 0 )
- {
- int i = 0;
- while ( error == 0 && i < mlt_playlist_count( ( mlt_playlist )object ) )
- mlt_parser_start( this, ( mlt_service )mlt_playlist_get_clip( ( mlt_playlist )object, i ++ ) );
- i = 0;
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_playlist( this, ( mlt_playlist )object );
- break;
- case tractor_type:
- error = this->on_start_tractor( this, ( mlt_tractor )object );
- if ( error == 0 )
- {
- int i = 0;
- mlt_service next = mlt_service_producer( object );
- mlt_parser_start( this, ( mlt_service )mlt_tractor_multitrack( ( mlt_tractor )object ) );
- while ( next != ( mlt_service )mlt_tractor_multitrack( ( mlt_tractor )object ) )
- {
- mlt_parser_start( this, next );
- next = mlt_service_producer( next );
- }
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_tractor( this, ( mlt_tractor )object );
- break;
- case multitrack_type:
- error = this->on_start_multitrack( this, ( mlt_multitrack )object );
- if ( error == 0 )
- {
- int i = 0;
- while ( i < mlt_multitrack_count( ( mlt_multitrack )object ) )
- {
- this->on_start_track( this );
- mlt_parser_start( this, ( mlt_service )mlt_multitrack_track( ( mlt_multitrack )object , i ++ ) );
- this->on_end_track( this );
- }
- i = 0;
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_multitrack( this, ( mlt_multitrack )object );
- break;
- case filter_type:
- error = this->on_start_filter( this, ( mlt_filter )object );
- if ( error == 0 )
- {
- int i = 0;
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_filter( this, ( mlt_filter )object );
- break;
- case transition_type:
- error = this->on_start_transition( this, ( mlt_transition )object );
- if ( error == 0 )
- {
- int i = 0;
- while ( error == 0 && mlt_producer_filter( ( mlt_producer )object, i ) != NULL )
- error = mlt_parser_start( this, ( mlt_service )mlt_producer_filter( ( mlt_producer )object, i ++ ) );
- }
- error = this->on_end_transition( this, ( mlt_transition )object );
- break;
- case field_type:
- break;
- case consumer_type:
- break;
- }
- return error;
-}
-
-void mlt_parser_close( mlt_parser this )
-{
- if ( this != NULL )
- {
- mlt_properties_close( &this->parent );
- free( this );
- }
-}
-
-
+++ /dev/null
-/**
- * \file mlt_parser.h
- * \brief service parsing functionality
- * \see mlt_parser_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PARSER_H_
-#define _MLT_PARSER_H_
-
-#include "mlt_types.h"
-
-/** \brief Parser class
- *
- * \extends mlt_properties_s
- */
-
-struct mlt_parser_s
-{
- struct mlt_properties_s parent;
- int ( *on_invalid )( mlt_parser self, mlt_service object );
- int ( *on_unknown )( mlt_parser self, mlt_service object );
- int ( *on_start_producer )( mlt_parser self, mlt_producer object );
- int ( *on_end_producer )( mlt_parser self, mlt_producer object );
- int ( *on_start_playlist )( mlt_parser self, mlt_playlist object );
- int ( *on_end_playlist )( mlt_parser self, mlt_playlist object );
- int ( *on_start_tractor )( mlt_parser self, mlt_tractor object );
- int ( *on_end_tractor )( mlt_parser self, mlt_tractor object );
- int ( *on_start_multitrack )( mlt_parser self, mlt_multitrack object );
- int ( *on_end_multitrack )( mlt_parser self, mlt_multitrack object );
- int ( *on_start_track )( mlt_parser self );
- int ( *on_end_track )( mlt_parser self );
- int ( *on_start_filter )( mlt_parser self, mlt_filter object );
- int ( *on_end_filter )( mlt_parser self, mlt_filter object );
- int ( *on_start_transition )( mlt_parser self, mlt_transition object );
- int ( *on_end_transition )( mlt_parser self, mlt_transition object );
-};
-
-extern mlt_parser mlt_parser_new( );
-extern mlt_properties mlt_parser_properties( mlt_parser self );
-extern int mlt_parser_start( mlt_parser self, mlt_service object );
-extern void mlt_parser_close( mlt_parser self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_playlist.c
- * \brief playlist service class
- * \see mlt_playlist_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_playlist.h"
-#include "mlt_tractor.h"
-#include "mlt_multitrack.h"
-#include "mlt_field.h"
-#include "mlt_frame.h"
-#include "mlt_transition.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** \brief Virtual playlist entry used by mlt_playlist_s
-*/
-
-struct playlist_entry_s
-{
- mlt_producer producer;
- mlt_position frame_in;
- mlt_position frame_out;
- mlt_position frame_count;
- int repeat;
- mlt_position producer_length;
- mlt_event event;
- int preservation_hack;
-};
-
-/* Forward declarations
-*/
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
-static int mlt_playlist_unmix( mlt_playlist this, int clip );
-static int mlt_playlist_resize_mix( mlt_playlist this, int clip, int in, int out );
-
-/** Construct a playlist.
- *
- * Sets the resource property to "<playlist>".
- * Set the mlt_type to property to "mlt_producer".
- * \public \memberof mlt_playlist_s
- * \return a new playlist
- */
-
-mlt_playlist mlt_playlist_init( )
-{
- mlt_playlist this = calloc( sizeof( struct mlt_playlist_s ), 1 );
- if ( this != NULL )
- {
- mlt_producer producer = &this->parent;
-
- // Construct the producer
- mlt_producer_init( producer, this );
-
- // Override the producer get_frame
- producer->get_frame = producer_get_frame;
-
- // Define the destructor
- producer->close = ( mlt_destructor )mlt_playlist_close;
- producer->close_object = this;
-
- // Initialise blank
- mlt_producer_init( &this->blank, NULL );
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( &this->blank ), "mlt_service", "blank" );
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( &this->blank ), "resource", "blank" );
-
- // Indicate that this producer is a playlist
- mlt_properties_set_data( MLT_PLAYLIST_PROPERTIES( this ), "playlist", this, 0, NULL, NULL );
-
- // Specify the eof condition
- mlt_properties_set( MLT_PLAYLIST_PROPERTIES( this ), "eof", "pause" );
- mlt_properties_set( MLT_PLAYLIST_PROPERTIES( this ), "resource", "<playlist>" );
- mlt_properties_set( MLT_PLAYLIST_PROPERTIES( this ), "mlt_type", "mlt_producer" );
- mlt_properties_set_position( MLT_PLAYLIST_PROPERTIES( this ), "in", 0 );
- mlt_properties_set_position( MLT_PLAYLIST_PROPERTIES( this ), "out", -1 );
- mlt_properties_set_position( MLT_PLAYLIST_PROPERTIES( this ), "length", 0 );
-
- this->size = 10;
- this->list = malloc( this->size * sizeof( playlist_entry * ) );
- }
-
- return this;
-}
-
-/** Get the producer associated to this playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the producer interface
- * \see MLT_PLAYLIST_PRODUCER
- */
-
-mlt_producer mlt_playlist_producer( mlt_playlist this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the service associated to this playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the service interface
- * \see MLT_PLAYLIST_SERVICE
- */
-
-mlt_service mlt_playlist_service( mlt_playlist this )
-{
- return MLT_PRODUCER_SERVICE( &this->parent );
-}
-
-/** Get the properties associated to this playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the playlist's properties list
- * \see MLT_PLAYLIST_PROPERTIES
- */
-
-mlt_properties mlt_playlist_properties( mlt_playlist this )
-{
- return MLT_PRODUCER_PROPERTIES( &this->parent );
-}
-
-/** Refresh the playlist after a clip has been changed.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \return false
- */
-
-static int mlt_playlist_virtual_refresh( mlt_playlist this )
-{
- // Obtain the properties
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- int i = 0;
- mlt_position frame_count = 0;
-
- for ( i = 0; i < this->count; i ++ )
- {
- // Get the producer
- mlt_producer producer = this->list[ i ]->producer;
- if ( producer )
- {
- int current_length = mlt_producer_get_out( producer ) - mlt_producer_get_in( producer ) + 1;
-
- // Check if the length of the producer has changed
- if ( this->list[ i ]->frame_in != mlt_producer_get_in( producer ) ||
- this->list[ i ]->frame_out != mlt_producer_get_out( producer ) )
- {
- // This clip should be removed...
- if ( current_length < 1 )
- {
- this->list[ i ]->frame_in = 0;
- this->list[ i ]->frame_out = -1;
- this->list[ i ]->frame_count = 0;
- }
- else
- {
- this->list[ i ]->frame_in = mlt_producer_get_in( producer );
- this->list[ i ]->frame_out = mlt_producer_get_out( producer );
- this->list[ i ]->frame_count = current_length;
- }
-
- // Update the producer_length
- this->list[ i ]->producer_length = current_length;
- }
- }
-
- // Calculate the frame_count
- this->list[ i ]->frame_count = ( this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1 ) * this->list[ i ]->repeat;
-
- // Update the frame_count for this clip
- frame_count += this->list[ i ]->frame_count;
- }
-
- // Refresh all properties
- mlt_events_block( properties, properties );
- mlt_properties_set_position( properties, "length", frame_count );
- mlt_events_unblock( properties, properties );
- mlt_properties_set_position( properties, "out", frame_count - 1 );
-
- return 0;
-}
-
-/** Listener for producers on the playlist.
- *
- * Refreshes the playlist whenever an entry receives producer-changed.
- * \private \memberof mlt_playlist_s
- * \param producer a producer
- * \param this a playlist
- */
-
-static void mlt_playlist_listener( mlt_producer producer, mlt_playlist this )
-{
- mlt_playlist_virtual_refresh( this );
-}
-
-/** Append to the virtual playlist.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \param source a producer
- * \param in the producer's starting time
- * \param out the producer's ending time
- * \return true if there was an error
- */
-
-static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer source, mlt_position in, mlt_position out )
-{
- mlt_producer producer = NULL;
- mlt_properties properties = NULL;
- mlt_properties parent = NULL;
-
- // If we have a cut, then use the in/out points from the cut
- if ( mlt_producer_is_blank( source ) )
- {
- // Make sure the blank is long enough to accomodate the length specified
- if ( out - in + 1 > mlt_producer_get_length( &this->blank ) )
- {
- mlt_properties blank_props = MLT_PRODUCER_PROPERTIES( &this->blank );
- mlt_events_block( blank_props, blank_props );
- mlt_producer_set_in_and_out( &this->blank, in, out );
- mlt_events_unblock( blank_props, blank_props );
- }
-
- // Now make sure the cut comes from this this->blank
- if ( source == NULL )
- {
- producer = mlt_producer_cut( &this->blank, in, out );
- }
- else if ( !mlt_producer_is_cut( source ) || mlt_producer_cut_parent( source ) != &this->blank )
- {
- producer = mlt_producer_cut( &this->blank, in, out );
- }
- else
- {
- producer = source;
- mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( producer ) );
- }
-
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- else if ( mlt_producer_is_cut( source ) )
- {
- producer = source;
- if ( in == -1 )
- in = mlt_producer_get_in( producer );
- if ( out == -1 || out > mlt_producer_get_out( producer ) )
- out = mlt_producer_get_out( producer );
- properties = MLT_PRODUCER_PROPERTIES( producer );
- mlt_properties_inc_ref( properties );
- }
- else
- {
- producer = mlt_producer_cut( source, in, out );
- if ( in == -1 || in < mlt_producer_get_in( producer ) )
- in = mlt_producer_get_in( producer );
- if ( out == -1 || out > mlt_producer_get_out( producer ) )
- out = mlt_producer_get_out( producer );
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
-
- // Fetch the cuts parent properties
- parent = MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( producer ) );
-
- // Remove fezzik normalisers for fx cuts
- if ( mlt_properties_get_int( parent, "meta.fx_cut" ) )
- {
- mlt_service service = MLT_PRODUCER_SERVICE( mlt_producer_cut_parent( producer ) );
- mlt_filter filter = mlt_service_filter( service, 0 );
- while ( filter != NULL && mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "_fezzik" ) )
- {
- mlt_service_detach( service, filter );
- filter = mlt_service_filter( service, 0 );
- }
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( producer ), "meta.fx_cut", 1 );
- }
-
- // Check that we have room
- if ( this->count >= this->size )
- {
- int i;
- this->list = realloc( this->list, ( this->size + 10 ) * sizeof( playlist_entry * ) );
- for ( i = this->size; i < this->size + 10; i ++ ) this->list[ i ] = NULL;
- this->size += 10;
- }
-
- // Create the entry
- this->list[ this->count ] = calloc( sizeof( playlist_entry ), 1 );
- if ( this->list[ this->count ] != NULL )
- {
- this->list[ this->count ]->producer = producer;
- this->list[ this->count ]->frame_in = in;
- this->list[ this->count ]->frame_out = out;
- this->list[ this->count ]->frame_count = out - in + 1;
- this->list[ this->count ]->repeat = 1;
- this->list[ this->count ]->producer_length = mlt_producer_get_out( producer ) - mlt_producer_get_in( producer ) + 1;
- this->list[ this->count ]->event = mlt_events_listen( parent, this, "producer-changed", ( mlt_listener )mlt_playlist_listener );
- mlt_event_inc_ref( this->list[ this->count ]->event );
- mlt_properties_set( properties, "eof", "pause" );
- mlt_producer_set_speed( producer, 0 );
- this->count ++;
- }
-
- return mlt_playlist_virtual_refresh( this );
-}
-
-/** Locate a producer by index.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \param[in, out] position the time at which to locate the producer, returns the time relative to the producer's starting point
- * \param[out] clip the index of the playlist entry
- * \param[out] total the duration of the playlist up to and including this producer
- * \return a producer or NULL if not found
- */
-
-static mlt_producer mlt_playlist_locate( mlt_playlist this, mlt_position *position, int *clip, int *total )
-{
- // Default producer to NULL
- mlt_producer producer = NULL;
-
- // Loop for each producer until found
- for ( *clip = 0; *clip < this->count; *clip += 1 )
- {
- // Increment the total
- *total += this->list[ *clip ]->frame_count;
-
- // Check if the position indicates that we have found the clip
- // Note that 0 length clips get skipped automatically
- if ( *position < this->list[ *clip ]->frame_count )
- {
- // Found it, now break
- producer = this->list[ *clip ]->producer;
- break;
- }
- else
- {
- // Decrement position by length of this entry
- *position -= this->list[ *clip ]->frame_count;
- }
- }
-
- return producer;
-}
-
-/** Seek in the virtual playlist.
- *
- * This gets the producer at the current position and seeks on the producer
- * while doing repeat and end-of-file handling. This is also responsible for
- * closing producers previous to the preceding playlist if the autoclose
- * property is set.
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \param[out] progressive true if the producer should be displayed progressively
- * \return the service interface of the producer at the play head
- * \see producer_get_frame
- */
-
-static mlt_service mlt_playlist_virtual_seek( mlt_playlist this, int *progressive )
-{
- // Map playlist position to real producer in virtual playlist
- mlt_position position = mlt_producer_frame( &this->parent );
-
- // Keep the original position since we change it while iterating through the list
- mlt_position original = position;
-
- // Clip index and total
- int i = 0;
- int total = 0;
-
- // Locate the producer for the position
- mlt_producer producer = mlt_playlist_locate( this, &position, &i, &total );
-
- // Get the properties
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
-
- // Automatically close previous producers if requested
- if ( i > 1 // keep immediate previous in case app wants to get info about what just finished
- && position < 2 // tolerate off-by-one error on going to next clip
- && mlt_properties_get_int( properties, "autoclose" ) )
- {
- int j;
- // They might have jumped ahead!
- for ( j = 0; j < i - 1; j++ )
- {
- mlt_service_lock( MLT_PRODUCER_SERVICE( this->list[ j ]->producer ) );
- mlt_producer p = this->list[ j ]->producer;
- if ( p )
- {
- this->list[ j ]->producer = NULL;
- mlt_service_unlock( MLT_PRODUCER_SERVICE( p ) );
- mlt_producer_close( p );
- }
- // If p is null, the lock will not have been "taken"
- }
- }
-
- // Get the eof handling
- char *eof = mlt_properties_get( properties, "eof" );
-
- // Seek in real producer to relative position
- if ( producer != NULL )
- {
- int count = this->list[ i ]->frame_count / this->list[ i ]->repeat;
- *progressive = count == 1;
- mlt_producer_seek( producer, (int)position % count );
- }
- else if ( !strcmp( eof, "pause" ) && total > 0 )
- {
- playlist_entry *entry = this->list[ this->count - 1 ];
- int count = entry->frame_count / entry->repeat;
- mlt_producer this_producer = MLT_PLAYLIST_PRODUCER( this );
- mlt_producer_seek( this_producer, original - 1 );
- producer = entry->producer;
- mlt_producer_seek( producer, (int)entry->frame_out % count );
- mlt_producer_set_speed( this_producer, 0 );
- mlt_producer_set_speed( producer, 0 );
- *progressive = count == 1;
- }
- else if ( !strcmp( eof, "loop" ) && total > 0 )
- {
- playlist_entry *entry = this->list[ 0 ];
- mlt_producer this_producer = MLT_PLAYLIST_PRODUCER( this );
- mlt_producer_seek( this_producer, 0 );
- producer = entry->producer;
- mlt_producer_seek( producer, 0 );
- }
- else
- {
- producer = &this->blank;
- }
-
- return MLT_PRODUCER_SERVICE( producer );
-}
-
-/** Invoked when a producer indicates that it has prematurely reached its end.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \return a producer
- * \see producer_get_frame
- */
-
-static mlt_producer mlt_playlist_virtual_set_out( mlt_playlist this )
-{
- // Default producer to blank
- mlt_producer producer = &this->blank;
-
- // Map playlist position to real producer in virtual playlist
- mlt_position position = mlt_producer_frame( &this->parent );
-
- // Loop through the virtual playlist
- int i = 0;
-
- for ( i = 0; i < this->count; i ++ )
- {
- if ( position < this->list[ i ]->frame_count )
- {
- // Found it, now break
- producer = this->list[ i ]->producer;
- break;
- }
- else
- {
- // Decrement position by length of this entry
- position -= this->list[ i ]->frame_count;
- }
- }
-
- // Seek in real producer to relative position
- if ( i < this->count && this->list[ i ]->frame_out != position )
- {
- // Update the frame_count for the changed clip (hmmm)
- this->list[ i ]->frame_out = position;
- this->list[ i ]->frame_count = this->list[ i ]->frame_out - this->list[ i ]->frame_in + 1;
-
- // Refresh the playlist
- mlt_playlist_virtual_refresh( this );
- }
-
- return producer;
-}
-
-/** Obtain the current clips index.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the index of the playlist entry at the current position
- */
-
-int mlt_playlist_current_clip( mlt_playlist this )
-{
- // Map playlist position to real producer in virtual playlist
- mlt_position position = mlt_producer_frame( &this->parent );
-
- // Loop through the virtual playlist
- int i = 0;
-
- for ( i = 0; i < this->count; i ++ )
- {
- if ( position < this->list[ i ]->frame_count )
- {
- // Found it, now break
- break;
- }
- else
- {
- // Decrement position by length of this entry
- position -= this->list[ i ]->frame_count;
- }
- }
-
- return i;
-}
-
-/** Obtain the current clips producer.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the producer at the current position
- */
-
-mlt_producer mlt_playlist_current( mlt_playlist this )
-{
- int i = mlt_playlist_current_clip( this );
- if ( i < this->count )
- return this->list[ i ]->producer;
- else
- return &this->blank;
-}
-
-/** Get the position which corresponds to the start of the next clip.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param whence the location from which to make the index relative:
- * start of playlist, end of playlist, or current position
- * \param index the playlist entry index relative to whence
- * \return the time at which the referenced clip starts
- */
-
-mlt_position mlt_playlist_clip( mlt_playlist this, mlt_whence whence, int index )
-{
- mlt_position position = 0;
- int absolute_clip = index;
- int i = 0;
-
- // Determine the absolute clip
- switch ( whence )
- {
- case mlt_whence_relative_start:
- absolute_clip = index;
- break;
-
- case mlt_whence_relative_current:
- absolute_clip = mlt_playlist_current_clip( this ) + index;
- break;
-
- case mlt_whence_relative_end:
- absolute_clip = this->count - index;
- break;
- }
-
- // Check that we're in a valid range
- if ( absolute_clip < 0 )
- absolute_clip = 0;
- else if ( absolute_clip > this->count )
- absolute_clip = this->count;
-
- // Now determine the position
- for ( i = 0; i < absolute_clip; i ++ )
- position += this->list[ i ]->frame_count;
-
- return position;
-}
-
-/** Get all the info about the clip specified.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param info a clip info struct
- * \param index a playlist entry index
- * \return true if there was an error
- */
-
-int mlt_playlist_get_clip_info( mlt_playlist this, mlt_playlist_clip_info *info, int index )
-{
- int error = index < 0 || index >= this->count || this->list[ index ]->producer == NULL;
- memset( info, 0, sizeof( mlt_playlist_clip_info ) );
- if ( !error )
- {
- mlt_producer producer = mlt_producer_cut_parent( this->list[ index ]->producer );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- info->clip = index;
- info->producer = producer;
- info->cut = this->list[ index ]->producer;
- info->start = mlt_playlist_clip( this, mlt_whence_relative_start, index );
- info->resource = mlt_properties_get( properties, "resource" );
- info->frame_in = this->list[ index ]->frame_in;
- info->frame_out = this->list[ index ]->frame_out;
- info->frame_count = this->list[ index ]->frame_count;
- info->repeat = this->list[ index ]->repeat;
- info->length = mlt_producer_get_length( producer );
- info->fps = mlt_producer_get_fps( producer );
- }
-
- return error;
-}
-
-/** Get number of clips in the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return the number of playlist entries
- */
-
-int mlt_playlist_count( mlt_playlist this )
-{
- return this->count;
-}
-
-/** Clear the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \return true if there was an error
- */
-
-int mlt_playlist_clear( mlt_playlist this )
-{
- int i;
- for ( i = 0; i < this->count; i ++ )
- {
- mlt_event_close( this->list[ i ]->event );
- mlt_producer_close( this->list[ i ]->producer );
- }
- this->count = 0;
- return mlt_playlist_virtual_refresh( this );
-}
-
-/** Append a producer to the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param producer the producer to append
- * \return true if there was an error
- */
-
-int mlt_playlist_append( mlt_playlist this, mlt_producer producer )
-{
- // Append to virtual list
- return mlt_playlist_virtual_append( this, producer, 0, mlt_producer_get_playtime( producer ) - 1 );
-}
-
-/** Append a producer to the playlist with in/out points.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param producer the producer to append
- * \param in the starting point on the producer
- * \param out the ending point on the producer
- * \return true if there was an error
- */
-
-int mlt_playlist_append_io( mlt_playlist this, mlt_producer producer, mlt_position in, mlt_position out )
-{
- // Append to virtual list
- if ( in != -1 && out != -1 )
- return mlt_playlist_virtual_append( this, producer, in, out );
- else
- return mlt_playlist_append( this, producer );
-}
-
-/** Append a blank to the playlist of a given length.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param length the ending time of the blank entry, not its duration
- * \return true if there was an error
- */
-
-int mlt_playlist_blank( mlt_playlist this, mlt_position length )
-{
- // Append to the virtual list
- if (length >= 0)
- return mlt_playlist_virtual_append( this, &this->blank, 0, length );
- else
- return 1;
-}
-
-/** Insert a producer into the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param producer the producer to insert
- * \param where the producer's playlist entry index
- * \param in the starting point on the producer
- * \param out the ending point on the producer
- * \return true if there was an error
- */
-
-int mlt_playlist_insert( mlt_playlist this, mlt_producer producer, int where, mlt_position in, mlt_position out )
-{
- // Append to end
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_append_io( this, producer, in, out );
-
- // Move to the position specified
- mlt_playlist_move( this, this->count - 1, where );
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
-
- return mlt_playlist_virtual_refresh( this );
-}
-
-/** Remove an entry in the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param where the playlist entry index
- * \return true if there was an error
- */
-
-int mlt_playlist_remove( mlt_playlist this, int where )
-{
- int error = where < 0 || where >= this->count;
- if ( error == 0 && mlt_playlist_unmix( this, where ) != 0 )
- {
- // We need to know the current clip and the position within the playlist
- int current = mlt_playlist_current_clip( this );
- mlt_position position = mlt_producer_position( MLT_PLAYLIST_PRODUCER( this ) );
-
- // We need all the details about the clip we're removing
- mlt_playlist_clip_info where_info;
- playlist_entry *entry = this->list[ where ];
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( entry->producer );
-
- // Loop variable
- int i = 0;
-
- // Get the clip info
- mlt_playlist_get_clip_info( this, &where_info, where );
-
- // Make sure the clip to be removed is valid and correct if necessary
- if ( where < 0 )
- where = 0;
- if ( where >= this->count )
- where = this->count - 1;
-
- // Reorganise the list
- for ( i = where + 1; i < this->count; i ++ )
- this->list[ i - 1 ] = this->list[ i ];
- this->count --;
-
- if ( entry->preservation_hack == 0 )
- {
- // Decouple from mix_in/out if necessary
- if ( mlt_properties_get_data( properties, "mix_in", NULL ) != NULL )
- {
- mlt_properties mix = mlt_properties_get_data( properties, "mix_in", NULL );
- mlt_properties_set_data( mix, "mix_out", NULL, 0, NULL, NULL );
- }
- if ( mlt_properties_get_data( properties, "mix_out", NULL ) != NULL )
- {
- mlt_properties mix = mlt_properties_get_data( properties, "mix_out", NULL );
- mlt_properties_set_data( mix, "mix_in", NULL, 0, NULL, NULL );
- }
-
- if ( mlt_properties_ref_count( MLT_PRODUCER_PROPERTIES( entry->producer ) ) == 1 )
- mlt_producer_clear( entry->producer );
- }
-
- // Close the producer associated to the clip info
- mlt_event_close( entry->event );
- mlt_producer_close( entry->producer );
-
- // Correct position
- if ( where == current )
- mlt_producer_seek( MLT_PLAYLIST_PRODUCER( this ), where_info.start );
- else if ( where < current && this->count > 0 )
- mlt_producer_seek( MLT_PLAYLIST_PRODUCER( this ), position - where_info.frame_count );
- else if ( this->count == 0 )
- mlt_producer_seek( MLT_PLAYLIST_PRODUCER( this ), 0 );
-
- // Free the entry
- free( entry );
-
- // Refresh the playlist
- mlt_playlist_virtual_refresh( this );
- }
-
- return error;
-}
-
-/** Move an entry in the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param src an entry index
- * \param dest an entry index
- * \return false
- */
-
-int mlt_playlist_move( mlt_playlist this, int src, int dest )
-{
- int i;
-
- /* We need to ensure that the requested indexes are valid and correct it as necessary */
- if ( src < 0 )
- src = 0;
- if ( src >= this->count )
- src = this->count - 1;
-
- if ( dest < 0 )
- dest = 0;
- if ( dest >= this->count )
- dest = this->count - 1;
-
- if ( src != dest && this->count > 1 )
- {
- int current = mlt_playlist_current_clip( this );
- mlt_position position = mlt_producer_position( MLT_PLAYLIST_PRODUCER( this ) );
- playlist_entry *src_entry = NULL;
-
- // We need all the details about the current clip
- mlt_playlist_clip_info current_info;
-
- mlt_playlist_get_clip_info( this, ¤t_info, current );
- position -= current_info.start;
-
- if ( current == src )
- current = dest;
- else if ( current > src && current < dest )
- current ++;
- else if ( current == dest )
- current = src;
-
- src_entry = this->list[ src ];
- if ( src > dest )
- {
- for ( i = src; i > dest; i -- )
- this->list[ i ] = this->list[ i - 1 ];
- }
- else
- {
- for ( i = src; i < dest; i ++ )
- this->list[ i ] = this->list[ i + 1 ];
- }
- this->list[ dest ] = src_entry;
-
- mlt_playlist_get_clip_info( this, ¤t_info, current );
- mlt_producer_seek( MLT_PLAYLIST_PRODUCER( this ), current_info.start + position );
- mlt_playlist_virtual_refresh( this );
- }
-
- return 0;
-}
-
-/** Repeat the specified clip n times.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip a playlist entry index
- * \param repeat the number of times to repeat the clip
- * \return true if there was an error
- */
-
-int mlt_playlist_repeat_clip( mlt_playlist this, int clip, int repeat )
-{
- int error = repeat < 1 || clip < 0 || clip >= this->count;
- if ( error == 0 )
- {
- playlist_entry *entry = this->list[ clip ];
- entry->repeat = repeat;
- mlt_playlist_virtual_refresh( this );
- }
- return error;
-}
-
-/** Resize the specified clip.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param in the new starting time on the clip's producer
- * \param out the new ending time on the clip's producer
- * \return true if there was an error
- */
-
-int mlt_playlist_resize_clip( mlt_playlist this, int clip, mlt_position in, mlt_position out )
-{
- int error = clip < 0 || clip >= this->count;
- if ( error == 0 && mlt_playlist_resize_mix( this, clip, in, out ) != 0 )
- {
- playlist_entry *entry = this->list[ clip ];
- mlt_producer producer = entry->producer;
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
-
- mlt_events_block( properties, properties );
-
- if ( mlt_producer_is_blank( producer ) )
- {
- // Make sure the blank is long enough to accomodate the length specified
- if ( out - in + 1 > mlt_producer_get_length( &this->blank ) )
- {
- mlt_properties blank_props = MLT_PRODUCER_PROPERTIES( &this->blank );
- mlt_properties_set_int( blank_props, "length", out - in + 1 );
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( producer ), "length", out - in + 1 );
- mlt_producer_set_in_and_out( &this->blank, 0, out - in );
- }
- }
-
- if ( in <= -1 )
- in = 0;
- if ( out <= -1 || out >= mlt_producer_get_length( producer ) )
- out = mlt_producer_get_length( producer ) - 1;
-
- if ( out < in )
- {
- mlt_position t = in;
- in = out;
- out = t;
- }
-
- mlt_producer_set_in_and_out( producer, in, out );
- mlt_events_unblock( properties, properties );
- mlt_playlist_virtual_refresh( this );
- }
- return error;
-}
-
-/** Split a clip on the playlist at the given position.
- *
- * This splits after the specified frame.
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param position the time at which to split relative to the beginning of the clip or its end if negative
- * \return true if there was an error
- */
-
-int mlt_playlist_split( mlt_playlist this, int clip, mlt_position position )
-{
- int error = clip < 0 || clip >= this->count;
- if ( error == 0 )
- {
- playlist_entry *entry = this->list[ clip ];
- position = position < 0 ? entry->frame_count + position - 1 : position;
- if ( position >= 0 && position < entry->frame_count - 1 )
- {
- int in = entry->frame_in;
- int out = entry->frame_out;
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_resize_clip( this, clip, in, in + position );
- if ( !mlt_producer_is_blank( entry->producer ) )
- {
- int i = 0;
- mlt_properties entry_properties = MLT_PRODUCER_PROPERTIES( entry->producer );
- mlt_producer split = mlt_producer_cut( entry->producer, in + position + 1, out );
- mlt_properties split_properties = MLT_PRODUCER_PROPERTIES( split );
- mlt_playlist_insert( this, split, clip + 1, 0, -1 );
- for ( i = 0; i < mlt_properties_count( entry_properties ); i ++ )
- {
- char *name = mlt_properties_get_name( entry_properties, i );
- if ( name != NULL && !strncmp( name, "meta.", 5 ) )
- mlt_properties_set( split_properties, name, mlt_properties_get_value( entry_properties, i ) );
- }
- mlt_producer_close( split );
- }
- else
- {
- mlt_playlist_insert( this, &this->blank, clip + 1, 0, out - position - 1 );
- }
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_virtual_refresh( this );
- }
- else
- {
- error = 1;
- }
- }
- return error;
-}
-
-/** Split the playlist at the absolute position.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position the time at which to split relative to the beginning of the clip
- * \param left true to split before the frame starting at position
- * \return true if there was an error
- */
-
-int mlt_playlist_split_at( mlt_playlist this, mlt_position position, int left )
-{
- int result = this == NULL ? -1 : 0;
- if ( !result )
- {
- if ( position >= 0 && position < mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) ) )
- {
- int clip = mlt_playlist_get_clip_index_at( this, position );
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( this, &info, clip );
- if ( left && position != info.start )
- mlt_playlist_split( this, clip, position - info.start - 1 );
- else if ( !left )
- mlt_playlist_split( this, clip, position - info.start );
- result = position;
- }
- else if ( position <= 0 )
- {
- result = 0;
- }
- else
- {
- result = mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) );
- }
- }
- return result;
-}
-
-/** Join 1 or more consecutive clips.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the starting playlist entry index
- * \param count the number of entries to merge
- * \param merge ignored
- * \return true if there was an error
- */
-
-int mlt_playlist_join( mlt_playlist this, int clip, int count, int merge )
-{
- int error = clip < 0 || clip >= this->count;
- if ( error == 0 )
- {
- int i = clip;
- mlt_playlist new_clip = mlt_playlist_init( );
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
- if ( clip + count >= this->count )
- count = this->count - clip - 1;
- for ( i = 0; i <= count; i ++ )
- {
- playlist_entry *entry = this->list[ clip ];
- mlt_playlist_append( new_clip, entry->producer );
- mlt_playlist_repeat_clip( new_clip, i, entry->repeat );
- entry->preservation_hack = 1;
- mlt_playlist_remove( this, clip );
- }
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_insert( this, MLT_PLAYLIST_PRODUCER( new_clip ), clip, 0, -1 );
- mlt_playlist_close( new_clip );
- }
- return error;
-}
-
-/** Mix consecutive clips for a specified length and apply transition if specified.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param length the number of frames over which to create the mix
- * \param transition the transition to use for the mix
- * \return true if there was an error
- */
-
-int mlt_playlist_mix( mlt_playlist this, int clip, int length, mlt_transition transition )
-{
- int error = ( clip < 0 || clip + 1 >= this->count );
- if ( error == 0 )
- {
- playlist_entry *clip_a = this->list[ clip ];
- playlist_entry *clip_b = this->list[ clip + 1 ];
- mlt_producer track_a = NULL;
- mlt_producer track_b = NULL;
- mlt_tractor tractor = mlt_tractor_new( );
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
-
- // Check length is valid for both clips and resize if necessary.
- int max_size = clip_a->frame_count > clip_b->frame_count ? clip_a->frame_count : clip_b->frame_count;
- length = length > max_size ? max_size : length;
-
- // Create the a and b tracks/cuts if necessary - note that no cuts are required if the length matches
- if ( length != clip_a->frame_count )
- track_a = mlt_producer_cut( clip_a->producer, clip_a->frame_out - length + 1, clip_a->frame_out );
- else
- track_a = clip_a->producer;
-
- if ( length != clip_b->frame_count )
- track_b = mlt_producer_cut( clip_b->producer, clip_b->frame_in, clip_b->frame_in + length - 1 );
- else
- track_b = clip_b->producer;
-
- // Set the tracks on the tractor
- mlt_tractor_set_track( tractor, track_a, 0 );
- mlt_tractor_set_track( tractor, track_b, 1 );
-
- // Insert the mix object into the playlist
- mlt_playlist_insert( this, MLT_TRACTOR_PRODUCER( tractor ), clip + 1, -1, -1 );
- mlt_properties_set_data( MLT_TRACTOR_PROPERTIES( tractor ), "mlt_mix", tractor, 0, NULL, NULL );
-
- // Attach the transition
- if ( transition != NULL )
- {
- mlt_field field = mlt_tractor_field( tractor );
- mlt_field_plant_transition( field, transition, 0, 1 );
- mlt_transition_set_in_and_out( transition, 0, length - 1 );
- }
-
- // Close our references to the tracks if we created new cuts above (the tracks can still be used here)
- if ( track_a != clip_a->producer )
- mlt_producer_close( track_a );
- if ( track_b != clip_b->producer )
- mlt_producer_close( track_b );
-
- // Check if we have anything left on the right hand clip
- if ( track_b == clip_b->producer )
- {
- clip_b->preservation_hack = 1;
- mlt_playlist_remove( this, clip + 2 );
- }
- else if ( clip_b->frame_out - clip_b->frame_in > length )
- {
- mlt_playlist_resize_clip( this, clip + 2, clip_b->frame_in + length, clip_b->frame_out );
- mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( clip_b->producer ), "mix_in", tractor, 0, NULL, NULL );
- mlt_properties_set_data( MLT_TRACTOR_PROPERTIES( tractor ), "mix_out", clip_b->producer, 0, NULL, NULL );
- }
- else
- {
- mlt_producer_clear( clip_b->producer );
- mlt_playlist_remove( this, clip + 2 );
- }
-
- // Check if we have anything left on the left hand clip
- if ( track_a == clip_a->producer )
- {
- clip_a->preservation_hack = 1;
- mlt_playlist_remove( this, clip );
- }
- else if ( clip_a->frame_out - clip_a->frame_in > length )
- {
- mlt_playlist_resize_clip( this, clip, clip_a->frame_in, clip_a->frame_out - length );
- mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( clip_a->producer ), "mix_out", tractor, 0, NULL, NULL );
- mlt_properties_set_data( MLT_TRACTOR_PROPERTIES( tractor ), "mix_in", clip_a->producer, 0, NULL, NULL );
- }
- else
- {
- mlt_producer_clear( clip_a->producer );
- mlt_playlist_remove( this, clip );
- }
-
- // Unblock and force a fire off of change events to listeners
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_virtual_refresh( this );
- mlt_tractor_close( tractor );
- }
- return error;
-}
-
-/** Add a transition to an existing mix.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param transition a transition
- * \return true if there was an error
- */
-
-int mlt_playlist_mix_add( mlt_playlist this, int clip, mlt_transition transition )
-{
- mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) );
- mlt_properties properties = producer != NULL ? MLT_PRODUCER_PROPERTIES( producer ) : NULL;
- mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL;
- int error = transition == NULL || tractor == NULL;
- if ( error == 0 )
- {
- mlt_field field = mlt_tractor_field( tractor );
- mlt_field_plant_transition( field, transition, 0, 1 );
- mlt_transition_set_in_and_out( transition, 0, this->list[ clip ]->frame_count - 1 );
- }
- return error;
-}
-
-/** Return the clip at the clip index.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of a playlist entry
- * \return a producer or NULL if there was an error
- */
-
-mlt_producer mlt_playlist_get_clip( mlt_playlist this, int clip )
-{
- if ( clip >= 0 && clip < this->count )
- return this->list[ clip ]->producer;
- return NULL;
-}
-
-/** Return the clip at the specified position.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position a time relative to the beginning of the playlist
- * \return a producer or NULL if not found
- */
-
-mlt_producer mlt_playlist_get_clip_at( mlt_playlist this, mlt_position position )
-{
- int index = 0, total = 0;
- return mlt_playlist_locate( this, &position, &index, &total );
-}
-
-/** Return the clip index of the specified position.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position a time relative to the beginning of the playlist
- * \return the index of the playlist entry
- */
-
-int mlt_playlist_get_clip_index_at( mlt_playlist this, mlt_position position )
-{
- int index = 0, total = 0;
- mlt_playlist_locate( this, &position, &index, &total );
- return index;
-}
-
-/** Determine if the clip is a mix.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return true if the producer is a mix
- */
-
-int mlt_playlist_clip_is_mix( mlt_playlist this, int clip )
-{
- mlt_producer producer = mlt_producer_cut_parent( mlt_playlist_get_clip( this, clip ) );
- mlt_properties properties = producer != NULL ? MLT_PRODUCER_PROPERTIES( producer ) : NULL;
- mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL;
- return tractor != NULL;
-}
-
-/** Remove a mixed clip - ensure that the cuts included in the mix find their way
- * back correctly on to the playlist.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return true if there was an error
- */
-
-static int mlt_playlist_unmix( mlt_playlist this, int clip )
-{
- int error = ( clip < 0 || clip >= this->count );
-
- // Ensure that the clip request is actually a mix
- if ( error == 0 )
- {
- mlt_producer producer = mlt_producer_cut_parent( this->list[ clip ]->producer );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- error = mlt_properties_get_data( properties, "mlt_mix", NULL ) == NULL ||
- this->list[ clip ]->preservation_hack;
- }
-
- if ( error == 0 )
- {
- playlist_entry *mix = this->list[ clip ];
- mlt_tractor tractor = ( mlt_tractor )mlt_producer_cut_parent( mix->producer );
- mlt_properties properties = MLT_TRACTOR_PROPERTIES( tractor );
- mlt_producer clip_a = mlt_properties_get_data( properties, "mix_in", NULL );
- mlt_producer clip_b = mlt_properties_get_data( properties, "mix_out", NULL );
- int length = mlt_producer_get_playtime( MLT_TRACTOR_PRODUCER( tractor ) );
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
-
- if ( clip_a != NULL )
- {
- mlt_producer_set_in_and_out( clip_a, mlt_producer_get_in( clip_a ), mlt_producer_get_out( clip_a ) + length );
- }
- else
- {
- mlt_producer cut = mlt_tractor_get_track( tractor, 0 );
- mlt_playlist_insert( this, cut, clip, -1, -1 );
- clip ++;
- }
-
- if ( clip_b != NULL )
- {
- mlt_producer_set_in_and_out( clip_b, mlt_producer_get_in( clip_b ) - length, mlt_producer_get_out( clip_b ) );
- }
- else
- {
- mlt_producer cut = mlt_tractor_get_track( tractor, 1 );
- mlt_playlist_insert( this, cut, clip + 1, -1, -1 );
- }
-
- mlt_properties_set_data( properties, "mlt_mix", NULL, 0, NULL, NULL );
- mlt_playlist_remove( this, clip );
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_virtual_refresh( this );
- }
- return error;
-}
-
-/** Resize a mix clip.
- *
- * \private \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param in the new starting point
- * \param out the new ending point
- * \return true if there was an error
- */
-
-static int mlt_playlist_resize_mix( mlt_playlist this, int clip, int in, int out )
-{
- int error = ( clip < 0 || clip >= this->count );
-
- // Ensure that the clip request is actually a mix
- if ( error == 0 )
- {
- mlt_producer producer = mlt_producer_cut_parent( this->list[ clip ]->producer );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- error = mlt_properties_get_data( properties, "mlt_mix", NULL ) == NULL;
- }
-
- if ( error == 0 )
- {
- playlist_entry *mix = this->list[ clip ];
- mlt_tractor tractor = ( mlt_tractor )mlt_producer_cut_parent( mix->producer );
- mlt_properties properties = MLT_TRACTOR_PROPERTIES( tractor );
- mlt_producer clip_a = mlt_properties_get_data( properties, "mix_in", NULL );
- mlt_producer clip_b = mlt_properties_get_data( properties, "mix_out", NULL );
- mlt_producer track_a = mlt_tractor_get_track( tractor, 0 );
- mlt_producer track_b = mlt_tractor_get_track( tractor, 1 );
- int length = out - in + 1;
- int length_diff = length - mlt_producer_get_playtime( MLT_TRACTOR_PRODUCER( tractor ) );
- mlt_events_block( MLT_PLAYLIST_PROPERTIES( this ), this );
-
- if ( clip_a != NULL )
- mlt_producer_set_in_and_out( clip_a, mlt_producer_get_in( clip_a ), mlt_producer_get_out( clip_a ) - length_diff );
-
- if ( clip_b != NULL )
- mlt_producer_set_in_and_out( clip_b, mlt_producer_get_in( clip_b ) + length_diff, mlt_producer_get_out( clip_b ) );
-
- mlt_producer_set_in_and_out( track_a, mlt_producer_get_in( track_a ) - length_diff, mlt_producer_get_out( track_a ) );
- mlt_producer_set_in_and_out( track_b, mlt_producer_get_in( track_b ), mlt_producer_get_out( track_b ) + length_diff );
- mlt_producer_set_in_and_out( MLT_MULTITRACK_PRODUCER( mlt_tractor_multitrack( tractor ) ), in, out );
- mlt_producer_set_in_and_out( MLT_TRACTOR_PRODUCER( tractor ), in, out );
- mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( mix->producer ), "length", out - in + 1 );
- mlt_producer_set_in_and_out( mix->producer, in, out );
-
- mlt_events_unblock( MLT_PLAYLIST_PROPERTIES( this ), this );
- mlt_playlist_virtual_refresh( this );
- }
- return error;
-}
-
-/** Consolidate adjacent blank producers.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param keep_length set false to remove the last entry if it is blank
- */
-
-void mlt_playlist_consolidate_blanks( mlt_playlist this, int keep_length )
-{
- if ( this != NULL )
- {
- int i = 0;
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
-
- mlt_events_block( properties, properties );
- for ( i = 1; i < this->count; i ++ )
- {
- playlist_entry *left = this->list[ i - 1 ];
- playlist_entry *right = this->list[ i ];
-
- if ( mlt_producer_is_blank( left->producer ) && mlt_producer_is_blank( right->producer ) )
- {
- mlt_playlist_resize_clip( this, i - 1, 0, left->frame_count + right->frame_count - 1 );
- mlt_playlist_remove( this, i -- );
- }
- }
-
- if ( !keep_length && this->count > 0 )
- {
- playlist_entry *last = this->list[ this->count - 1 ];
- if ( mlt_producer_is_blank( last->producer ) )
- mlt_playlist_remove( this, this->count - 1 );
- }
-
- mlt_events_unblock( properties, properties );
- mlt_playlist_virtual_refresh( this );
- }
-}
-
-/** Determine if the specified clip index is a blank.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return true if there was an error
- */
-
-int mlt_playlist_is_blank( mlt_playlist this, int clip )
-{
- return this == NULL || mlt_producer_is_blank( mlt_playlist_get_clip( this, clip ) );
-}
-
-/** Determine if the specified position is a blank.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position a time relative to the start or end (negative) of the playlist
- * \return true if there was an error
- */
-
-int mlt_playlist_is_blank_at( mlt_playlist this, mlt_position position )
-{
- return this == NULL || mlt_producer_is_blank( mlt_playlist_get_clip_at( this, position ) );
-}
-
-/** Replace the specified clip with a blank and return the clip.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return a producer or NULL if there was an error
- */
-
-mlt_producer mlt_playlist_replace_with_blank( mlt_playlist this, int clip )
-{
- mlt_producer producer = NULL;
- if ( !mlt_playlist_is_blank( this, clip ) )
- {
- playlist_entry *entry = this->list[ clip ];
- int in = entry->frame_in;
- int out = entry->frame_out;
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- producer = entry->producer;
- mlt_properties_inc_ref( MLT_PRODUCER_PROPERTIES( producer ) );
- mlt_events_block( properties, properties );
- mlt_playlist_remove( this, clip );
- mlt_playlist_blank( this, out - in );
- mlt_playlist_move( this, this->count - 1, clip );
- mlt_events_unblock( properties, properties );
- mlt_playlist_virtual_refresh( this );
- mlt_producer_set_in_and_out( producer, in, out );
- }
- return producer;
-}
-
-/** Insert blank space.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the new blank section
- * \param length the ending time of the new blank section (duration - 1)
- */
-
-void mlt_playlist_insert_blank( mlt_playlist this, int clip, int length )
-{
- if ( this != NULL && length >= 0 )
- {
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- mlt_events_block( properties, properties );
- mlt_playlist_blank( this, length );
- mlt_playlist_move( this, this->count - 1, clip );
- mlt_events_unblock( properties, properties );
- mlt_playlist_virtual_refresh( this );
- }
-}
-
-/** Resize a blank entry.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position the time at which the blank entry exists relative to the start or end (negative) of the playlist.
- * \param length the additional amount of blank frames to add
- * \param find true to fist locate the blank after the clip at position
- */
-void mlt_playlist_pad_blanks( mlt_playlist this, mlt_position position, int length, int find )
-{
- if ( this != NULL && length != 0 )
- {
- int clip = mlt_playlist_get_clip_index_at( this, position );
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- mlt_events_block( properties, properties );
- if ( find && clip < this->count && !mlt_playlist_is_blank( this, clip ) )
- clip ++;
- if ( clip < this->count && mlt_playlist_is_blank( this, clip ) )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( this, &info, clip );
- if ( info.frame_out + length > info.frame_in )
- mlt_playlist_resize_clip( this, clip, info.frame_in, info.frame_out + length );
- else
- mlt_playlist_remove( this, clip );
- }
- else if ( find && clip < this->count && length > 0 )
- {
- mlt_playlist_insert_blank( this, clip, length );
- }
- mlt_events_unblock( properties, properties );
- mlt_playlist_virtual_refresh( this );
- }
-}
-
-/** Insert a clip at a specific time.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position the time at which to insert
- * \param producer the producer to insert
- * \param mode true if you want to overwrite any blank section
- * \return true if there was an error
- */
-
-int mlt_playlist_insert_at( mlt_playlist this, mlt_position position, mlt_producer producer, int mode )
-{
- int ret = this == NULL || position < 0 || producer == NULL;
- if ( ret == 0 )
- {
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- int length = mlt_producer_get_playtime( producer );
- int clip = mlt_playlist_get_clip_index_at( this, position );
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( this, &info, clip );
- mlt_events_block( properties, this );
- if ( clip < this->count && mlt_playlist_is_blank( this, clip ) )
- {
- // Split and move to new clip if need be
- if ( position != info.start && mlt_playlist_split( this, clip, position - info.start - 1 ) == 0 )
- mlt_playlist_get_clip_info( this, &info, ++ clip );
-
- // Split again if need be
- if ( length < info.frame_count )
- mlt_playlist_split( this, clip, length - 1 );
-
- // Remove
- mlt_playlist_remove( this, clip );
-
- // Insert
- mlt_playlist_insert( this, producer, clip, -1, -1 );
- ret = clip;
- }
- else if ( clip < this->count )
- {
- if ( position > info.start + info.frame_count / 2 )
- clip ++;
- if ( mode == 1 && clip < this->count && mlt_playlist_is_blank( this, clip ) )
- {
- mlt_playlist_get_clip_info( this, &info, clip );
- if ( length < info.frame_count )
- mlt_playlist_split( this, clip, length );
- mlt_playlist_remove( this, clip );
- }
- mlt_playlist_insert( this, producer, clip, -1, -1 );
- ret = clip;
- }
- else
- {
- if ( mode == 1 ) {
- if ( position == info.start )
- mlt_playlist_remove( this, clip );
- else
- mlt_playlist_blank( this, position - mlt_properties_get_int( properties, "length" ) - 1 );
- }
- mlt_playlist_append( this, producer );
- ret = this->count - 1;
- }
- mlt_events_unblock( properties, this );
- mlt_playlist_virtual_refresh( this );
- }
- else
- {
- ret = -1;
- }
- return ret;
-}
-
-/** Get the time at which the clip starts relative to the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return the starting time
- */
-
-int mlt_playlist_clip_start( mlt_playlist this, int clip )
-{
- mlt_playlist_clip_info info;
- if ( mlt_playlist_get_clip_info( this, &info, clip ) == 0 )
- return info.start;
- return clip < 0 ? 0 : mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) );
-}
-
-/** Get the playable duration of the clip.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \return the duration of the playlist entry
- */
-
-int mlt_playlist_clip_length( mlt_playlist this, int clip )
-{
- mlt_playlist_clip_info info;
- if ( mlt_playlist_get_clip_info( this, &info, clip ) == 0 )
- return info.frame_count;
- return 0;
-}
-
-/** Get the duration of a blank space.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param clip the index of the playlist entry
- * \param bounded the maximum number of blank entries or 0 for all
- * \return the duration of a blank section
- */
-
-int mlt_playlist_blanks_from( mlt_playlist this, int clip, int bounded )
-{
- int count = 0;
- mlt_playlist_clip_info info;
- if ( this != NULL && clip < this->count )
- {
- mlt_playlist_get_clip_info( this, &info, clip );
- if ( mlt_playlist_is_blank( this, clip ) )
- count += info.frame_count;
- if ( bounded == 0 )
- bounded = this->count;
- for ( clip ++; clip < this->count && bounded >= 0; clip ++ )
- {
- mlt_playlist_get_clip_info( this, &info, clip );
- if ( mlt_playlist_is_blank( this, clip ) )
- count += info.frame_count;
- else
- bounded --;
- }
- }
- return count;
-}
-
-/** Remove a portion of the playlist by time.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- * \param position the starting time
- * \param length the duration of time to remove
- * \return the new entry index at the position
- */
-
-int mlt_playlist_remove_region( mlt_playlist this, mlt_position position, int length )
-{
- int index = mlt_playlist_get_clip_index_at( this, position );
- if ( index >= 0 && index < this->count )
- {
- mlt_properties properties = MLT_PLAYLIST_PROPERTIES( this );
- int clip_start = mlt_playlist_clip_start( this, index );
- int clip_length = mlt_playlist_clip_length( this, index );
- int list_length = mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( this ) );
- mlt_events_block( properties, this );
-
- if ( position + length > list_length )
- length -= ( position + length - list_length );
-
- if ( clip_start < position )
- {
- mlt_playlist_split( this, index ++, position - clip_start );
- clip_length -= position - clip_start;
- }
-
- while( length > 0 )
- {
- if ( mlt_playlist_clip_length( this, index ) > length )
- mlt_playlist_split( this, index, length );
- length -= mlt_playlist_clip_length( this, index );
- mlt_playlist_remove( this, index );
- }
-
- mlt_playlist_consolidate_blanks( this, 0 );
- mlt_events_unblock( properties, this );
- mlt_playlist_virtual_refresh( this );
-
- // Just to be sure, we'll get the clip index again...
- index = mlt_playlist_get_clip_index_at( this, position );
- }
- return index;
-}
-
-/** Not implemented
- *
- * \deprecated not implemented
- * \public \memberof mlt_playlist_s
- * \param this
- * \param position
- * \param length
- * \param new_position
- * \return
- */
-
-int mlt_playlist_move_region( mlt_playlist this, mlt_position position, int length, int new_position )
-{
- if ( this != NULL )
- {
- }
- return 0;
-}
-
-/** Get the current frame.
- *
- * The implementation of the get_frame virtual function.
- * \private \memberof mlt_playlist_s
- * \param producer a producer
- * \param frame a frame by reference
- * \param index the time at which to get the frame
- * \return false
- */
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Check that we have a producer
- if ( producer == NULL )
- {
- *frame = NULL;
- return -1;
- }
-
- // Get this mlt_playlist
- mlt_playlist this = producer->child;
-
- // Need to ensure the frame is deinterlaced when repeating 1 frame
- int progressive = 0;
-
- // Get the real producer
- mlt_service real = mlt_playlist_virtual_seek( this, &progressive );
-
- // Check that we have a producer
- if ( real == NULL )
- {
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
- return 0;
- }
-
- // Get the frame
- if ( !mlt_properties_get_int( MLT_SERVICE_PROPERTIES( real ), "meta.fx_cut" ) )
- {
- mlt_service_get_frame( real, frame, index );
- }
- else
- {
- mlt_producer parent = mlt_producer_cut_parent( ( mlt_producer )real );
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "fx_cut", 1 );
- mlt_frame_push_service( *frame, NULL );
- mlt_frame_push_audio( *frame, NULL );
- mlt_service_apply_filters( MLT_PRODUCER_SERVICE( parent ), *frame, 0 );
- mlt_service_apply_filters( real, *frame, 0 );
- mlt_deque_pop_front( MLT_FRAME_IMAGE_STACK( *frame ) );
- mlt_deque_pop_front( MLT_FRAME_AUDIO_STACK( *frame ) );
- }
-
- // Check if we're at the end of the clip
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
- if ( mlt_properties_get_int( properties, "end_of_clip" ) )
- mlt_playlist_virtual_set_out( this );
-
- // Set the consumer progressive property
- if ( progressive )
- {
- mlt_properties_set_int( properties, "consumer_deinterlace", progressive );
- mlt_properties_set_int( properties, "test_audio", 1 );
- }
-
- // Check for notifier and call with appropriate argument
- mlt_properties playlist_properties = MLT_PRODUCER_PROPERTIES( producer );
- void ( *notifier )( void * ) = mlt_properties_get_data( playlist_properties, "notifier", NULL );
- if ( notifier != NULL )
- {
- void *argument = mlt_properties_get_data( playlist_properties, "notifier_arg", NULL );
- notifier( argument );
- }
-
- // Update position on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_frame( producer ) );
-
- // Position ourselves on the next frame
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-/** Close the playlist.
- *
- * \public \memberof mlt_playlist_s
- * \param this a playlist
- */
-
-void mlt_playlist_close( mlt_playlist this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_PLAYLIST_PROPERTIES( this ) ) <= 0 )
- {
- int i = 0;
- this->parent.close = NULL;
- for ( i = 0; i < this->count; i ++ )
- {
- mlt_event_close( this->list[ i ]->event );
- mlt_producer_close( this->list[ i ]->producer );
- free( this->list[ i ] );
- }
- mlt_producer_close( &this->blank );
- mlt_producer_close( &this->parent );
- free( this->list );
- free( this );
- }
-}
+++ /dev/null
-/**
- * \file mlt_playlist.h
- * \brief playlist service class
- * \see mlt_playlist_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PLAYLIST_H_
-#define _MLT_PLAYLIST_H_
-
-#include "mlt_producer.h"
-
-/** \brief structure for returning clip information from a playlist entry
- */
-
-typedef struct
-{
- int clip; /**< the index of the clip within the playlist */
- mlt_producer producer; /**< the clip's producer (or parent producer of a cut) */
- mlt_producer cut; /**< the clips' cut producer */
- mlt_position start; /**< the time this begins relative to the beginning of the playlist */
- char *resource; /**< the file name or address of the clip */
- mlt_position frame_in; /**< the clip's in point */
- mlt_position frame_out; /**< the clip's out point */
- mlt_position frame_count; /**< the duration of the clip */
- mlt_position length; /**< the unedited duration of the clip */
- float fps; /**< the frame rate of the clip */
- int repeat; /**< the number of times the clip is repeated */
-}
-mlt_playlist_clip_info;
-
-/** Playlist Entry
-*/
-
-typedef struct playlist_entry_s playlist_entry;
-
-/** \brief Playlist class
- *
- * A playlist is a sequential container of producers and blank spaces. The class provides all
- * sorts of playlist assembly and manipulation routines. A playlist is also a producer within
- * the framework.
- *
- * \extends mlt_producer_s
- * \properties \em autoclose Set this true if you are doing sequential processing and want to
- * automatically close producers as they are finished being used to free resources.
- * \properties \em meta.fx_cut Set true on a producer to indicate that it is a "fx_cut,"
- * which is a way to add filters as a playlist entry - useful only in a multitrack. See FxCut on the wiki.
- * \properties \em mix_in
- * \properties \em mix_out
- */
-
-struct mlt_playlist_s
-{
- struct mlt_producer_s parent;
- struct mlt_producer_s blank;
-
- int size;
- int count;
- playlist_entry **list;
-};
-
-#define MLT_PLAYLIST_PRODUCER( playlist ) ( &( playlist )->parent )
-#define MLT_PLAYLIST_SERVICE( playlist ) MLT_PRODUCER_SERVICE( MLT_PLAYLIST_PRODUCER( playlist ) )
-#define MLT_PLAYLIST_PROPERTIES( playlist ) MLT_SERVICE_PROPERTIES( MLT_PLAYLIST_SERVICE( playlist ) )
-
-extern mlt_playlist mlt_playlist_init( );
-extern mlt_producer mlt_playlist_producer( mlt_playlist self );
-extern mlt_service mlt_playlist_service( mlt_playlist self );
-extern mlt_properties mlt_playlist_properties( mlt_playlist self );
-extern int mlt_playlist_count( mlt_playlist self );
-extern int mlt_playlist_clear( mlt_playlist self );
-extern int mlt_playlist_append( mlt_playlist self, mlt_producer producer );
-extern int mlt_playlist_append_io( mlt_playlist self, mlt_producer producer, mlt_position in, mlt_position out );
-extern int mlt_playlist_blank( mlt_playlist self, mlt_position length );
-extern mlt_position mlt_playlist_clip( mlt_playlist self, mlt_whence whence, int index );
-extern int mlt_playlist_current_clip( mlt_playlist self );
-extern mlt_producer mlt_playlist_current( mlt_playlist self );
-extern int mlt_playlist_get_clip_info( mlt_playlist self, mlt_playlist_clip_info *info, int index );
-extern int mlt_playlist_insert( mlt_playlist self, mlt_producer producer, int where, mlt_position in, mlt_position out );
-extern int mlt_playlist_remove( mlt_playlist self, int where );
-extern int mlt_playlist_move( mlt_playlist self, int from, int to );
-extern int mlt_playlist_resize_clip( mlt_playlist self, int clip, mlt_position in, mlt_position out );
-extern int mlt_playlist_repeat_clip( mlt_playlist self, int clip, int repeat );
-extern int mlt_playlist_split( mlt_playlist self, int clip, mlt_position position );
-extern int mlt_playlist_split_at( mlt_playlist self, mlt_position position, int left );
-extern int mlt_playlist_join( mlt_playlist self, int clip, int count, int merge );
-extern int mlt_playlist_mix( mlt_playlist self, int clip, int length, mlt_transition transition );
-extern int mlt_playlist_mix_add( mlt_playlist self, int clip, mlt_transition transition );
-extern mlt_producer mlt_playlist_get_clip( mlt_playlist self, int clip );
-extern mlt_producer mlt_playlist_get_clip_at( mlt_playlist self, mlt_position position );
-extern int mlt_playlist_get_clip_index_at( mlt_playlist self, mlt_position position );
-extern int mlt_playlist_clip_is_mix( mlt_playlist self, int clip );
-extern void mlt_playlist_consolidate_blanks( mlt_playlist self, int keep_length );
-extern int mlt_playlist_is_blank( mlt_playlist self, int clip );
-extern int mlt_playlist_is_blank_at( mlt_playlist self, mlt_position position );
-extern void mlt_playlist_insert_blank( mlt_playlist self, int clip, int length );
-extern void mlt_playlist_pad_blanks( mlt_playlist self, mlt_position position, int length, int find );
-extern mlt_producer mlt_playlist_replace_with_blank( mlt_playlist self, int clip );
-extern int mlt_playlist_insert_at( mlt_playlist self, mlt_position position, mlt_producer producer, int mode );
-extern int mlt_playlist_clip_start( mlt_playlist self, int clip );
-extern int mlt_playlist_clip_length( mlt_playlist self, int clip );
-extern int mlt_playlist_blanks_from( mlt_playlist self, int clip, int bounded );
-extern int mlt_playlist_remove_region( mlt_playlist self, mlt_position position, int length );
-extern int mlt_playlist_move_region( mlt_playlist self, mlt_position position, int length, int new_position );
-extern void mlt_playlist_close( mlt_playlist self );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_pool.c
- * \brief memory pooling functionality
- * \see mlt_pool_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_properties.h"
-#include "mlt_deque.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-
-// Not nice - memalign is defined here apparently?
-#ifdef linux
-#include <malloc.h>
-#endif
-
-/** global singleton for tracking pools */
-
-static mlt_properties pools = NULL;
-
-/** \brief Pool (memory) class
- */
-
-typedef struct mlt_pool_s
-{
- pthread_mutex_t lock; ///< lock to prevent race conditions
- mlt_deque stack; ///< a stack of addresses to memory blocks
- int size; ///< the size of the memory block as a power of 2
- int count; ///< the number of blocks in the pool
-}
-*mlt_pool;
-
-/** \brief private to mlt_pool_s, for tracking items to release
- */
-
-typedef struct mlt_release_s
-{
- mlt_pool pool;
- int references;
-}
-*mlt_release;
-
-/** Create a pool.
- *
- * \private \memberof mlt_pool_s
- * \param size the size of the memory blocks to hold as some power of two
- * \return a new pool object
- */
-
-static mlt_pool pool_init( int size )
-{
- // Create the pool
- mlt_pool this = calloc( 1, sizeof( struct mlt_pool_s ) );
-
- // Initialise it
- if ( this != NULL )
- {
- // Initialise the mutex
- pthread_mutex_init( &this->lock, NULL );
-
- // Create the stack
- this->stack = mlt_deque_init( );
-
- // Assign the size
- this->size = size;
- }
-
- // Return it
- return this;
-}
-
-/** Get an item from the pool.
- *
- * \private \memberof mlt_pool_s
- * \param this a pool
- * \return an opaque pointer
- */
-
-static void *pool_fetch( mlt_pool this )
-{
- // We will generate a release object
- void *ptr = NULL;
-
- // Sanity check
- if ( this != NULL )
- {
- // Lock the pool
- pthread_mutex_lock( &this->lock );
-
- // Check if the stack is empty
- if ( mlt_deque_count( this->stack ) != 0 )
- {
- // Pop the top of the stack
- ptr = mlt_deque_pop_back( this->stack );
-
- // Assign the reference
- ( ( mlt_release )ptr )->references = 1;
- }
- else
- {
- // We need to generate a release item
-#ifdef linux
- mlt_release release = memalign( 16, this->size );
-#else
- mlt_release release = malloc( this->size );
-#endif
-
- // Initialise it
- if ( release != NULL )
- {
- // Increment the number of items allocated to this pool
- this->count ++;
-
- // Assign the pool
- release->pool = this;
-
- // Assign the reference
- release->references = 1;
-
- // Determine the ptr
- ptr = ( char * )release + sizeof( struct mlt_release_s );
- }
- }
-
- // Unlock the pool
- pthread_mutex_unlock( &this->lock );
- }
-
- // Return the generated release object
- return ptr;
-}
-
-/** Return an item to the pool.
- *
- * \private \memberof mlt_pool_s
- * \param ptr an opaque pointer
- */
-
-static void pool_return( void *ptr )
-{
- // Sanity checks
- if ( ptr != NULL )
- {
- // Get the release pointer
- mlt_release that = ( void * )(( char * )ptr - sizeof( struct mlt_release_s ));
-
- // Get the pool
- mlt_pool this = that->pool;
-
- if ( this != NULL )
- {
- // Lock the pool
- pthread_mutex_lock( &this->lock );
-
- // Push the that back back on to the stack
- mlt_deque_push_back( this->stack, ptr );
-
- // Unlock the pool
- pthread_mutex_unlock( &this->lock );
-
- // Ensure that we don't clean up
- ptr = NULL;
- }
- }
-
- // Tidy up - this will only occur if the returned item is incorrect
- if ( ptr != NULL )
- {
- // Free the release itself
- free( ( char * )ptr - sizeof( struct mlt_release_s ) );
- }
-}
-
-/** Destroy a pool.
- *
- * \private \memberof mlt_pool_s
- * \param this a pool
- */
-
-static void pool_close( mlt_pool this )
-{
- if ( this != NULL )
- {
- // We need to free up all items in the pool
- void *release = NULL;
-
- // Iterate through the stack until depleted
- while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
- {
- // We'll free this item now
- free( ( char * )release - sizeof( struct mlt_release_s ) );
- }
-
- // We can now close the stack
- mlt_deque_close( this->stack );
-
- // Destroy the mutex
- pthread_mutex_destroy( &this->lock );
-
- // Close the pool
- free( this );
- }
-}
-
-/** Initialise the global pool.
- *
- * \public \memberof mlt_pool_s
- */
-
-void mlt_pool_init( )
-{
- // Loop variable used to create the pools
- int i = 0;
-
- // Create the pools
- pools = mlt_properties_new( );
-
- // Create the pools
- for ( i = 8; i < 31; i ++ )
- {
- // Each properties item needs a name
- char name[ 32 ];
-
- // Construct a pool
- mlt_pool pool = pool_init( 1 << i );
-
- // Generate a name
- sprintf( name, "%d", i );
-
- // Register with properties
- mlt_properties_set_data( pools, name, pool, 0, ( mlt_destructor )pool_close, NULL );
- }
-}
-
-/** Allocate size bytes from the pool.
- *
- * \public \memberof mlt_pool_s
- * \param size the number of bytes
- */
-
-void *mlt_pool_alloc( int size )
-{
- // This will be used to obtain the pool to use
- mlt_pool pool = NULL;
-
- // Determines the index of the pool to use
- int index = 8;
-
- // Minimum size pooled is 256 bytes
- size = size + sizeof( mlt_release );
- while ( ( 1 << index ) < size )
- index ++;
-
- // Now get the pool at the index
- pool = mlt_properties_get_data_at( pools, index - 8, NULL );
-
- // Now get the real item
- return pool_fetch( pool );
-}
-
-/** Allocate size bytes from the pool.
- *
- * \public \memberof mlt_pool_s
- * \param ptr an opaque pointer - can be in the pool or a new block to allocate
- * \param size the number of bytes
- */
-
-void *mlt_pool_realloc( void *ptr, int size )
-{
- // Result to return
- void *result = NULL;
-
- // Check if we actually have an address
- if ( ptr != NULL )
- {
- // Get the release pointer
- mlt_release that = ( void * )(( char * )ptr - sizeof( struct mlt_release_s ));
-
- // If the current pool this ptr belongs to is big enough
- if ( size > that->pool->size - sizeof( struct mlt_release_s ) )
- {
- // Allocate
- result = mlt_pool_alloc( size );
-
- // Copy
- memcpy( result, ptr, that->pool->size - sizeof( struct mlt_release_s ) );
-
- // Release
- mlt_pool_release( ptr );
- }
- else
- {
- // Nothing to do
- result = ptr;
- }
- }
- else
- {
- // Simply allocate
- result = mlt_pool_alloc( size );
- }
-
- return result;
-}
-
-/** Purge unused items in the pool.
- *
- * A form of garbage collection.
- * \public \memberof mlt_pool_s
- */
-
-void mlt_pool_purge( )
-{
- int i = 0;
-
- // For each pool
- for ( i = 0; i < mlt_properties_count( pools ); i ++ )
- {
- // Get the pool
- mlt_pool this = mlt_properties_get_data_at( pools, i, NULL );
-
- // Pointer to unused memory
- void *release = NULL;
-
- // Lock the pool
- pthread_mutex_lock( &this->lock );
-
- // We'll free all unused items now
- while ( ( release = mlt_deque_pop_back( this->stack ) ) != NULL )
- free( ( char * )release - sizeof( struct mlt_release_s ) );
-
- // Unlock the pool
- pthread_mutex_unlock( &this->lock );
- }
-}
-
-/** Release the allocated memory.
- *
- * \public \memberof mlt_pool_s
- * \param release an opaque pointer of a block in the pool
- */
-
-void mlt_pool_release( void *release )
-{
- // Return to the pool
- pool_return( release );
-}
-
-/** Close the pool.
- *
- * \public \memberof mlt_pool_s
- */
-
-void mlt_pool_close( )
-{
-#ifdef _MLT_POOL_CHECKS_
- // Stats dump on close
- int i = 0;
- for ( i = 0; i < mlt_properties_count( pools ); i ++ )
- {
- mlt_pool pool = mlt_properties_get_data_at( pools, i, NULL );
- if ( pool->count )
- mlt_log( NULL, MLT_LOG_DEBUG, "%s: size %d allocated %d returned %d %c\n", __FUNCTION__,
- pool->size, pool->count, mlt_deque_count( pool->stack ),
- pool->count != mlt_deque_count( pool->stack ) ? '*' : ' ' );
- }
-#endif
-
- // Close the properties
- mlt_properties_close( pools );
-}
-
+++ /dev/null
-/**
- * \file mlt_pool.h
- * \brief memory pooling functionality
- * \see mlt_pool_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_POOL_H
-#define _MLT_POOL_H
-
-extern void mlt_pool_init( );
-extern void *mlt_pool_alloc( int size );
-extern void *mlt_pool_realloc( void *ptr, int size );
-extern void mlt_pool_release( void *release );
-extern void mlt_pool_purge( );
-extern void mlt_pool_close( );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_producer.c
- * \brief abstraction for all producer services
- * \see mlt_producer_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_producer.h"
-#include "mlt_factory.h"
-#include "mlt_frame.h"
-#include "mlt_parser.h"
-#include "mlt_profile.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Forward references. */
-
-static int producer_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-static void mlt_producer_property_changed( mlt_service owner, mlt_producer this, char *name );
-static void mlt_producer_service_changed( mlt_service owner, mlt_producer this );
-
-/* for debugging */
-//#define _MLT_PRODUCER_CHECKS_ 1
-#ifdef _MLT_PRODUCER_CHECKS_
-static int producers_created = 0;
-static int producers_destroyed = 0;
-#endif
-
-/** Initialize a producer service.
- *
- * \public \memberof mlt_producer_s
- * \param this the producer structure to initialize
- * \param child a pointer to the child object for the subclass
- * \return true if there was an error
- */
-
-int mlt_producer_init( mlt_producer this, void *child )
-{
- // Check that we haven't received NULL
- int error = this == NULL;
-
- // Continue if no error
- if ( error == 0 )
- {
-#ifdef _MLT_PRODUCER_CHECKS_
- producers_created ++;
-#endif
-
- // Initialise the producer
- memset( this, 0, sizeof( struct mlt_producer_s ) );
-
- // Associate with the child
- this->child = child;
-
- // Initialise the service
- if ( mlt_service_init( &this->parent, this ) == 0 )
- {
- // The parent is the service
- mlt_service parent = &this->parent;
-
- // Define the parent close
- parent->close = ( mlt_destructor )mlt_producer_close;
- parent->close_object = this;
-
- // For convenience, we'll assume the close_object is this
- this->close_object = this;
-
- // Get the properties of the parent
- mlt_properties properties = MLT_SERVICE_PROPERTIES( parent );
-
- // Set the default properties
- mlt_properties_set( properties, "mlt_type", "mlt_producer" );
- mlt_properties_set_position( properties, "_position", 0.0 );
- mlt_properties_set_double( properties, "_frame", 0 );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( NULL ) );
- mlt_properties_set_double( properties, "_speed", 1.0 );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 14999 );
- mlt_properties_set_position( properties, "length", 15000 );
- mlt_properties_set( properties, "eof", "pause" );
- mlt_properties_set( properties, "resource", "<producer>" );
-
- // Override service get_frame
- parent->get_frame = producer_get_frame;
-
- mlt_events_listen( properties, this, "service-changed", ( mlt_listener )mlt_producer_service_changed );
- mlt_events_listen( properties, this, "property-changed", ( mlt_listener )mlt_producer_property_changed );
- mlt_events_register( properties, "producer-changed", NULL );
- }
- }
-
- return error;
-}
-
-/** Listener for property changes.
- *
- * If the in, out, or length properties changed, fire a "producer-changed" event.
- *
- * \private \memberof mlt_producer_s
- * \param owner a service (ignored)
- * \param this the producer
- * \param name the property that changed
- */
-
-static void mlt_producer_property_changed( mlt_service owner, mlt_producer this, char *name )
-{
- if ( !strcmp( name, "in" ) || !strcmp( name, "out" ) || !strcmp( name, "length" ) )
- mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "producer-changed", NULL );
-}
-
-/** Listener for service changes.
- *
- * Fires the "producer-changed" event.
- *
- * \private \memberof mlt_producer_s
- * \param owner a service (ignored)
- * \param this the producer
- */
-
-static void mlt_producer_service_changed( mlt_service owner, mlt_producer this )
-{
- mlt_events_fire( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "producer-changed", NULL );
-}
-
-/** Create and initialize a new producer.
- *
- * \public \memberof mlt_producer_s
- * \return the new producer
- */
-
-mlt_producer mlt_producer_new( )
-{
- mlt_producer this = malloc( sizeof( struct mlt_producer_s ) );
- mlt_producer_init( this, NULL );
- return this;
-}
-
-/** Determine if producer is a cut.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return true if \p this is a "cut" producer
- * \see mlt_producer_cut
- */
-
-int mlt_producer_is_cut( mlt_producer this )
-{
- return mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( this ), "_cut" );
-}
-
-/** Determine if producer is a mix.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return true if this is a "mix" producer
- * \todo Define a mix producer.
- */
-
-int mlt_producer_is_mix( mlt_producer this )
-{
- mlt_properties properties = this != NULL ? MLT_PRODUCER_PROPERTIES( this ) : NULL;
- mlt_tractor tractor = properties != NULL ? mlt_properties_get_data( properties, "mlt_mix", NULL ) : NULL;
- return tractor != NULL;
-}
-
-/** Determine if the producer is a blank.
- *
- * Blank producers should only appear as an item in a playlist.
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return true if this is a "blank" producer
- * \see mlt_playlist_insert_blank
- */
-
-int mlt_producer_is_blank( mlt_producer this )
-{
- return this == NULL || !strcmp( mlt_properties_get( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), "resource" ), "blank" );
-}
-
-/** Obtain the parent producer.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return either the parent producer if this is a "cut" producer or \p this otherwise.
- */
-
-mlt_producer mlt_producer_cut_parent( mlt_producer this )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- if ( mlt_producer_is_cut( this ) )
- return mlt_properties_get_data( properties, "_cut_parent", NULL );
- else
- return this;
-}
-
-/** Create a cut of this producer.
- *
- * A "cut" is a portion of another (parent) producer.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \param in the beginning
- * \param out the end
- * \return the new producer
- * \todo Expand on the value of a cut.
- */
-
-mlt_producer mlt_producer_cut( mlt_producer this, int in, int out )
-{
- mlt_producer result = mlt_producer_new( );
- mlt_producer parent = mlt_producer_cut_parent( this );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( result );
- mlt_properties parent_props = MLT_PRODUCER_PROPERTIES( parent );
-
- mlt_events_block( MLT_PRODUCER_PROPERTIES( result ), MLT_PRODUCER_PROPERTIES( result ) );
- // Special case - allow for a cut of the entire producer (this will squeeze all other cuts to 0)
- if ( in <= 0 )
- in = 0;
- if ( ( out < 0 || out >= mlt_producer_get_length( parent ) ) && !mlt_producer_is_blank( this ) )
- out = mlt_producer_get_length( parent ) - 1;
-
- mlt_properties_inc_ref( parent_props );
- mlt_properties_set_int( properties, "_cut", 1 );
- mlt_properties_set_data( properties, "_cut_parent", parent, 0, ( mlt_destructor )mlt_producer_close, NULL );
- mlt_properties_set_position( properties, "length", mlt_properties_get_position( parent_props, "length" ) );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( parent_props, "aspect_ratio" ) );
- mlt_producer_set_in_and_out( result, in, out );
-
- return result;
-}
-
-/** Get the parent service object.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the service parent class
- * \see MLT_PRODUCER_SERVICE
- */
-
-mlt_service mlt_producer_service( mlt_producer this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the producer properties.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the producer's property list
- * \see MLT_PRODUCER_PROPERTIES
- */
-
-mlt_properties mlt_producer_properties( mlt_producer this )
-{
- return MLT_SERVICE_PROPERTIES( &this->parent );
-}
-
-/** Seek to a specified position.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \param position set the "play head" position of the producer
- * \return false
- * \todo Document how the properties affect behavior.
- */
-
-int mlt_producer_seek( mlt_producer this, mlt_position position )
-{
- // Determine eof handling
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- char *eof = mlt_properties_get( properties, "eof" );
- int use_points = 1 - mlt_properties_get_int( properties, "ignore_points" );
-
- // Recursive behaviour for cuts - repositions parent and then repositions cut
- // hence no return on this condition
- if ( mlt_producer_is_cut( this ) )
- mlt_producer_seek( mlt_producer_cut_parent( this ), position + mlt_producer_get_in( this ) );
-
- // Check bounds
- if ( position < 0 || mlt_producer_get_playtime( this ) == 0 )
- {
- position = 0;
- }
- else if ( use_points && ( eof == NULL || !strcmp( eof, "pause" ) ) && position >= mlt_producer_get_playtime( this ) )
- {
- mlt_producer_set_speed( this, 0 );
- position = mlt_producer_get_playtime( this ) - 1;
- }
- else if ( use_points && !strcmp( eof, "loop" ) && position >= mlt_producer_get_playtime( this ) )
- {
- position = (int)position % (int)mlt_producer_get_playtime( this );
- }
-
- // Set the position
- mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "_position", position );
-
- // Calculate the absolute frame
- mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "_frame", use_points * mlt_producer_get_in( this ) + position );
-
- return 0;
-}
-
-/** Get the current position (relative to in point).
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the position of the "play head" relative to its beginning
- */
-
-mlt_position mlt_producer_position( mlt_producer this )
-{
- return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "_position" );
-}
-
-/** Get the current position (relative to start of producer).
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the position of the "play head" regardless of the in point
- */
-
-mlt_position mlt_producer_frame( mlt_producer this )
-{
- return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "_frame" );
-}
-
-/** Set the playing speed.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \param speed the new speed as a relative factor (1.0 = normal)
- * \return
- */
-
-int mlt_producer_set_speed( mlt_producer this, double speed )
-{
- return mlt_properties_set_double( MLT_PRODUCER_PROPERTIES( this ), "_speed", speed );
-}
-
-/** Get the playing speed.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the speed as a relative factor (1.0 = normal)
- */
-
-double mlt_producer_get_speed( mlt_producer this )
-{
- return mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this ), "_speed" );
-}
-
-/** Get the frames per second.
- *
- * This is determined by the producer's profile.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the video refresh rate
- */
-
-double mlt_producer_get_fps( mlt_producer this )
-{
- mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( this ) );
- return mlt_profile_fps( profile );
-}
-
-/** Set the in and out points.
- *
- * The in point is where play out should start relative to the natural start
- * of the underlying file. The out point is where play out should end, also
- * relative to the start of the underlying file. If the underlying resource is
- * a live stream, then the in point is an offset relative to first usable
- * sample.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \param in the relative starting time
- * \param out the relative ending time
- * \return false
- */
-
-int mlt_producer_set_in_and_out( mlt_producer this, mlt_position in, mlt_position out )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Correct ins and outs if necessary
- if ( in < 0 )
- in = 0;
- else if ( in >= mlt_producer_get_length( this ) )
- in = mlt_producer_get_length( this ) - 1;
-
- if ( out < 0 )
- out = 0;
- else if ( out >= mlt_producer_get_length( this ) && !mlt_producer_is_blank( this ) )
- out = mlt_producer_get_length( this ) - 1;
- else if ( out >= mlt_producer_get_length( this ) && mlt_producer_is_blank( this ) )
- mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( this ), "length", out + 1 );
-
- // Swap ins and outs if wrong
- if ( out < in )
- {
- mlt_position t = in;
- in = out;
- out = t;
- }
-
- // Set the values
- mlt_events_block( properties, properties );
- mlt_properties_set_position( properties, "in", in );
- mlt_events_unblock( properties, properties );
- mlt_properties_set_position( properties, "out", out );
-
- return 0;
-}
-
-/** Physically reduce the producer (typically a cut) to a 0 length.
- * Essentially, all 0 length cuts should be immediately removed by containers.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return false
- */
-
-int mlt_producer_clear( mlt_producer this )
-{
- if ( this != NULL )
- {
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- mlt_events_block( properties, properties );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_events_unblock( properties, properties );
- mlt_properties_set_position( properties, "out", -1 );
- }
- return 0;
-}
-
-/** Get the in point.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the in point
- */
-
-mlt_position mlt_producer_get_in( mlt_producer this )
-{
- return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "in" );
-}
-
-/** Get the out point.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the out point
- */
-
-mlt_position mlt_producer_get_out( mlt_producer this )
-{
- return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "out" );
-}
-
-/** Get the total play time.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the playable (based on in and out points) duration
- */
-
-mlt_position mlt_producer_get_playtime( mlt_producer this )
-{
- return mlt_producer_get_out( this ) - mlt_producer_get_in( this ) + 1;
-}
-
-/** Get the total, unedited length of the producer.
- *
- * The value returned by a live streaming producer is unknown.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return the duration of the producer regardless of in and out points
- */
-
-mlt_position mlt_producer_get_length( mlt_producer this )
-{
- return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( this ), "length" );
-}
-
-/** Prepare for next frame.
- *
- * Advance the play out position. If the speed is less than zero, it will
- * move the play out position in the reverse direction.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- */
-
-void mlt_producer_prepare_next( mlt_producer this )
-{
- if ( mlt_producer_get_speed( this ) != 0 )
- mlt_producer_seek( this, mlt_producer_position( this ) + mlt_producer_get_speed( this ) );
-}
-
-/** Get a frame.
- *
- * This is the implementation of the \p get_frame virtual function.
- * It requests a new frame object from the actual producer for the current
- * play out position. The producer and its filters can add information and
- * operations to the frame object in their get_frame handlers.
- *
- * \private \memberof mlt_producer_s
- * \param service a service
- * \param[out] frame a frame by reference
- * \param index as determined by the actual producer
- * \return true if there was an error
- * \todo Learn more about the details and document how certain properties affect
- * its behavior.
- */
-
-static int producer_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
-{
- int result = 1;
- mlt_producer this = service != NULL ? service->child : NULL;
-
- if ( this != NULL && !mlt_producer_is_cut( this ) )
- {
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Determine eof handling
- char *eof = mlt_properties_get( MLT_PRODUCER_PROPERTIES( this ), "eof" );
-
- // Get the speed of the producer
- double speed = mlt_producer_get_speed( this );
-
- // We need to use the clone if it's specified
- mlt_producer clone = mlt_properties_get_data( properties, "use_clone", NULL );
-
- // If no clone is specified, use this
- clone = clone == NULL ? this : clone;
-
- // A properly instatiated producer will have a get_frame method...
- if ( this->get_frame == NULL || ( !strcmp( eof, "continue" ) && mlt_producer_position( this ) > mlt_producer_get_out( this ) ) )
- {
- // Generate a test frame
- *frame = mlt_frame_init( service );
-
- // Set the position
- result = mlt_frame_set_position( *frame, mlt_producer_position( this ) );
-
- // Mark as a test card
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", 1 );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", 1 );
-
- // Calculate the next position
- mlt_producer_prepare_next( this );
- }
- else
- {
- // Get the frame from the implementation
- result = this->get_frame( clone, frame, index );
- }
-
- // Copy the fps and speed of the producer onto the frame
- properties = MLT_FRAME_PROPERTIES( *frame );
- mlt_properties_set_double( properties, "_speed", speed );
- mlt_properties_set_int( properties, "test_audio", mlt_frame_is_test_audio( *frame ) );
- mlt_properties_set_int( properties, "test_image", mlt_frame_is_test_card( *frame ) );
- if ( mlt_properties_get_data( properties, "_producer", NULL ) == NULL )
- mlt_properties_set_data( properties, "_producer", service, 0, NULL, NULL );
- }
- else if ( this != NULL )
- {
- // Get the speed of the cut
- double speed = mlt_producer_get_speed( this );
-
- // Get the parent of this cut
- mlt_producer parent = mlt_producer_cut_parent( this );
-
- // Get the properties of the parent
- mlt_properties parent_properties = MLT_PRODUCER_PROPERTIES( parent );
-
- // Get the properties of the cut
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Determine the clone index
- int clone_index = mlt_properties_get_int( properties, "_clone" );
-
- // Determine the clone to use
- mlt_producer clone = this;
-
- if ( clone_index > 0 )
- {
- char key[ 25 ];
- sprintf( key, "_clone.%d", clone_index - 1 );
- clone = mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( mlt_producer_cut_parent( this ) ), key, NULL );
- if ( clone == NULL ) mlt_log( service, MLT_LOG_ERROR, "requested clone doesn't exist %d\n", clone_index );
- clone = clone == NULL ? this : clone;
- }
- else
- {
- clone = parent;
- }
-
- // We need to seek to the correct position in the clone
- mlt_producer_seek( clone, mlt_producer_get_in( this ) + mlt_properties_get_int( properties, "_position" ) );
-
- // Assign the clone property to the parent
- mlt_properties_set_data( parent_properties, "use_clone", clone, 0, NULL, NULL );
-
- // Now get the frame from the parents service
- result = mlt_service_get_frame( MLT_PRODUCER_SERVICE( parent ), frame, index );
-
- // We're done with the clone now
- mlt_properties_set_data( parent_properties, "use_clone", NULL, 0, NULL, NULL );
-
- // This is useful and required by always_active transitions to determine in/out points of the cut
- if ( mlt_properties_get_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", NULL ) == MLT_PRODUCER_SERVICE( parent ) )
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "_producer", this, 0, NULL, NULL );
-
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( *frame ), "_speed", speed );
- mlt_producer_prepare_next( this );
- }
- else
- {
- *frame = mlt_frame_init( service );
- result = 0;
- }
-
- // Pass on all meta properties from the producer/cut on to the frame
- if ( *frame != NULL && this != NULL )
- {
- int i = 0;
- mlt_properties p_props = MLT_PRODUCER_PROPERTIES( this );
- mlt_properties f_props = MLT_FRAME_PROPERTIES( *frame );
- int count = mlt_properties_count( p_props );
- for ( i = 0; i < count; i ++ )
- {
- char *name = mlt_properties_get_name( p_props, i );
- if ( !strncmp( name, "meta.", 5 ) )
- mlt_properties_set( f_props, name, mlt_properties_get( p_props, name ) );
- else if ( !strncmp( name, "set.", 4 ) )
- mlt_properties_set( f_props, name + 4, mlt_properties_get( p_props, name ) );
- }
- }
-
- return result;
-}
-
-/** Attach a filter.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \param filter the filter to attach
- * \return true if there was an error
- */
-
-int mlt_producer_attach( mlt_producer this, mlt_filter filter )
-{
- return mlt_service_attach( MLT_PRODUCER_SERVICE( this ), filter );
-}
-
-/** Detach a filter.
- *
- * \public \memberof mlt_producer_s
- * \param this a service
- * \param filter the filter to detach
- * \return true if there was an error
- */
-
-int mlt_producer_detach( mlt_producer this, mlt_filter filter )
-{
- return mlt_service_detach( MLT_PRODUCER_SERVICE( this ), filter );
-}
-
-/** Retrieve a filter.
- *
- * \public \memberof mlt_producer_s
- * \param this a service
- * \param index which filter to retrieve
- * \return the filter or null if there was an error
- */
-
-mlt_filter mlt_producer_filter( mlt_producer this, int index )
-{
- return mlt_service_filter( MLT_PRODUCER_SERVICE( this ), index );
-}
-
-/** Clone this producer.
- *
- * \private \memberof mlt_producer_s
- * \param this a producer
- * \return a new producer that is a copy of \p this
- * \see mlt_producer_set_clones
- */
-
-static mlt_producer mlt_producer_clone( mlt_producer this )
-{
- mlt_producer clone = NULL;
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- char *resource = mlt_properties_get( properties, "resource" );
- char *service = mlt_properties_get( properties, "mlt_service" );
- mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( this ) );
-
- mlt_events_block( mlt_factory_event_object( ), mlt_factory_event_object( ) );
-
- if ( service != NULL )
- clone = mlt_factory_producer( profile, service, resource );
-
- if ( clone == NULL && resource != NULL )
- clone = mlt_factory_producer( profile, mlt_environment( "MLT_PRODUCER" ), resource );
-
- if ( clone != NULL )
- mlt_properties_inherit( MLT_PRODUCER_PROPERTIES( clone ), properties );
-
- mlt_events_unblock( mlt_factory_event_object( ), mlt_factory_event_object( ) );
-
- return clone;
-}
-
-/** Create clones.
- *
- * \private \memberof mlt_producer_s
- * \param this a producer
- * \param clones the number of copies to make
- * \see mlt_producer_optimise
- */
-
-static void mlt_producer_set_clones( mlt_producer this, int clones )
-{
- mlt_producer parent = mlt_producer_cut_parent( this );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( parent );
- int existing = mlt_properties_get_int( properties, "_clones" );
- int i = 0;
- char key[ 25 ];
-
- // If the number of existing clones is different, then create/remove as necessary
- if ( existing != clones )
- {
- if ( existing < clones )
- {
- for ( i = existing; i < clones; i ++ )
- {
- mlt_producer clone = mlt_producer_clone( parent );
- sprintf( key, "_clone.%d", i );
- mlt_properties_set_data( properties, key, clone, 0, ( mlt_destructor )mlt_producer_close, NULL );
- }
- }
- else
- {
- for ( i = clones; i < existing; i ++ )
- {
- sprintf( key, "_clone.%d", i );
- mlt_properties_set_data( properties, key, NULL, 0, NULL, NULL );
- }
- }
- }
-
- // Ensure all properties on the parent are passed to the clones
- for ( i = 0; i < clones; i ++ )
- {
- mlt_producer clone = NULL;
- sprintf( key, "_clone.%d", i );
- clone = mlt_properties_get_data( properties, key, NULL );
- if ( clone != NULL )
- mlt_properties_pass( MLT_PRODUCER_PROPERTIES( clone ), properties, "" );
- }
-
- // Update the number of clones on the properties
- mlt_properties_set_int( properties, "_clones", clones );
-}
-
-/** \brief private to mlt_producer_s, used by mlt_producer_optimise() */
-
-typedef struct
-{
- int multitrack;
- int track;
- int position;
- int length;
- int offset;
-}
-track_info;
-
-/** \brief private to mlt_producer_s, used by mlt_producer_optimise() */
-
-typedef struct
-{
- mlt_producer cut;
- int start;
- int end;
-}
-clip_references;
-
-static int intersect( clip_references *a, clip_references *b )
-{
- int diff = ( a->start - b->start ) + ( a->end - b->end );
- return diff >= 0 && diff < ( a->end - a->start + 1 );
-}
-
-static int push( mlt_parser this, int multitrack, int track, int position )
-{
- mlt_properties properties = mlt_parser_properties( this );
- mlt_deque stack = mlt_properties_get_data( properties, "stack", NULL );
- track_info *info = malloc( sizeof( track_info ) );
- info->multitrack = multitrack;
- info->track = track;
- info->position = position;
- info->length = 0;
- info->offset = 0;
- return mlt_deque_push_back( stack, info );
-}
-
-static track_info *pop( mlt_parser this )
-{
- mlt_properties properties = mlt_parser_properties( this );
- mlt_deque stack = mlt_properties_get_data( properties, "stack", NULL );
- return mlt_deque_pop_back( stack );
-}
-
-static track_info *peek( mlt_parser this )
-{
- mlt_properties properties = mlt_parser_properties( this );
- mlt_deque stack = mlt_properties_get_data( properties, "stack", NULL );
- return mlt_deque_peek_back( stack );
-}
-
-static int on_start_multitrack( mlt_parser this, mlt_multitrack object )
-{
- track_info *info = peek( this );
- return push( this, info->multitrack ++, info->track, info->position );
-}
-
-static int on_start_track( mlt_parser this )
-{
- track_info *info = peek( this );
- info->position -= info->offset;
- info->length -= info->offset;
- return push( this, info->multitrack, info->track ++, info->position );
-}
-
-static int on_start_producer( mlt_parser this, mlt_producer object )
-{
- mlt_properties properties = mlt_parser_properties( this );
- mlt_properties producers = mlt_properties_get_data( properties, "producers", NULL );
- mlt_producer parent = mlt_producer_cut_parent( object );
- if ( mlt_service_identify( ( mlt_service )mlt_producer_cut_parent( object ) ) == producer_type && mlt_producer_is_cut( object ) )
- {
- int ref_count = 0;
- clip_references *old_refs = NULL;
- clip_references *refs = NULL;
- char key[ 50 ];
- int count = 0;
- track_info *info = peek( this );
- sprintf( key, "%p", parent );
- mlt_properties_get_data( producers, key, &count );
- mlt_properties_set_data( producers, key, parent, ++ count, NULL, NULL );
- old_refs = mlt_properties_get_data( properties, key, &ref_count );
- refs = malloc( ( ref_count + 1 ) * sizeof( clip_references ) );
- if ( old_refs != NULL )
- memcpy( refs, old_refs, ref_count * sizeof( clip_references ) );
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( object ), "_clone", -1 );
- refs[ ref_count ].cut = object;
- refs[ ref_count ].start = info->position;
- refs[ ref_count ].end = info->position + mlt_producer_get_playtime( object ) - 1;
- mlt_properties_set_data( properties, key, refs, ++ ref_count, free, NULL );
- info->position += mlt_producer_get_playtime( object );
- info->length += mlt_producer_get_playtime( object );
- }
- return 0;
-}
-
-static int on_end_track( mlt_parser this )
-{
- track_info *track = pop( this );
- track_info *multi = peek( this );
- multi->length += track->length;
- multi->position += track->length;
- multi->offset = track->length;
- free( track );
- return 0;
-}
-
-static int on_end_multitrack( mlt_parser this, mlt_multitrack object )
-{
- track_info *multi = pop( this );
- track_info *track = peek( this );
- track->position += multi->length;
- track->length += multi->length;
- free( multi );
- return 0;
-}
-
-/** Optimise for overlapping cuts from the same clip.
- *
- * \todo learn more about this
- * \public \memberof mlt_producer_s
- * \param this a producer
- * \return true if there was an error
- */
-
-int mlt_producer_optimise( mlt_producer this )
-{
- int error = 1;
- mlt_parser parser = mlt_parser_new( );
- if ( parser != NULL )
- {
- int i = 0, j = 0, k = 0;
- mlt_properties properties = mlt_parser_properties( parser );
- mlt_properties producers = mlt_properties_new( );
- mlt_deque stack = mlt_deque_init( );
- mlt_properties_set_data( properties, "producers", producers, 0, ( mlt_destructor )mlt_properties_close, NULL );
- mlt_properties_set_data( properties, "stack", stack, 0, ( mlt_destructor )mlt_deque_close, NULL );
- parser->on_start_producer = on_start_producer;
- parser->on_start_track = on_start_track;
- parser->on_end_track = on_end_track;
- parser->on_start_multitrack = on_start_multitrack;
- parser->on_end_multitrack = on_end_multitrack;
- push( parser, 0, 0, 0 );
- mlt_parser_start( parser, MLT_PRODUCER_SERVICE( this ) );
- free( pop( parser ) );
- for ( k = 0; k < mlt_properties_count( producers ); k ++ )
- {
- char *name = mlt_properties_get_name( producers, k );
- int count = 0;
- int clones = 0;
- int max_clones = 0;
- mlt_producer producer = mlt_properties_get_data( producers, name, &count );
- if ( producer != NULL && count > 1 )
- {
- clip_references *refs = mlt_properties_get_data( properties, name, &count );
- for ( i = 0; i < count; i ++ )
- {
- clones = 0;
- for ( j = i + 1; j < count; j ++ )
- {
- if ( intersect( &refs[ i ], &refs[ j ] ) )
- {
- clones ++;
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( refs[ j ].cut ), "_clone", clones );
- }
- }
- if ( clones > max_clones )
- max_clones = clones;
- }
-
- for ( i = 0; i < count; i ++ )
- {
- mlt_producer cut = refs[ i ].cut;
- if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone" ) == -1 )
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 );
- }
-
- mlt_producer_set_clones( producer, max_clones );
- }
- else if ( producer != NULL )
- {
- clip_references *refs = mlt_properties_get_data( properties, name, &count );
- for ( i = 0; i < count; i ++ )
- {
- mlt_producer cut = refs[ i ].cut;
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( cut ), "_clone", 0 );
- }
- mlt_producer_set_clones( producer, 0 );
- }
- }
- mlt_parser_close( parser );
- }
- return error;
-}
-
-/** Close the producer.
- *
- * Destroys the producer and deallocates its resources managed by its
- * properties list. This will call the close virtual function. Therefore, a
- * subclass that defines its own close function should set its virtual close
- * function to NULL prior to calling this to avoid circular calls.
- *
- * \public \memberof mlt_producer_s
- * \param this a producer
- */
-
-void mlt_producer_close( mlt_producer this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_PRODUCER_PROPERTIES( this ) ) <= 0 )
- {
- this->parent.close = NULL;
-
- if ( this->close != NULL )
- {
- this->close( this->close_object );
- }
- else
- {
- int destroy = mlt_producer_is_cut( this );
-
-#if _MLT_PRODUCER_CHECKS_ == 1
- // Show debug info
- mlt_properties_debug( MLT_PRODUCER_PROPERTIES( this ), "Producer closing", stderr );
-#endif
-
-#ifdef _MLT_PRODUCER_CHECKS_
- // Show current stats - these should match when the app is closed
- mlt_log( MLT_PRODUCER_SERVICE( this ), MLT_LOG_DEBUG, "Producers created %d, destroyed %d\n", producers_created, ++producers_destroyed );
-#endif
-
- mlt_service_close( &this->parent );
-
- if ( destroy )
- free( this );
- }
- }
-}
+++ /dev/null
-/**
- * \file mlt_producer.h
- * \brief abstraction for all producer services
- * \see mlt_producer_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PRODUCER_H_
-#define _MLT_PRODUCER_H_
-
-#include "mlt_service.h"
-#include "mlt_filter.h"
-
-/** \brief Producer abstract service class
- *
- * A producer is a service that generates audio, video, and metadata.
- * Some day it may also generate text (subtitles). This is not to say
- * a producer "synthesizes," rather that is an origin of data within the
- * service network - that could be through synthesis or reading a stream.
- *
- * \extends mlt_service
- * \event \em producer-changed
- * \properties \em mlt_type the name of the service subclass, e.g. mlt_producer
- * \properties \em mlt_service the name of a producer subclass
- * \properties \em _position the current position of the play head, relative to the in point
- * \properties \em _frame the current position of the play head, relative to the beginning of the resource
- * \properties \em _speed the current speed factor, where 1.0 is normal
- * \properties \em aspect_ratio sample aspect ratio
- * \properties \em length the duration of the cut in frames
- * \properties \em eof the end-of-file behavior, one of: pause, continue, loop
- * \properties \em resource the file name, stream address, or the class name in angle brackets
- * \properties \em _cut set if this producer is a "cut" producer
- * \properties \em mlt_mix stores the data for a "mix" producer
- * \properties \em _cut_parent holds a reference to the cut's parent producer
- * \properties \em ignore_points Set this to temporarily disable the in and out points.
- * \properties \em use_clone holds a reference to a clone's producer, as created by mlt_producer_optimise
- * \properties \em _clone is the index of the clone in the list of clones stored on the clone's producer
- * \properties \em _clones is the number of clones of the producer, as created by mlt_producer_optimise
- * \properties \em _clone.{N} holds a reference to the N'th clone of the producer, as created by mlt_producer_optimise
- * \properties \em meta.* holds metadata - there is a loose taxonomy to be defined
- * \properties \em set.* holds properties to set on a frame produced
- * \todo define the media metadata taxonomy
- */
-
-struct mlt_producer_s
-{
- /** A producer is a service. */
- struct mlt_service_s parent;
-
- /** Get a frame of data (virtual function).
- *
- * \param mlt_producer a producer
- * \param mlt_frame_ptr a frame pointer by reference
- * \param int an index
- * \return true if there was an error
- */
- int ( *get_frame )( mlt_producer, mlt_frame_ptr, int );
-
- /** the destructor virtual function */
- mlt_destructor close;
- void *close_object; /**< the object supplied to the close virtual function */
-
- void *local; /**< \private instance object */
- void *child; /**< \private the object of a subclass */
-};
-
-/*
- * Public final methods
- */
-
-#define MLT_PRODUCER_SERVICE( producer ) ( &( producer )->parent )
-#define MLT_PRODUCER_PROPERTIES( producer ) MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) )
-
-extern int mlt_producer_init( mlt_producer self, void *child );
-extern mlt_producer mlt_producer_new( );
-extern mlt_service mlt_producer_service( mlt_producer self );
-extern mlt_properties mlt_producer_properties( mlt_producer self );
-extern int mlt_producer_seek( mlt_producer self, mlt_position position );
-extern mlt_position mlt_producer_position( mlt_producer self );
-extern mlt_position mlt_producer_frame( mlt_producer self );
-extern int mlt_producer_set_speed( mlt_producer self, double speed );
-extern double mlt_producer_get_speed( mlt_producer self );
-extern double mlt_producer_get_fps( mlt_producer self );
-extern int mlt_producer_set_in_and_out( mlt_producer self, mlt_position in, mlt_position out );
-extern int mlt_producer_clear( mlt_producer self );
-extern mlt_position mlt_producer_get_in( mlt_producer self );
-extern mlt_position mlt_producer_get_out( mlt_producer self );
-extern mlt_position mlt_producer_get_playtime( mlt_producer self );
-extern mlt_position mlt_producer_get_length( mlt_producer self );
-extern void mlt_producer_prepare_next( mlt_producer self );
-extern int mlt_producer_attach( mlt_producer self, mlt_filter filter );
-extern int mlt_producer_detach( mlt_producer self, mlt_filter filter );
-extern mlt_filter mlt_producer_filter( mlt_producer self, int index );
-extern mlt_producer mlt_producer_cut( mlt_producer self, int in, int out );
-extern int mlt_producer_is_cut( mlt_producer self );
-extern int mlt_producer_is_mix( mlt_producer self );
-extern int mlt_producer_is_blank( mlt_producer self );
-extern mlt_producer mlt_producer_cut_parent( mlt_producer self );
-extern int mlt_producer_optimise( mlt_producer self );
-extern void mlt_producer_close( mlt_producer self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_profile.c
- * \brief video output definition
- * \see mlt_profile_s
- *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_profile.h"
-#include "mlt_factory.h"
-#include "mlt_properties.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <libgen.h>
-
-
-/** the default subdirectory of the prefix for holding profiles */
-#define PROFILES_DIR "/share/mlt/profiles/"
-
-/** Load a profile from the system folder.
- *
- * The environment variable MLT_PROFILES_PATH overrides the default \p PROFILES_DIR.
- *
- * \private \memberof mlt_profile_s
- * \param name the name of a profile settings file located in the standard location or
- * the full path name to a profile settings file
- * \return a profile or NULL on error
- */
-
-static mlt_profile mlt_profile_select( const char *name )
-{
- char *filename = NULL;
- const char *prefix = getenv( "MLT_PROFILES_PATH" );
- mlt_properties properties = mlt_properties_load( name );
- mlt_profile profile = NULL;
-
- // Try to load from file specification
- if ( properties && mlt_properties_get_int( properties, "width" ) )
- {
- filename = calloc( 1, strlen( name ) + 1 );
- }
- // Load from $prefix/share/mlt/profiles
- else if ( prefix == NULL )
- {
- prefix = PREFIX;
- filename = calloc( 1, strlen( prefix ) + strlen( PROFILES_DIR ) + strlen( name ) + 2 );
- strcpy( filename, prefix );
- if ( filename[ strlen( filename ) - 1 ] != '/' )
- filename[ strlen( filename ) ] = '/';
- strcat( filename, PROFILES_DIR );
- }
- // Use environment variable instead
- else
- {
- filename = calloc( 1, strlen( prefix ) + strlen( name ) + 2 );
- strcpy( filename, prefix );
- if ( filename[ strlen( filename ) - 1 ] != '/' )
- filename[ strlen( filename ) ] = '/';
- }
-
- // Finish loading
- strcat( filename, name );
- profile = mlt_profile_load_file( filename );
-
- // Cleanup
- mlt_properties_close( properties );
- free( filename );
-
- return profile;
-}
-
-/** Construct a profile.
- *
- * This will never return NULL as it uses the dv_pal settings as hard-coded fallback default.
- *
- * \public \memberof mlt_profile_s
- * @param name the name of a profile settings file located in the standard location or
- * the full path name to a profile settings file
- * @return a profile
- */
-
-mlt_profile mlt_profile_init( const char *name )
-{
- mlt_profile profile = NULL;
-
- // Explicit profile by name gets priority over environment variables
- if ( name )
- profile = mlt_profile_select( name );
-
- // Try to load by environment variable
- if ( profile == NULL )
- {
- // MLT_PROFILE is preferred environment variable
- if ( getenv( "MLT_PROFILE" ) )
- profile = mlt_profile_select( getenv( "MLT_PROFILE" ) );
- // MLT_NORMALISATION backwards compatibility
- else if ( getenv( "MLT_NORMALISATION" ) && strcmp( getenv( "MLT_NORMALISATION" ), "PAL" ) )
- profile = mlt_profile_select( "dv_ntsc" );
- else
- profile = mlt_profile_select( "dv_pal" );
-
- // If still not loaded (no profile files), default to PAL
- if ( profile == NULL )
- {
- profile = calloc( 1, sizeof( struct mlt_profile_s ) );
- if ( profile )
- {
- mlt_environment_set( "MLT_PROFILE", "dv_pal" );
- profile->description = strdup( "PAL 4:3 DV or DVD" );
- profile->frame_rate_num = 25;
- profile->frame_rate_den = 1;
- profile->width = 720;
- profile->height = 576;
- profile->progressive = 0;
- profile->sample_aspect_num = 16;
- profile->sample_aspect_den = 15;
- profile->display_aspect_num = 4;
- profile->display_aspect_den = 3;
- }
- }
- }
- return profile;
-}
-
-/** Load a profile from specific file.
- *
- * \public \memberof mlt_profile_s
- * @param file the full path name to a properties file
- * @return a profile or NULL on error
- */
-
-mlt_profile mlt_profile_load_file( const char *file )
-{
- mlt_profile profile = NULL;
-
- // Load the profile as properties
- mlt_properties properties = mlt_properties_load( file );
- if ( properties )
- {
- // Simple check if the profile is valid
- if ( mlt_properties_get_int( properties, "width" ) )
- {
- profile = mlt_profile_load_properties( properties );
-
- // Set MLT_PROFILE to basename
- char *filename = strdup( file );
- mlt_environment_set( "MLT_PROFILE", basename( filename ) );
- free( filename );
- }
- mlt_properties_close( properties );
- }
-
- // Set MLT_NORMALISATION to appease legacy modules
- char *profile_name = mlt_environment( "MLT_PROFILE" );
- if ( profile_name )
- {
- if ( strstr( profile_name, "_ntsc" ) ||
- strstr( profile_name, "_60" ) ||
- strstr( profile_name, "_30" ) )
- {
- mlt_environment_set( "MLT_NORMALISATION", "NTSC" );
- }
- else if ( strstr( profile_name, "_pal" ) ||
- strstr( profile_name, "_50" ) ||
- strstr( profile_name, "_25" ) )
- {
- mlt_environment_set( "MLT_NORMALISATION", "PAL" );
- }
- }
- return profile;
-}
-
-/** Load a profile from a properties object.
- *
- * \public \memberof mlt_profile_s
- * @param properties a properties list
- * @return a profile or NULL if out of memory
- */
-
-mlt_profile mlt_profile_load_properties( mlt_properties properties )
-{
- mlt_profile profile = calloc( 1, sizeof( struct mlt_profile_s ) );
- if ( profile )
- {
- if ( mlt_properties_get( properties, "name" ) )
- mlt_environment_set( "MLT_PROFILE", mlt_properties_get( properties, "name" ) );
- if ( mlt_properties_get( properties, "description" ) )
- profile->description = strdup( mlt_properties_get( properties, "description" ) );
- profile->frame_rate_num = mlt_properties_get_int( properties, "frame_rate_num" );
- profile->frame_rate_den = mlt_properties_get_int( properties, "frame_rate_den" );
- profile->width = mlt_properties_get_int( properties, "width" );
- profile->height = mlt_properties_get_int( properties, "height" );
- profile->progressive = mlt_properties_get_int( properties, "progressive" );
- profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
- profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
- profile->display_aspect_num = mlt_properties_get_int( properties, "display_aspect_num" );
- profile->display_aspect_den = mlt_properties_get_int( properties, "display_aspect_den" );
- }
- return profile;
-}
-
-/** Load an anonymous profile from string.
- *
- * \public \memberof mlt_profile_s
- * @param string a newline-delimited list of properties as name=value pairs
- * @return a profile or NULL if out of memory
- */
-
-mlt_profile mlt_profile_load_string( const char *string )
-{
- mlt_properties properties = mlt_properties_new();
- if ( properties )
- {
- const char *p = string;
- while ( p )
- {
- if ( strcmp( p, "" ) && p[ 0 ] != '#' )
- mlt_properties_parse( properties, p );
- p = strchr( p, '\n' );
- if ( p ) p++;
- }
- }
- return mlt_profile_load_properties( properties );
-}
-
-/** Get the video frame rate as a floating point value.
- *
- * \public \memberof mlt_profile_s
- * @param aprofile a profile
- * @return the frame rate
- */
-
-double mlt_profile_fps( mlt_profile aprofile )
-{
- if ( aprofile )
- return ( double ) aprofile->frame_rate_num / aprofile->frame_rate_den;
- else
- return 0;
-}
-
-/** Get the sample aspect ratio as a floating point value.
- *
- * \public \memberof mlt_profile_s
- * @param aprofile a profile
- * @return the pixel aspect ratio
- */
-
-double mlt_profile_sar( mlt_profile aprofile )
-{
- if ( aprofile )
- return ( double ) aprofile->sample_aspect_num / aprofile->sample_aspect_den;
- else
- return 0;
-}
-
-/** Get the display aspect ratio as floating point value.
- *
- * \public \memberof mlt_profile_s
- * @param aprofile a profile
- * @return the image aspect ratio
- */
-
-double mlt_profile_dar( mlt_profile aprofile )
-{
- if ( aprofile )
- return ( double ) aprofile->display_aspect_num / aprofile->display_aspect_den;
- else
- return 0;
-}
-
-/** Free up the global profile resources.
- *
- * \public \memberof mlt_profile_s
- * @param profile a profile
- */
-
-void mlt_profile_close( mlt_profile profile )
-{
- if ( profile )
- {
- if ( profile->description )
- free( profile->description );
- profile->description = NULL;
- free( profile );
- profile = NULL;
- }
-}
+++ /dev/null
-/**
- * \file mlt_profile.h
- * \brief video output definition
- * \see mlt_profile_s
- *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PROFILE_H
-#define _MLT_PROFILE_H
-
-#include "mlt_types.h"
-
-/** \brief Profile class
- *
- */
-
-struct mlt_profile_s
-{
- char* description; /**< a brief description suitable as a label in UI menu */
- int frame_rate_num; /**< the numerator of the video frame rate */
- int frame_rate_den; /**< the denominator of the video frame rate */
- int width; /**< the horizontal resolution of the video */
- int height; /**< the vertical resolution of the video */
- int progressive; /**< a flag to indicate if the video is progressive scan, interlace if not set */
- int sample_aspect_num; /**< the numerator of the pixel aspect ratio */
- int sample_aspect_den; /**< the denominator of the pixel aspect ratio */
- int display_aspect_num; /**< the numerator of the image aspect ratio in case it can not be simply derived (e.g. ITU-R 601) */
- int display_aspect_den; /**< the denominator of the image aspect ratio in case it can not be simply derived (e.g. ITU-R 601) */
-};
-
-extern mlt_profile mlt_profile_init( const char *name );
-extern mlt_profile mlt_profile_load_file( const char *file );
-extern mlt_profile mlt_profile_load_properties( mlt_properties properties );
-extern mlt_profile mlt_profile_load_string( const char *string );
-extern double mlt_profile_fps( mlt_profile profile );
-extern double mlt_profile_sar( mlt_profile profile );
-extern double mlt_profile_dar( mlt_profile profile );
-extern void mlt_profile_close( mlt_profile profile );
-#endif
+++ /dev/null
-/**
- * \file mlt_properties.c
- * \brief Properties class definition
- * \see mlt_properties_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_properties.h"
-#include "mlt_property.h"
-#include "mlt_deque.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <dirent.h>
-
-
-/** \brief private implementation of the property list */
-
-typedef struct
-{
- int hash[ 199 ];
- char **name;
- mlt_property *value;
- int count;
- int size;
- mlt_properties mirror;
- int ref_count;
- pthread_mutex_t mutex;
-}
-property_list;
-
-/* Memory leak checks */
-
-//#define _MLT_PROPERTY_CHECKS_ 2
-#ifdef _MLT_PROPERTY_CHECKS_
-static int properties_created = 0;
-static int properties_destroyed = 0;
-#endif
-
-/** Initialize a properties object that was already allocated.
- *
- * This does allocate its ::property_list, and it adds a reference count.
- * \public \memberof mlt_properties_s
- * \param this the properties structure to initialize
- * \param child an opaque pointer to a subclass object
- * \return true if failed
- */
-
-int mlt_properties_init( mlt_properties this, void *child )
-{
- if ( this != NULL )
- {
-#ifdef _MLT_PROPERTY_CHECKS_
- // Increment number of properties created
- properties_created ++;
-#endif
-
- // NULL all methods
- memset( this, 0, sizeof( struct mlt_properties_s ) );
-
- // Assign the child of the object
- this->child = child;
-
- // Allocate the local structure
- this->local = calloc( sizeof( property_list ), 1 );
-
- // Increment the ref count
- ( ( property_list * )this->local )->ref_count = 1;
- pthread_mutex_init( &( ( property_list * )this->local )->mutex, NULL );;
- }
-
- // Check that initialisation was successful
- return this != NULL && this->local == NULL;
-}
-
-/** Create a properties object.
- *
- * This allocates the properties structure and calls mlt_properties_init() on it.
- * Free the properties object with mlt_properties_close().
- * \public \memberof mlt_properties_s
- * \return a new properties object
- */
-
-mlt_properties mlt_properties_new( )
-{
- // Construct a standalone properties object
- mlt_properties this = calloc( sizeof( struct mlt_properties_s ), 1 );
-
- // Initialise this
- mlt_properties_init( this, NULL );
-
- // Return the pointer
- return this;
-}
-
-/** Create a properties object by reading a .properties text file.
- *
- * Free the properties object with mlt_properties_close().
- * \deprecated Please start using mlt_properties_parse_yaml().
- * \public \memberof mlt_properties_s
- * \param filename a string contain the absolute file name
- * \return a new properties object
- */
-
-mlt_properties mlt_properties_load( const char *filename )
-{
- // Construct a standalone properties object
- mlt_properties this = mlt_properties_new( );
-
- if ( this != NULL )
- {
- // Open the file
- FILE *file = fopen( filename, "r" );
-
- // Load contents of file
- if ( file != NULL )
- {
- // Temp string
- char temp[ 1024 ];
- char last[ 1024 ] = "";
-
- // Read each string from the file
- while( fgets( temp, 1024, file ) )
- {
- // Chomp the string
- temp[ strlen( temp ) - 1 ] = '\0';
-
- // Check if the line starts with a .
- if ( temp[ 0 ] == '.' )
- {
- char temp2[ 1024 ];
- sprintf( temp2, "%s%s", last, temp );
- strcpy( temp, temp2 );
- }
- else if ( strchr( temp, '=' ) )
- {
- strcpy( last, temp );
- *( strchr( last, '=' ) ) = '\0';
- }
-
- // Parse and set the property
- if ( strcmp( temp, "" ) && temp[ 0 ] != '#' )
- mlt_properties_parse( this, temp );
- }
-
- // Close the file
- fclose( file );
- }
- }
-
- // Return the pointer
- return this;
-}
-
-/** Generate a hash key.
- *
- * \private \memberof mlt_properties_s
- * \param name a string
- * \return an integer
- */
-
-static inline int generate_hash( const char *name )
-{
- int hash = 0;
- int i = 1;
- while ( *name )
- hash = ( hash + ( i ++ * ( *name ++ & 31 ) ) ) % 199;
- return hash;
-}
-
-/** Copy a serializable property to properties list that is mirroring this one.
- *
- * Special case - when a container (such as fezzik) is protecting another
- * producer, we need to ensure that properties are passed through to the
- * real producer.
- * \private \memberof mlt_properties_s
- * \param this a properties list
- * \param name the name of the property to copy
- */
-
-static inline void mlt_properties_do_mirror( mlt_properties this, const char *name )
-{
- property_list *list = this->local;
- if ( list->mirror != NULL )
- {
- char *value = mlt_properties_get( this, name );
- if ( value != NULL )
- mlt_properties_set( list->mirror, name, value );
- }
-}
-
-/** Increment the reference count.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \return the new reference count
- */
-
-int mlt_properties_inc_ref( mlt_properties this )
-{
- int result = 0;
- if ( this != NULL )
- {
- property_list *list = this->local;
- pthread_mutex_lock( &list->mutex );
- result = ++ list->ref_count;
- pthread_mutex_unlock( &list->mutex );
- }
- return result;
-}
-
-/** Decrement the reference count.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \return the new reference count
- */
-
-int mlt_properties_dec_ref( mlt_properties this )
-{
- int result = 0;
- if ( this != NULL )
- {
- property_list *list = this->local;
- pthread_mutex_lock( &list->mutex );
- result = -- list->ref_count;
- pthread_mutex_unlock( &list->mutex );
- }
- return result;
-}
-
-/** Get the reference count.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \return the current reference count
- */
-
-int mlt_properties_ref_count( mlt_properties this )
-{
- if ( this != NULL )
- {
- property_list *list = this->local;
- return list->ref_count;
- }
- return 0;
-}
-
-/** Set a properties list to be a mirror copy of another.
- *
- * Note that this does not copy all existing properties. Rather, you must
- * call this before setting the properties that you wish to copy.
- * \public \memberof mlt_properties_s
- * \param that the properties which will receive copies of the properties as they are set.
- * \param this the properties to mirror
- */
-
-void mlt_properties_mirror( mlt_properties this, mlt_properties that )
-{
- property_list *list = this->local;
- list->mirror = that;
-}
-
-/** Copy all serializable properties to another properties list.
- *
- * \public \memberof mlt_properties_s
- * \param this The properties to copy to
- * \param that The properties to copy from
- * \return false
- */
-
-int mlt_properties_inherit( mlt_properties this, mlt_properties that )
-{
- int count = mlt_properties_count( that );
- int i = 0;
- for ( i = 0; i < count; i ++ )
- {
- char *value = mlt_properties_get_value( that, i );
- if ( value != NULL )
- {
- char *name = mlt_properties_get_name( that, i );
- mlt_properties_set( this, name, value );
- }
- }
- return 0;
-}
-
-/** Pass all serializable properties that match a prefix to another properties object
- *
- * \public \memberof mlt_properties_s
- * \param this the properties to copy to
- * \param that The properties to copy from
- * \param prefix the property names to match (required)
- * \return false
- */
-
-int mlt_properties_pass( mlt_properties this, mlt_properties that, const char *prefix )
-{
- int count = mlt_properties_count( that );
- int length = strlen( prefix );
- int i = 0;
- for ( i = 0; i < count; i ++ )
- {
- char *name = mlt_properties_get_name( that, i );
- if ( !strncmp( name, prefix, length ) )
- {
- char *value = mlt_properties_get_value( that, i );
- if ( value != NULL )
- mlt_properties_set( this, name + length, value );
- }
- }
- return 0;
-}
-
-/** Locate a property by name.
- *
- * \private \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to lookup by name
- * \return the property or NULL for failure
- */
-
-static inline mlt_property mlt_properties_find( mlt_properties this, const char *name )
-{
- property_list *list = this->local;
- mlt_property value = NULL;
- int key = generate_hash( name );
- int i = list->hash[ key ] - 1;
-
- if ( i >= 0 )
- {
- // Check if we're hashed
- if ( list->count > 0 &&
- name[ 0 ] == list->name[ i ][ 0 ] &&
- !strcmp( list->name[ i ], name ) )
- value = list->value[ i ];
-
- // Locate the item
- for ( i = list->count - 1; value == NULL && i >= 0; i -- )
- if ( name[ 0 ] == list->name[ i ][ 0 ] && !strcmp( list->name[ i ], name ) )
- value = list->value[ i ];
- }
-
- return value;
-}
-
-/** Add a new property.
- *
- * \private \memberof mlt_properties_s
- * \param this a properties list
- * \param name the name of the new property
- * \return the new property
- */
-
-static mlt_property mlt_properties_add( mlt_properties this, const char *name )
-{
- property_list *list = this->local;
- int key = generate_hash( name );
-
- // Check that we have space and resize if necessary
- if ( list->count == list->size )
- {
- list->size += 50;
- list->name = realloc( list->name, list->size * sizeof( const char * ) );
- list->value = realloc( list->value, list->size * sizeof( mlt_property ) );
- }
-
- // Assign name/value pair
- list->name[ list->count ] = strdup( name );
- list->value[ list->count ] = mlt_property_init( );
-
- // Assign to hash table
- if ( list->hash[ key ] == 0 )
- list->hash[ key ] = list->count + 1;
-
- // Return and increment count accordingly
- return list->value[ list->count ++ ];
-}
-
-/** Fetch a property by name and add one if not found.
- *
- * \private \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to lookup or add
- * \return the property
- */
-
-static mlt_property mlt_properties_fetch( mlt_properties this, const char *name )
-{
- // Try to find an existing property first
- mlt_property property = mlt_properties_find( this, name );
-
- // If it wasn't found, create one
- if ( property == NULL )
- property = mlt_properties_add( this, name );
-
- // Return the property
- return property;
-}
-
-/** Copy a property to another properties list.
- *
- * \public \memberof mlt_properties_s
- * \author Zach <zachary.drew@gmail.com>
- * \param this the properties to copy to
- * \param that the properties to copy from
- * \param name the name of the property to copy
- */
-
-void mlt_properties_pass_property( mlt_properties this, mlt_properties that, const char *name )
-{
- // Make sure the source property isn't null.
- mlt_property that_prop = mlt_properties_find( that, name );
- if( that_prop == NULL )
- return;
-
- mlt_property_pass( mlt_properties_fetch( this, name ), that_prop );
-}
-
-/** Copy all properties specified in a comma-separated list to another properties list.
- *
- * White space is also a delimiter.
- * \public \memberof mlt_properties_s
- * \author Zach <zachary.drew@gmail.com>
- * \param this the properties to copy to
- * \param that the properties to copy from
- * \param list a delimited list of property names
- * \return false
- */
-
-
-int mlt_properties_pass_list( mlt_properties this, mlt_properties that, const char *list )
-{
- char *props = strdup( list );
- char *ptr = props;
- const char *delim = " ,\t\n"; // Any combination of spaces, commas, tabs, and newlines
- int count, done = 0;
-
- while( !done )
- {
- count = strcspn( ptr, delim );
-
- if( ptr[count] == '\0' )
- done = 1;
- else
- ptr[count] = '\0'; // Make it a real string
-
- mlt_properties_pass_property( this, that, ptr );
-
- ptr += count + 1;
- ptr += strspn( ptr, delim );
- }
-
- free( props );
-
- return 0;
-}
-
-
-/** Set a property to a string.
- *
- * This makes a copy of the string value you supply.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value the property's new value
- * \return true if error
- */
-
-int mlt_properties_set( mlt_properties this, const char *name, const char *value )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property == NULL )
- {
- mlt_log( NULL, MLT_LOG_FATAL, "Whoops - %s not found (should never occur)\n", name );
- }
- else if ( value == NULL )
- {
- error = mlt_property_set_string( property, value );
- mlt_properties_do_mirror( this, name );
- }
- else if ( *value != '@' )
- {
- error = mlt_property_set_string( property, value );
- mlt_properties_do_mirror( this, name );
- }
- else if ( value[ 0 ] == '@' )
- {
- double total = 0;
- double current = 0;
- char id[ 255 ];
- char op = '+';
-
- value ++;
-
- while ( *value != '\0' )
- {
- int length = strcspn( value, "+-*/" );
-
- // Get the identifier
- strncpy( id, value, length );
- id[ length ] = '\0';
- value += length;
-
- // Determine the value
- if ( isdigit( id[ 0 ] ) )
- current = atof( id );
- else
- current = mlt_properties_get_double( this, id );
-
- // Apply the operation
- switch( op )
- {
- case '+':
- total += current;
- break;
- case '-':
- total -= current;
- break;
- case '*':
- total *= current;
- break;
- case '/':
- total = total / current;
- break;
- }
-
- // Get the next op
- op = *value != '\0' ? *value ++ : ' ';
- }
-
- error = mlt_property_set_double( property, total );
- mlt_properties_do_mirror( this, name );
- }
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Set or default a property to a string.
- *
- * This makes a copy of the string value you supply.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value the string value to set or NULL to use the default
- * \param def the default string if value is NULL
- * \return true if error
- */
-
-int mlt_properties_set_or_default( mlt_properties this, const char *name, const char *value, const char *def )
-{
- return mlt_properties_set( this, name, value == NULL ? def : value );
-}
-
-/** Get a string value by name.
- *
- * Do not free the returned string. It's lifetime is controlled by the property
- * and this properties object.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \return the property's string value or NULL if it does not exist
- */
-
-char *mlt_properties_get( mlt_properties this, const char *name )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? NULL : mlt_property_get_string( value );
-}
-
-/** Get a property name by index.
- *
- * Do not free the returned string.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param index the numeric index of the property
- * \return the name of the property or NULL if index is out of range
- */
-
-char *mlt_properties_get_name( mlt_properties this, int index )
-{
- property_list *list = this->local;
- if ( index >= 0 && index < list->count )
- return list->name[ index ];
- return NULL;
-}
-
-/** Get a property's string value by index.
- *
- * Do not free the returned string.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param index the numeric index of the property
- * \return the property value as a string or NULL if the index is out of range
- */
-
-char *mlt_properties_get_value( mlt_properties this, int index )
-{
- property_list *list = this->local;
- if ( index >= 0 && index < list->count )
- return mlt_property_get_string( list->value[ index ] );
- return NULL;
-}
-
-/** Get a data value by index.
- *
- * Do not free the returned pointer if you supplied a destructor function when you
- * set this property.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param index the numeric index of the property
- * \param[out] size the size of the binary data in bytes or NULL if the index is out of range
- */
-
-void *mlt_properties_get_data_at( mlt_properties this, int index, int *size )
-{
- property_list *list = this->local;
- if ( index >= 0 && index < list->count )
- return mlt_property_get_data( list->value[ index ], size );
- return NULL;
-}
-
-/** Return the number of items in the list.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \return the number of property objects
- */
-
-int mlt_properties_count( mlt_properties this )
-{
- property_list *list = this->local;
- return list->count;
-}
-
-/** Set a value by parsing a name=value string.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param namevalue a string containing name and value delimited by '='
- * \return true if there was an error
- */
-
-int mlt_properties_parse( mlt_properties this, const char *namevalue )
-{
- char *name = strdup( namevalue );
- char *value = NULL;
- int error = 0;
- char *ptr = strchr( name, '=' );
-
- if ( ptr )
- {
- *( ptr ++ ) = '\0';
-
- if ( *ptr != '\"' )
- {
- value = strdup( ptr );
- }
- else
- {
- ptr ++;
- value = strdup( ptr );
- if ( value != NULL && value[ strlen( value ) - 1 ] == '\"' )
- value[ strlen( value ) - 1 ] = '\0';
- }
- }
- else
- {
- value = strdup( "" );
- }
-
- error = mlt_properties_set( this, name, value );
-
- free( name );
- free( value );
-
- return error;
-}
-
-/** Get an integer associated to the name.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \return The integer value, 0 if not found (which may also be a legitimate value)
- */
-
-int mlt_properties_get_int( mlt_properties this, const char *name )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_int( value );
-}
-
-/** Set a property to an integer value.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value the integer
- * \return true if error
- */
-
-int mlt_properties_set_int( mlt_properties this, const char *name, int value )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property != NULL )
- {
- error = mlt_property_set_int( property, value );
- mlt_properties_do_mirror( this, name );
- }
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Get a 64-bit integer associated to the name.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \return the integer value, 0 if not found (which may also be a legitimate value)
- */
-
-int64_t mlt_properties_get_int64( mlt_properties this, const char *name )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_int64( value );
-}
-
-/** Set a property to a 64-bit integer value.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value the integer
- * \return true if error
- */
-
-int mlt_properties_set_int64( mlt_properties this, const char *name, int64_t value )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property != NULL )
- {
- error = mlt_property_set_int64( property, value );
- mlt_properties_do_mirror( this, name );
- }
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Get a floating point value associated to the name.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \return the floating point, 0 if not found (which may also be a legitimate value)
- */
-
-double mlt_properties_get_double( mlt_properties this, const char *name )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_double( value );
-}
-
-/** Set a property to a floating point value.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value the floating point value
- * \return true if error
- */
-
-int mlt_properties_set_double( mlt_properties this, const char *name, double value )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property != NULL )
- {
- error = mlt_property_set_double( property, value );
- mlt_properties_do_mirror( this, name );
- }
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Get a position value associated to the name.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \return the position, 0 if not found (which may also be a legitimate value)
- */
-
-mlt_position mlt_properties_get_position( mlt_properties this, const char *name )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? 0 : mlt_property_get_position( value );
-}
-
-/** Set a property to a position value.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \param value the position
- * \return true if error
- */
-
-int mlt_properties_set_position( mlt_properties this, const char *name, mlt_position value )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property != NULL )
- {
- error = mlt_property_set_position( property, value );
- mlt_properties_do_mirror( this, name );
- }
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Get a binary data value associated to the name.
- *
- * Do not free the returned pointer if you supplied a destructor function
- * when you set this property.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to get
- * \param[out] length The size of the binary data in bytes, if available (often it is not, you should know)
- */
-
-void *mlt_properties_get_data( mlt_properties this, const char *name, int *length )
-{
- mlt_property value = mlt_properties_find( this, name );
- return value == NULL ? NULL : mlt_property_get_data( value, length );
-}
-
-/** Store binary data as a property.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param name the property to set
- * \param value an opaque pointer to binary data
- * \param length the size of the binary data in bytes (optional)
- * \param destroy a function to dellacate the binary data when the property is closed (optional)
- * \param serialise a function that can serialize the binary data as text (optional)
- * \return true if error
- */
-
-int mlt_properties_set_data( mlt_properties this, const char *name, void *value, int length, mlt_destructor destroy, mlt_serialiser serialise )
-{
- int error = 1;
-
- // Fetch the property to work with
- mlt_property property = mlt_properties_fetch( this, name );
-
- // Set it if not NULL
- if ( property != NULL )
- error = mlt_property_set_data( property, value, length, destroy, serialise );
-
- mlt_events_fire( this, "property-changed", name, NULL );
-
- return error;
-}
-
-/** Rename a property.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param source the property to rename
- * \param dest the new name
- * \return true if the name is already in use
- */
-
-int mlt_properties_rename( mlt_properties this, const char *source, const char *dest )
-{
- mlt_property value = mlt_properties_find( this, dest );
-
- if ( value == NULL )
- {
- property_list *list = this->local;
- int i = 0;
-
- // Locate the item
- for ( i = 0; i < list->count; i ++ )
- {
- if ( !strcmp( list->name[ i ], source ) )
- {
- free( list->name[ i ] );
- list->name[ i ] = strdup( dest );
- list->hash[ generate_hash( dest ) ] = i + 1;
- break;
- }
- }
- }
-
- return value != NULL;
-}
-
-/** Dump the properties to a file handle.
- *
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param output a file handle
- */
-
-void mlt_properties_dump( mlt_properties this, FILE *output )
-{
- property_list *list = this->local;
- int i = 0;
- for ( i = 0; i < list->count; i ++ )
- if ( mlt_properties_get( this, list->name[ i ] ) != NULL )
- fprintf( output, "%s=%s\n", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) );
-}
-
-/** Output the properties to a file handle.
- *
- * This version includes reference counts and does not put each property on a new line.
- * \public \memberof mlt_properties_s
- * \param this a properties pointer
- * \param title a string to preface the output
- * \param output a file handle
- */
-void mlt_properties_debug( mlt_properties this, const char *title, FILE *output )
-{
- if ( output == NULL ) output = stderr;
- fprintf( output, "%s: ", title );
- if ( this != NULL )
- {
- property_list *list = this->local;
- int i = 0;
- fprintf( output, "[ ref=%d", list->ref_count );
- for ( i = 0; i < list->count; i ++ )
- if ( mlt_properties_get( this, list->name[ i ] ) != NULL )
- fprintf( output, ", %s=%s", list->name[ i ], mlt_properties_get( this, list->name[ i ] ) );
- else
- fprintf( output, ", %s=%p", list->name[ i ], mlt_properties_get_data( this, list->name[ i ], NULL ) );
- fprintf( output, " ]" );
- }
- fprintf( output, "\n" );
-}
-
-/** Save the properties to a file by name.
- *
- * This uses the dump format - one line per property.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param filename the name of a file to create or overwrite
- * \return true if there was an error
- */
-
-int mlt_properties_save( mlt_properties this, const char *filename )
-{
- int error = 1;
- FILE *f = fopen( filename, "w" );
- if ( f != NULL )
- {
- mlt_properties_dump( this, f );
- fclose( f );
- error = 0;
- }
- return error;
-}
-
-/* This is a very basic cross platform fnmatch replacement - it will fail in
- * many cases, but for the basic *.XXX and YYY*.XXX, it will work ok.
- */
-
-/** Test whether a filename or pathname matches a shell-style pattern.
- *
- * \private \memberof mlt_properties_s
- * \param wild a string containing a wildcard pattern
- * \param file the name of a file to test against
- * \return true if the file name matches the wildcard pattern
- */
-
-static int mlt_fnmatch( const char *wild, const char *file )
-{
- int f = 0;
- int w = 0;
-
- while( f < strlen( file ) && w < strlen( wild ) )
- {
- if ( wild[ w ] == '*' )
- {
- w ++;
- if ( w == strlen( wild ) )
- f = strlen( file );
- while ( f != strlen( file ) && tolower( file[ f ] ) != tolower( wild[ w ] ) )
- f ++;
- }
- else if ( wild[ w ] == '?' || tolower( file[ f ] ) == tolower( wild[ w ] ) )
- {
- f ++;
- w ++;
- }
- else if ( wild[ 0 ] == '*' )
- {
- w = 0;
- }
- else
- {
- return 0;
- }
- }
-
- return strlen( file ) == f && strlen( wild ) == w;
-}
-
-/** Compare the string or serialized value of two properties.
- *
- * \private \memberof mlt_properties_s
- * \param this a property
- * \param that a property
- * \return < 0 if 'this' less than 'that', 0 if equal, or > 0 if 'this' is greater than 'that'
- */
-
-static int mlt_compare( const void *this, const void *that )
-{
- return strcmp( mlt_property_get_string( *( const mlt_property * )this ), mlt_property_get_string( *( const mlt_property * )that ) );
-}
-
-/** Get the contents of a directory.
- *
- * Obtains an optionally sorted list of the files found in a directory with a specific wild card.
- * Entries in the list have a numeric name (running from 0 to count - 1). Only values change
- * position if sort is enabled. Designed to be posix compatible (linux, os/x, mingw etc).
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \param dirname the name of the directory
- * \param pattern a wildcard pattern to filter the directory listing
- * \param sort Do you want to sort the directory listing?
- * \return the number of items in the directory listing
- */
-
-int mlt_properties_dir_list( mlt_properties this, const char *dirname, const char *pattern, int sort )
-{
- DIR *dir = opendir( dirname );
-
- if ( dir )
- {
- char key[ 20 ];
- struct dirent *de = readdir( dir );
- char fullname[ 1024 ];
- while( de != NULL )
- {
- sprintf( key, "%d", mlt_properties_count( this ) );
- snprintf( fullname, 1024, "%s/%s", dirname, de->d_name );
- if ( pattern == NULL )
- mlt_properties_set( this, key, fullname );
- else if ( de->d_name[ 0 ] != '.' && mlt_fnmatch( pattern, de->d_name ) )
- mlt_properties_set( this, key, fullname );
- de = readdir( dir );
- }
-
- closedir( dir );
- }
-
- if ( sort && mlt_properties_count( this ) )
- {
- property_list *list = this->local;
- qsort( list->value, mlt_properties_count( this ), sizeof( mlt_property ), mlt_compare );
- }
-
- return mlt_properties_count( this );
-}
-
-/** Close a properties object.
- *
- * Deallocates the properties object and everything it contains.
- * \public \memberof mlt_properties_s
- * \param this a properties object
- */
-
-void mlt_properties_close( mlt_properties this )
-{
- if ( this != NULL && mlt_properties_dec_ref( this ) <= 0 )
- {
- if ( this->close != NULL )
- {
- this->close( this->close_object );
- }
- else
- {
- property_list *list = this->local;
- int index = 0;
-
-#if _MLT_PROPERTY_CHECKS_ == 1
- // Show debug info
- mlt_properties_debug( this, "Closing", stderr );
-#endif
-
-#ifdef _MLT_PROPERTY_CHECKS_
- // Increment destroyed count
- properties_destroyed ++;
-
- // Show current stats - these should match when the app is closed
- mlt_log( NULL, MLT_LOG_DEBUG, "Created %d, destroyed %d\n", properties_created, properties_destroyed );
-#endif
-
- // Clean up names and values
- for ( index = list->count - 1; index >= 0; index -- )
- {
- free( list->name[ index ] );
- mlt_property_close( list->value[ index ] );
- }
-
- // Clear up the list
- pthread_mutex_destroy( &list->mutex );
- free( list->name );
- free( list->value );
- free( list );
-
- // Free this now if this has no child
- if ( this->child == NULL )
- free( this );
- }
- }
-}
-
-/** Determine if the properties list is really just a sequence or ordered list.
- *
- * \public \memberof mlt_properties_s
- * \param properties a properties list
- * \return true if all of the property names are numeric (a sequence)
- */
-
-int mlt_properties_is_sequence( mlt_properties properties )
-{
- int i;
- int n = mlt_properties_count( properties );
- for ( i = 0; i < n; i++ )
- if ( ! isdigit( mlt_properties_get_name( properties, i )[0] ) )
- return 0;
- return 1;
-}
-
-/** \brief YAML Tiny Parser context structure
- *
- * YAML is a nifty text format popular in the Ruby world as a cleaner,
- * less verbose alternative to XML. See this Wikipedia topic for an overview:
- * http://en.wikipedia.org/wiki/YAML
- * The YAML specification is at:
- * http://yaml.org/
- * YAML::Tiny is a Perl module that specifies a subset of YAML that we are
- * using here (for the same reasons):
- * http://search.cpan.org/~adamk/YAML-Tiny-1.25/lib/YAML/Tiny.pm
- * \private
- */
-
-struct yaml_parser_context
-{
- mlt_deque stack;
- unsigned int level;
- unsigned int index;
- char block;
- char *block_name;
- unsigned int block_indent;
-
-};
-typedef struct yaml_parser_context *yaml_parser;
-
-/** Remove spaces from the left side of a string.
- *
- * \param s the string to trim
- * \return the number of characters removed
- */
-
-static unsigned int ltrim( char **s )
-{
- unsigned int i = 0;
- char *c = *s;
- int n = strlen( c );
- for ( i = 0; i < n && *c == ' '; i++, c++ );
- *s = c;
- return i;
-}
-
-/** Remove spaces from the right side of a string.
- *
- * \param s the string to trim
- * \return the number of characters removed
- */
-
-static unsigned int rtrim( char *s )
-{
- int n = strlen( s );
- int i;
- for ( i = n; i > 0 && s[i - 1] == ' '; --i )
- s[i - 1] = 0;
- return n - i;
-}
-
-/** Parse a line of YAML Tiny.
- *
- * Adds a property if needed.
- * \private \memberof yaml_parser_context
- * \param context a YAML Tiny Parser context
- * \param namevalue a line of YAML Tiny
- * \return true if there was an error
- */
-
-static int parse_yaml( yaml_parser context, const char *namevalue )
-{
- char *name_ = strdup( namevalue );
- char *name = name_;
- char *value = NULL;
- int error = 0;
- char *ptr = strchr( name, ':' );
- unsigned int indent = ltrim( &name );
- mlt_properties properties = mlt_deque_peek_front( context->stack );
-
- // Ascending one more levels in the tree
- if ( indent < context->level )
- {
- unsigned int i;
- unsigned int n = ( context->level - indent ) / 2;
- for ( i = 0; i < n; i++ )
- mlt_deque_pop_front( context->stack );
- properties = mlt_deque_peek_front( context->stack );
- context->level = indent;
- }
-
- // Descending a level in the tree
- else if ( indent > context->level && context->block == 0 )
- {
- context->level = indent;
- }
-
- // If there is a colon that is not part of a block
- if ( ptr && ( indent == context->level ) )
- {
- // Reset block processing
- if ( context->block_name )
- {
- free( context->block_name );
- context->block_name = NULL;
- context->block = 0;
- }
-
- // Terminate the name and setup the value pointer
- *( ptr ++ ) = 0;
-
- // Trim comment
- char *comment = strchr( ptr, '#' );
- if ( comment )
- {
- *comment = 0;
- }
-
- // Trim leading and trailing spaces from bare value
- ltrim( &ptr );
- rtrim( ptr );
-
- // No value means a child
- if ( strcmp( ptr, "" ) == 0 )
- {
- mlt_properties child = mlt_properties_new();
- mlt_properties_set_data( properties, name, child, 0,
- ( mlt_destructor )mlt_properties_close, NULL );
- mlt_deque_push_front( context->stack, child );
- context->index = 0;
- free( name_ );
- return error;
- }
-
- // A dash indicates a sequence item
- if ( name[0] == '-' )
- {
- mlt_properties child = mlt_properties_new();
- char key[20];
-
- snprintf( key, sizeof(key), "%d", context->index++ );
- mlt_properties_set_data( properties, key, child, 0,
- ( mlt_destructor )mlt_properties_close, NULL );
- mlt_deque_push_front( context->stack, child );
-
- name ++;
- context->level += ltrim( &name ) + 1;
- properties = child;
- }
-
- // Value is quoted
- if ( *ptr == '\"' )
- {
- ptr ++;
- value = strdup( ptr );
- if ( value && value[ strlen( value ) - 1 ] == '\"' )
- value[ strlen( value ) - 1 ] = 0;
- }
-
- // Value is folded or unfolded block
- else if ( *ptr == '|' || *ptr == '>' )
- {
- context->block = *ptr;
- context->block_name = strdup( name );
- context->block_indent = 0;
- value = strdup( "" );
- }
-
- // Bare value
- else
- {
- value = strdup( ptr );
- }
- }
-
- // A list of scalars
- else if ( name[0] == '-' )
- {
- // Reset block processing
- if ( context->block_name )
- {
- free( context->block_name );
- context->block_name = NULL;
- context->block = 0;
- }
-
- char key[20];
-
- snprintf( key, sizeof(key), "%d", context->index++ );
- ptr = name + 1;
-
- // Trim comment
- char *comment = strchr( ptr, '#' );
- if ( comment )
- *comment = 0;
-
- // Trim leading and trailing spaces from bare value
- ltrim( &ptr );
- rtrim( ptr );
-
- // Value is quoted
- if ( *ptr == '\"' )
- {
- ptr ++;
- value = strdup( ptr );
- if ( value && value[ strlen( value ) - 1 ] == '\"' )
- value[ strlen( value ) - 1 ] = 0;
- }
-
- // Value is folded or unfolded block
- else if ( *ptr == '|' || *ptr == '>' )
- {
- context->block = *ptr;
- context->block_name = strdup( key );
- context->block_indent = 0;
- value = strdup( "" );
- }
-
- // Bare value
- else
- {
- value = strdup( ptr );
- }
-
- free( name_ );
- name = name_ = strdup( key );
- }
-
- // Non-folded block
- else if ( context->block == '|' )
- {
- if ( context->block_indent == 0 )
- context->block_indent = indent;
- if ( indent > context->block_indent )
- name = &name_[ context->block_indent ];
- rtrim( name );
- char *old_value = mlt_properties_get( properties, context->block_name );
- value = calloc( 1, strlen( old_value ) + strlen( name ) + 2 );
- strcpy( value, old_value );
- if ( strcmp( old_value, "" ) )
- strcat( value, "\n" );
- strcat( value, name );
- name = context->block_name;
- }
-
- // Folded block
- else if ( context->block == '>' )
- {
- ltrim( &name );
- rtrim( name );
- char *old_value = mlt_properties_get( properties, context->block_name );
-
- // Blank line (prepended with spaces) is new line
- if ( strcmp( name, "" ) == 0 )
- {
- value = calloc( 1, strlen( old_value ) + 2 );
- strcat( value, old_value );
- strcat( value, "\n" );
- }
- // Concatenate with space
- else
- {
- value = calloc( 1, strlen( old_value ) + strlen( name ) + 2 );
- strcat( value, old_value );
- if ( strcmp( old_value, "" ) && old_value[ strlen( old_value ) - 1 ] != '\n' )
- strcat( value, " " );
- strcat( value, name );
- }
- name = context->block_name;
- }
-
- else
- {
- value = strdup( "" );
- }
-
- error = mlt_properties_set( properties, name, value );
-
- free( name_ );
- free( value );
-
- return error;
-}
-
-/** Parse a YAML Tiny file by name.
- *
- * \public \memberof mlt_properties_s
- * \param filename the name of a text file containing YAML Tiny
- * \return a new properties list
- */
-
-mlt_properties mlt_properties_parse_yaml( const char *filename )
-{
- // Construct a standalone properties object
- mlt_properties this = mlt_properties_new( );
-
- if ( this )
- {
- // Open the file
- FILE *file = fopen( filename, "r" );
-
- // Load contents of file
- if ( file )
- {
- // Temp string
- char temp[ 1024 ];
- char *ptemp = &temp[ 0 ];
-
- // Parser context
- yaml_parser context = calloc( 1, sizeof( struct yaml_parser_context ) );
- context->stack = mlt_deque_init();
- mlt_deque_push_front( context->stack, this );
-
- // Read each string from the file
- while( fgets( temp, 1024, file ) )
- {
- // Check for end-of-stream
- if ( strncmp( ptemp, "...", 3 ) == 0 )
- break;
-
- // Chomp the string
- temp[ strlen( temp ) - 1 ] = '\0';
-
- // Skip blank lines, comment lines, and document separator
- if ( strcmp( ptemp, "" ) && ptemp[ 0 ] != '#' && strncmp( ptemp, "---", 3 )
- && strncmp( ptemp, "%YAML", 5 ) && strncmp( ptemp, "% YAML", 6 ) )
- parse_yaml( context, temp );
- }
-
- // Close the file
- fclose( file );
- mlt_deque_close( context->stack );
- if ( context->block_name )
- free( context->block_name );
- free( context );
- }
- }
-
- // Return the pointer
- return this;
-}
-
-/*
- * YAML Tiny Serializer
- */
-
-/** How many bytes to grow at a time */
-#define STRBUF_GROWTH (1024)
-
-/** \brief Private to mlt_properties_s, a self-growing buffer for building strings
- * \private
- */
-
-struct strbuf_s
-{
- size_t size;
- char *string;
-};
-
-typedef struct strbuf_s *strbuf;
-
-/** Create a new string buffer
- *
- * \private \memberof strbuf_s
- * \return a new string buffer
- */
-
-static strbuf strbuf_new( )
-{
- strbuf buffer = calloc( 1, sizeof( struct strbuf_s ) );
- buffer->size = STRBUF_GROWTH;
- buffer->string = calloc( 1, buffer->size );
- return buffer;
-}
-
-/** Destroy a string buffer
- *
- * \private \memberof strbuf_s
- * \param buffer the string buffer to close
- */
-
-static void strbuf_close( strbuf buffer )
-{
- // We do not free buffer->string; strbuf user must save that pointer
- // and free it.
- if ( buffer )
- free( buffer );
-}
-
-/** Format a string into a string buffer
- *
- * A variable number of arguments follows the format string - one for each
- * format specifier.
- * \private \memberof strbuf_s
- * \param buffer the string buffer to write into
- * \param format a string that contains text and formatting instructions
- * \return the formatted string
- */
-
-static char *strbuf_printf( strbuf buffer, const char *format, ... )
-{
- while ( buffer->string )
- {
- va_list ap;
- va_start( ap, format );
- size_t len = strlen( buffer->string );
- size_t remain = buffer->size - len - 1;
- int need = vsnprintf( buffer->string + len, remain, format, ap );
- va_end( ap );
- if ( need > -1 && need < remain )
- break;
- buffer->string[ len ] = 0;
- buffer->size += need + STRBUF_GROWTH;
- buffer->string = realloc( buffer->string, buffer->size );
- }
- return buffer->string;
-}
-
-/** Indent a line of YAML Tiny.
- *
- * \private \memberof strbuf_s
- * \param output a string buffer
- * \param indent the number of spaces to indent
- */
-
-static inline void indent_yaml( strbuf output, int indent )
-{
- int j;
- for ( j = 0; j < indent; j++ )
- strbuf_printf( output, " " );
-}
-
-/** Convert a line string into a YAML block literal.
- *
- * \private \memberof strbuf_s
- * \param output a string buffer
- * \param value the string to format as a block literal
- * \param indent the number of spaces to indent
- */
-
-static void output_yaml_block_literal( strbuf output, const char *value, int indent )
-{
- char *v = strdup( value );
- char *sol = v;
- char *eol = strchr( sol, '\n' );
-
- while ( eol )
- {
- indent_yaml( output, indent );
- *eol = '\0';
- strbuf_printf( output, "%s\n", sol );
- sol = eol + 1;
- eol = strchr( sol, '\n' );
- }
- indent_yaml( output, indent );
- strbuf_printf( output, "%s\n", sol );
-}
-
-/** Recursively serialize a properties list into a string buffer as YAML Tiny.
- *
- * \private \memberof mlt_properties_s
- * \param this a properties list
- * \param output a string buffer to hold the serialized YAML Tiny
- * \param indent the number of spaces to indent (for recursion, initialize to 0)
- * \param is_parent_sequence Is 'this' properties list really just a sequence (for recursion, initialize to 0)?
- */
-
-static void serialise_yaml( mlt_properties this, strbuf output, int indent, int is_parent_sequence )
-{
- property_list *list = this->local;
- int i = 0;
-
- for ( i = 0; i < list->count; i ++ )
- {
- // This implementation assumes that all data elements are property lists.
- // Unfortunately, we do not have run time type identification.
- mlt_properties child = mlt_property_get_data( list->value[ i ], NULL );
-
- if ( mlt_properties_is_sequence( this ) )
- {
- // Ignore hidden/non-serialisable items
- if ( list->name[ i ][ 0 ] != '_' )
- {
- // Indicate a sequence item
- indent_yaml( output, indent );
- strbuf_printf( output, "- " );
-
- // If the value can be represented as a string
- const char *value = mlt_properties_get( this, list->name[ i ] );
- if ( value && strcmp( value, "" ) )
- {
- // Determine if this is an unfolded block literal
- if ( strchr( value, '\n' ) )
- {
- strbuf_printf( output, "|\n" );
- output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( "|" ) );
- }
- else
- {
- strbuf_printf( output, "%s\n", value );
- }
- }
- }
- // Recurse on child
- if ( child )
- serialise_yaml( child, output, indent + 2, 1 );
- }
- else
- {
- // Assume this is a normal map-oriented properties list
- const char *value = mlt_properties_get( this, list->name[ i ] );
-
- // Ignore hidden/non-serialisable items
- // If the value can be represented as a string
- if ( list->name[ i ][ 0 ] != '_' && value && strcmp( value, "" ) )
- {
- if ( is_parent_sequence == 0 )
- indent_yaml( output, indent );
- else
- is_parent_sequence = 0;
-
- // Determine if this is an unfolded block literal
- if ( strchr( value, '\n' ) )
- {
- strbuf_printf( output, "%s: |\n", list->name[ i ] );
- output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( ": " ) );
- }
- else
- {
- strbuf_printf( output, "%s: %s\n", list->name[ i ], value );
- }
- }
-
- // Output a child as a map item
- if ( child )
- {
- indent_yaml( output, indent );
- strbuf_printf( output, "%s:\n", list->name[ i ] );
-
- // Recurse on child
- serialise_yaml( child, output, indent + 2, 0 );
- }
- }
- }
-}
-
-/** Serialize a properties list as a string of YAML Tiny.
- *
- * The caller MUST free the returned string!
- * This operates on properties containing properties as a hierarchical data
- * structure.
- * \public \memberof mlt_properties_s
- * \param this a properties list
- * \return a string containing YAML Tiny that represents the properties list
- */
-
-char *mlt_properties_serialise_yaml( mlt_properties this )
-{
- strbuf b = strbuf_new();
- strbuf_printf( b, "---\n" );
- serialise_yaml( this, b, 0, 0 );
- strbuf_printf( b, "...\n" );
- char *ret = b->string;
- strbuf_close( b );
- return ret;
-}
+++ /dev/null
-/**
- * \file mlt_properties.h
- * \brief Properties class declaration
- * \see mlt_properties_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PROPERTIES_H_
-#define _MLT_PROPERTIES_H_
-
-#include "mlt_types.h"
-#include "mlt_events.h"
-#include <stdio.h>
-
-/** \brief Properties class
- *
- * Properties is a combination list/dictionary of name/::mlt_property pairs.
- * It is also a base class for many of the other MLT classes.
- */
-
-struct mlt_properties_s
-{
- void *child; /**< \private the object of a subclass */
- void *local; /**< \private instance object */
-
- /** the destructor virtual function */
- mlt_destructor close;
- void *close_object; /**< the object supplied to the close virtual function */
-};
-
-extern int mlt_properties_init( mlt_properties, void *child );
-extern mlt_properties mlt_properties_new( );
-extern mlt_properties mlt_properties_load( const char *file );
-extern int mlt_properties_inc_ref( mlt_properties self );
-extern int mlt_properties_dec_ref( mlt_properties self );
-extern int mlt_properties_ref_count( mlt_properties self );
-extern void mlt_properties_mirror( mlt_properties self, mlt_properties that );
-extern int mlt_properties_inherit( mlt_properties self, mlt_properties that );
-extern int mlt_properties_pass( mlt_properties self, mlt_properties that, const char *prefix );
-extern void mlt_properties_pass_property( mlt_properties self, mlt_properties that, const char *name );
-extern int mlt_properties_pass_list( mlt_properties self, mlt_properties that, const char *list );
-extern int mlt_properties_set( mlt_properties self, const char *name, const char *value );
-extern int mlt_properties_set_or_default( mlt_properties self, const char *name, const char *value, const char *def );
-extern int mlt_properties_parse( mlt_properties self, const char *namevalue );
-extern char *mlt_properties_get( mlt_properties self, const char *name );
-extern char *mlt_properties_get_name( mlt_properties self, int index );
-extern char *mlt_properties_get_value( mlt_properties self, int index );
-extern void *mlt_properties_get_data_at( mlt_properties self, int index, int *size );
-extern int mlt_properties_get_int( mlt_properties self, const char *name );
-extern int mlt_properties_set_int( mlt_properties self, const char *name, int value );
-extern int64_t mlt_properties_get_int64( mlt_properties self, const char *name );
-extern int mlt_properties_set_int64( mlt_properties self, const char *name, int64_t value );
-extern double mlt_properties_get_double( mlt_properties self, const char *name );
-extern int mlt_properties_set_double( mlt_properties self, const char *name, double value );
-extern mlt_position mlt_properties_get_position( mlt_properties self, const char *name );
-extern int mlt_properties_set_position( mlt_properties self, const char *name, mlt_position value );
-extern int mlt_properties_set_data( mlt_properties self, const char *name, void *value, int length, mlt_destructor, mlt_serialiser );
-extern void *mlt_properties_get_data( mlt_properties self, const char *name, int *length );
-extern int mlt_properties_rename( mlt_properties self, const char *source, const char *dest );
-extern int mlt_properties_count( mlt_properties self );
-extern void mlt_properties_dump( mlt_properties self, FILE *output );
-extern void mlt_properties_debug( mlt_properties self, const char *title, FILE *output );
-extern int mlt_properties_save( mlt_properties, const char * );
-extern int mlt_properties_dir_list( mlt_properties, const char *, const char *, int );
-extern void mlt_properties_close( mlt_properties self );
-extern int mlt_properties_is_sequence( mlt_properties self );
-extern mlt_properties mlt_properties_parse_yaml( const char *file );
-extern char *mlt_properties_serialise_yaml( mlt_properties self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_property.c
- * \brief Property class definition
- * \see mlt_property_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_property.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/** Bit pattern used internally to indicated representations available.
-*/
-
-typedef enum
-{
- mlt_prop_none = 0, //!< not set
- mlt_prop_int = 1, //!< set as an integer
- mlt_prop_string = 2, //!< set as string or already converted to string
- mlt_prop_position = 4,//!< set as a position
- mlt_prop_double = 8, //!< set as a floating point
- mlt_prop_data = 16, //!< set as opaque binary
- mlt_prop_int64 = 32 //!< set as a 64-bit integer
-}
-mlt_property_type;
-
-/** \brief Property class
- *
- * A property is like a variant or dynamic type. They are used for many things
- * in MLT, but in particular they are the parameter mechanism for the plugins.
- */
-
-struct mlt_property_s
-{
- /// Stores a bit pattern of types available for this property
- mlt_property_type types;
-
- /// Atomic type handling
- int prop_int;
- mlt_position prop_position;
- double prop_double;
- int64_t prop_int64;
-
- /// String handling
- char *prop_string;
-
- /// Generic type handling
- void *data;
- int length;
- mlt_destructor destructor;
- mlt_serialiser serialiser;
-};
-
-/** Construct a property and initialize it
- * \public \memberof mlt_property_s
- */
-
-mlt_property mlt_property_init( )
-{
- mlt_property this = malloc( sizeof( struct mlt_property_s ) );
- if ( this != NULL )
- {
- this->types = 0;
- this->prop_int = 0;
- this->prop_position = 0;
- this->prop_double = 0;
- this->prop_int64 = 0;
- this->prop_string = NULL;
- this->data = NULL;
- this->length = 0;
- this->destructor = NULL;
- this->serialiser = NULL;
- }
- return this;
-}
-
-/** Clear (0/null) a property.
- *
- * Frees up any associated resources in the process.
- * \private \memberof mlt_property_s
- * \param this a property
- */
-
-static inline void mlt_property_clear( mlt_property this )
-{
- // Special case data handling
- if ( this->types & mlt_prop_data && this->destructor != NULL )
- this->destructor( this->data );
-
- // Special case string handling
- if ( this->types & mlt_prop_string )
- free( this->prop_string );
-
- // Wipe stuff
- this->types = 0;
- this->prop_int = 0;
- this->prop_position = 0;
- this->prop_double = 0;
- this->prop_int64 = 0;
- this->prop_string = NULL;
- this->data = NULL;
- this->length = 0;
- this->destructor = NULL;
- this->serialiser = NULL;
-}
-
-/** Set the property to an integer value.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value an integer
- * \return false
- */
-
-int mlt_property_set_int( mlt_property this, int value )
-{
- mlt_property_clear( this );
- this->types = mlt_prop_int;
- this->prop_int = value;
- return 0;
-}
-
-/** Set the property to a floating point value.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value a double precision floating point value
- * \return false
- */
-
-int mlt_property_set_double( mlt_property this, double value )
-{
- mlt_property_clear( this );
- this->types = mlt_prop_double;
- this->prop_double = value;
- return 0;
-}
-
-/** Set the property to a position value.
- *
- * Position is a relative time value in frame units.
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value a position value
- * \return false
- */
-
-int mlt_property_set_position( mlt_property this, mlt_position value )
-{
- mlt_property_clear( this );
- this->types = mlt_prop_position;
- this->prop_position = value;
- return 0;
-}
-
-/** Set the property to a string value.
- *
- * This makes a copy of the string you supply so you do not need to track
- * a new reference to it.
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value the string to copy to the property
- * \return true if it failed
- */
-
-int mlt_property_set_string( mlt_property this, const char *value )
-{
- if ( value != this->prop_string )
- {
- mlt_property_clear( this );
- this->types = mlt_prop_string;
- if ( value != NULL )
- this->prop_string = strdup( value );
- }
- else
- {
- this->types = mlt_prop_string;
- }
- return this->prop_string == NULL;
-}
-
-/** Set the property to a 64-bit integer value.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value a 64-bit integer
- * \return false
- */
-
-int mlt_property_set_int64( mlt_property this, int64_t value )
-{
- mlt_property_clear( this );
- this->types = mlt_prop_int64;
- this->prop_int64 = value;
- return 0;
-}
-
-/** Set a property to an opaque binary value.
- *
- * This does not make a copy of the data. You can use a Properties object
- * with its reference tracking and the destructor function to control
- * the lifetime of the data. Otherwise, pass NULL for the destructor
- * function and control the lifetime yourself.
- * \public \memberof mlt_property_s
- * \param this a property
- * \param value an opaque pointer
- * \param length the number of bytes pointed to by value (optional)
- * \param destructor a function to use to destroy this binary data (optional, assuming you manage the resource)
- * \param serialiser a function to use to convert this binary data to a string (optional)
- * \return false
- */
-
-int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser )
-{
- if ( this->data == value )
- this->destructor = NULL;
- mlt_property_clear( this );
- this->types = mlt_prop_data;
- this->data = value;
- this->length = length;
- this->destructor = destructor;
- this->serialiser = serialiser;
- return 0;
-}
-
-/** Convert a base 10 or base 16 string to an integer.
- *
- * The string must begin with '0x' to be interpreted as hexadecimal.
- * Otherwise, it is interpreted as base 10.
- * If the string begins with '#' it is interpreted as a hexadecimal color value
- * in the form RRGGBB or AARRGGBB. Color values that begin with '0x' are
- * always in the form RRGGBBAA where the alpha components are not optional.
- * Applications and services should expect the binary color value in bytes to
- * be in the following order: RGBA. This means they will have to cast the int
- * to an unsigned int. This is especially important when they need to shift
- * right to obtain RGB without alpha in order to make it do a logical instead
- * of arithmetic shift.
- *
- * \private \memberof mlt_property_s
- * \param value a string to convert
- * \return the resultant integer
- */
-static inline int mlt_property_atoi( const char *value )
-{
- if ( value == NULL )
- return 0;
- // Parse a hex color value as #RRGGBB or #AARRGGBB.
- if ( value[0] == '#' )
- {
- unsigned int rgb = strtoul( value + 1, NULL, 16 );
- unsigned int alpha = ( strlen( value ) > 7 ) ? ( rgb >> 24 ) : 0xff;
- return ( rgb << 8 ) | alpha;
- }
- // Do hex and decimal explicitly to avoid decimal value with leading zeros
- // interpreted as octal.
- else if ( value[0] == '0' && value[1] == 'x' )
- {
- return strtoul( value + 2, NULL, 16 );
- }
- else
- {
- return strtol( value, NULL, 10 );
- }
-}
-
-/** Get the property as an integer.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \return an integer value
- */
-
-int mlt_property_get_int( mlt_property this )
-{
- if ( this->types & mlt_prop_int )
- return this->prop_int;
- else if ( this->types & mlt_prop_double )
- return ( int )this->prop_double;
- else if ( this->types & mlt_prop_position )
- return ( int )this->prop_position;
- else if ( this->types & mlt_prop_int64 )
- return ( int )this->prop_int64;
- else if ( this->types & mlt_prop_string )
- return mlt_property_atoi( this->prop_string );
- return 0;
-}
-
-/** Get the property as a floating point.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \return a floating point value
- */
-
-double mlt_property_get_double( mlt_property this )
-{
- if ( this->types & mlt_prop_double )
- return this->prop_double;
- else if ( this->types & mlt_prop_int )
- return ( double )this->prop_int;
- else if ( this->types & mlt_prop_position )
- return ( double )this->prop_position;
- else if ( this->types & mlt_prop_int64 )
- return ( double )this->prop_int64;
- else if ( this->types & mlt_prop_string )
- return atof( this->prop_string );
- return 0;
-}
-
-/** Get the property as a position.
- *
- * A position is an offset time in terms of frame units.
- * \public \memberof mlt_property_s
- * \param this a property
- * \return the position in frames
- */
-
-mlt_position mlt_property_get_position( mlt_property this )
-{
- if ( this->types & mlt_prop_position )
- return this->prop_position;
- else if ( this->types & mlt_prop_int )
- return ( mlt_position )this->prop_int;
- else if ( this->types & mlt_prop_double )
- return ( mlt_position )this->prop_double;
- else if ( this->types & mlt_prop_int64 )
- return ( mlt_position )this->prop_int64;
- else if ( this->types & mlt_prop_string )
- return ( mlt_position )atol( this->prop_string );
- return 0;
-}
-
-/** Convert a string to a 64-bit integer.
- *
- * If the string begins with '0x' it is interpreted as a hexadecimal value.
- * \private \memberof mlt_property_s
- * \param value a string
- * \return a 64-bit integer
- */
-
-static inline int64_t mlt_property_atoll( const char *value )
-{
- if ( value == NULL )
- return 0;
- else if ( value[0] == '0' && value[1] == 'x' )
- return strtoll( value + 2, NULL, 16 );
- else
- return strtoll( value, NULL, 10 );
-}
-
-/** Get the property as a signed integer.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- * \return a 64-bit integer
- */
-
-int64_t mlt_property_get_int64( mlt_property this )
-{
- if ( this->types & mlt_prop_int64 )
- return this->prop_int64;
- else if ( this->types & mlt_prop_int )
- return ( int64_t )this->prop_int;
- else if ( this->types & mlt_prop_double )
- return ( int64_t )this->prop_double;
- else if ( this->types & mlt_prop_position )
- return ( int64_t )this->prop_position;
- else if ( this->types & mlt_prop_string )
- return mlt_property_atoll( this->prop_string );
- return 0;
-}
-
-/** Get the property as a string.
- *
- * The caller is not responsible for deallocating the returned string!
- * The string is deallocated when the Property is closed.
- * This tries its hardest to convert the property to string including using
- * a serialization function for binary data, if supplied.
- * \public \memberof mlt_property_s
- * \param this a property
- * \return a string representation of the property or NULL if failed
- */
-
-char *mlt_property_get_string( mlt_property this )
-{
- // Construct a string if need be
- if ( ! ( this->types & mlt_prop_string ) )
- {
- if ( this->types & mlt_prop_int )
- {
- this->types |= mlt_prop_string;
- this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%d", this->prop_int );
- }
- else if ( this->types & mlt_prop_double )
- {
- this->types |= mlt_prop_string;
- this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%f", this->prop_double );
- }
- else if ( this->types & mlt_prop_position )
- {
- this->types |= mlt_prop_string;
- this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%d", (int)this->prop_position ); /* I don't know if this is wanted. -Zach */
- }
- else if ( this->types & mlt_prop_int64 )
- {
- this->types |= mlt_prop_string;
- this->prop_string = malloc( 32 );
- sprintf( this->prop_string, "%lld", (long long int)this->prop_int64 );
- }
- else if ( this->types & mlt_prop_data && this->serialiser != NULL )
- {
- this->types |= mlt_prop_string;
- this->prop_string = this->serialiser( this->data, this->length );
- }
- }
-
- // Return the string (may be NULL)
- return this->prop_string;
-}
-
-/** Get the binary data from a property.
- *
- * This only works if you previously put binary data into the property.
- * This does not return a copy of the data; it returns a pointer to it.
- * If you supplied a destructor function when setting the binary data,
- * the destructor is used when the Property is closed to free the memory.
- * Therefore, only free the returned pointer if you did not supply a
- * destructor function.
- * \public \memberof mlt_property_s
- * \param this a property
- * \param[out] length the size of the binary object in bytes (optional)
- * \return an opaque data pointer or NULL if not available
- */
-
-void *mlt_property_get_data( mlt_property this, int *length )
-{
- // Assign length if not NULL
- if ( length != NULL )
- *length = this->length;
-
- // Return the data (note: there is no conversion here)
- return this->data;
-}
-
-/** Destroy a property and free all related resources.
- *
- * \public \memberof mlt_property_s
- * \param this a property
- */
-
-void mlt_property_close( mlt_property this )
-{
- mlt_property_clear( this );
- free( this );
-}
-
-/** Copy a property.
- *
- * A Property holding binary data only copies the data if a serialiser
- * function was supplied when you set the Property.
- * \public \memberof mlt_property_s
- * \author Zach <zachary.drew@gmail.com>
- * \param this a property
- * \param that another property
- */
-void mlt_property_pass( mlt_property this, mlt_property that )
-{
- mlt_property_clear( this );
-
- this->types = that->types;
-
- if ( this->types & mlt_prop_int64 )
- this->prop_int64 = that->prop_int64;
- else if ( this->types & mlt_prop_int )
- this->prop_int = that->prop_int;
- else if ( this->types & mlt_prop_double )
- this->prop_double = that->prop_double;
- else if ( this->types & mlt_prop_position )
- this->prop_position = that->prop_position;
- else if ( this->types & mlt_prop_string )
- {
- if ( that->prop_string != NULL )
- this->prop_string = strdup( that->prop_string );
- }
- else if ( this->types & mlt_prop_data && this->serialiser != NULL )
- {
- this->types = mlt_prop_string;
- this->prop_string = this->serialiser( this->data, this->length );
- }
-}
+++ /dev/null
-/**
- * \file mlt_property.h
- * \brief Property class declaration
- * \see mlt_property_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_PROPERTY_H_
-#define _MLT_PROPERTY_H_
-
-#include "mlt_types.h"
-
-extern mlt_property mlt_property_init( );
-extern int mlt_property_set_int( mlt_property self, int value );
-extern int mlt_property_set_double( mlt_property self, double value );
-extern int mlt_property_set_position( mlt_property self, mlt_position value );
-extern int mlt_property_set_int64( mlt_property self, int64_t value );
-extern int mlt_property_set_string( mlt_property self, const char *value );
-extern int mlt_property_set_data( mlt_property self, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser );
-extern int mlt_property_get_int( mlt_property self );
-extern double mlt_property_get_double( mlt_property self );
-extern mlt_position mlt_property_get_position( mlt_property self );
-extern int64_t mlt_property_get_int64( mlt_property self );
-extern char *mlt_property_get_string( mlt_property self );
-extern void *mlt_property_get_data( mlt_property self, int *length );
-extern void mlt_property_close( mlt_property self );
-
-extern void mlt_property_pass( mlt_property this, mlt_property that );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_repository.c
- * \brief provides a map between service and shared objects
- * \see mlt_repository_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_repository.h"
-#include "mlt_properties.h"
-#include "mlt_tokeniser.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <string.h>
-
-/** \brief Repository class
- *
- * The Repository is a collection of plugin modules and their services and service metadata.
- *
- * \extends mlt_properties_s
- * \properties \p language a cached list of user locales
- */
-
-struct mlt_repository_s
-{
- struct mlt_properties_s parent; /// a list of object files
- mlt_properties consumers; /// a list of entry points for consumers
- mlt_properties filters; /// a list of entry points for filters
- mlt_properties producers; /// a list of entry points for producers
- mlt_properties transitions; /// a list of entry points for transitions
-};
-
-/** Construct a new repository.
- *
- * \public \memberof mlt_repository_s
- * \param directory the full path of a directory from which to read modules
- * \return a new repository or NULL if failed
- */
-
-mlt_repository mlt_repository_init( const char *directory )
-{
- // Safety check
- if ( directory == NULL || strcmp( directory, "" ) == 0 )
- return NULL;
-
- // Construct the repository
- mlt_repository this = calloc( sizeof( struct mlt_repository_s ), 1 );
- mlt_properties_init( &this->parent, this );
- this->consumers = mlt_properties_new();
- this->filters = mlt_properties_new();
- this->producers = mlt_properties_new();
- this->transitions = mlt_properties_new();
-
- // Get the directory list
- mlt_properties dir = mlt_properties_new();
- int count = mlt_properties_dir_list( dir, directory, NULL, 0 );
- int i;
-
- // Iterate over files
- for ( i = 0; i < count; i++ )
- {
- int flags = RTLD_NOW;
- const char *object_name = mlt_properties_get_value( dir, i);
-
- // Very temporary hack to allow the quicktime plugins to work
- // TODO: extend repository to allow this to be used on a case by case basis
- if ( strstr( object_name, "libmltkino" ) )
- flags |= RTLD_GLOBAL;
-
- // Open the shared object
- void *object = dlopen( object_name, flags );
- if ( object != NULL )
- {
- // Get the registration function
- mlt_repository_callback symbol_ptr = dlsym( object, "mlt_register" );
-
- // Call the registration function
- if ( symbol_ptr != NULL )
- {
- symbol_ptr( this );
-
- // Register the object file for closure
- mlt_properties_set_data( &this->parent, object_name, object, 0, ( mlt_destructor )dlclose, NULL );
- }
- else
- {
- dlclose( object );
- }
- }
- else if ( strstr( object_name, "libmlt" ) )
- {
- mlt_log( NULL, MLT_LOG_WARNING, "%s: failed to dlopen %s\n (%s)\n", __FUNCTION__, object_name, dlerror() );
- }
- }
-
- mlt_properties_close( dir );
-
- return this;
-}
-
-/** Create a properties list for a service holding a function pointer to its constructor function.
- *
- * \private \memberof mlt_repository_s
- * \param symbol a pointer to a function that can create the service.
- * \return a properties list
- */
-
-static mlt_properties new_service( void *symbol )
-{
- mlt_properties properties = mlt_properties_new();
- mlt_properties_set_data( properties, "symbol", symbol, 0, NULL, NULL );
- return properties;
-}
-
-/** Register a service with the repository.
- *
- * Typically, this is invoked by a module within its mlt_register().
- *
- * \public \memberof mlt_repository_s
- * \param this a repository
- * \param service_type a service class
- * \param service the name of a service
- * \param symbol a pointer to a function to create the service
- */
-
-void mlt_repository_register( mlt_repository this, mlt_service_type service_type, const char *service, mlt_register_callback symbol )
-{
- // Add the entry point to the corresponding service list
- switch ( service_type )
- {
- case consumer_type:
- mlt_properties_set_data( this->consumers, service, new_service( symbol ), 0, ( mlt_destructor )mlt_properties_close, NULL );
- break;
- case filter_type:
- mlt_properties_set_data( this->filters, service, new_service( symbol ), 0, ( mlt_destructor )mlt_properties_close, NULL );
- break;
- case producer_type:
- mlt_properties_set_data( this->producers, service, new_service( symbol ), 0, ( mlt_destructor )mlt_properties_close, NULL );
- break;
- case transition_type:
- mlt_properties_set_data( this->transitions, service, new_service( symbol ), 0, ( mlt_destructor )mlt_properties_close, NULL );
- break;
- default:
- break;
- }
-}
-
-/** Get the repository properties for particular service class.
- *
- * \private \memberof mlt_repository_s
- * \param this a repository
- * \param type a service class
- * \param service the name of a service
- * \return a properties list or NULL if error
- */
-
-static mlt_properties get_service_properties( mlt_repository this, mlt_service_type type, const char *service )
-{
- mlt_properties service_properties = NULL;
-
- // Get the entry point from the corresponding service list
- switch ( type )
- {
- case consumer_type:
- service_properties = mlt_properties_get_data( this->consumers, service, NULL );
- break;
- case filter_type:
- service_properties = mlt_properties_get_data( this->filters, service, NULL );
- break;
- case producer_type:
- service_properties = mlt_properties_get_data( this->producers, service, NULL );
- break;
- case transition_type:
- service_properties = mlt_properties_get_data( this->transitions, service, NULL );
- break;
- default:
- break;
- }
- return service_properties;
-}
-
-/** Construct a new instance of a service.
- *
- * \public \memberof mlt_repository_s
- * \param this a repository
- * \param profile a \p mlt_profile to give the service
- * \param type a service class
- * \param service the name of the service
- * \param input an optional argument to the service constructor
- */
-
-void *mlt_repository_create( mlt_repository this, mlt_profile profile, mlt_service_type type, const char *service, const void *input )
-{
- mlt_properties properties = get_service_properties( this, type, service );
- if ( properties != NULL )
- {
- mlt_register_callback symbol_ptr = mlt_properties_get_data( properties, "symbol", NULL );
-
- // Construct the service
- return ( symbol_ptr != NULL ) ? symbol_ptr( profile, type, service, input ) : NULL;
- }
- return NULL;
-}
-
-/** Destroy a repository and free its resources.
- *
- * \public \memberof mlt_repository_s
- * \param this a repository
- */
-
-void mlt_repository_close( mlt_repository this )
-{
- mlt_properties_close( this->consumers );
- mlt_properties_close( this->filters );
- mlt_properties_close( this->producers );
- mlt_properties_close( this->transitions );
- mlt_properties_close( &this->parent );
- free( this );
-}
-
-/** Get the list of registered consumers.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \return a properties list containing all of the consumers
- */
-
-mlt_properties mlt_repository_consumers( mlt_repository self )
-{
- return self->consumers;
-}
-
-/** Get the list of registered filters.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \return a properties list of all of the filters
- */
-
-mlt_properties mlt_repository_filters( mlt_repository self )
-{
- return self->filters;
-}
-
-/** Get the list of registered producers.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \return a properties list of all of the producers
- */
-
-mlt_properties mlt_repository_producers( mlt_repository self )
-{
- return self->producers;
-}
-
-/** Get the list of registered transitions.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \return a properties list of all of the transitions
- */
-
-mlt_properties mlt_repository_transitions( mlt_repository self )
-{
- return self->transitions;
-}
-
-/** Register the metadata for a service.
- *
- * IMPORTANT: mlt_repository will take responsibility for deallocating the metadata properties
- * that you supply!
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \param type a service class
- * \param service the name of a service
- * \param callback the pointer to a function that can supply metadata
- * \param callback_data an opaque user data pointer to be supplied on the callback
- */
-
-void mlt_repository_register_metadata( mlt_repository self, mlt_service_type type, const char *service, mlt_metadata_callback callback, void *callback_data )
-{
- mlt_properties service_properties = get_service_properties( self, type, service );
- mlt_properties_set_data( service_properties, "metadata_cb", callback, 0, NULL, NULL );
- mlt_properties_set_data( service_properties, "metadata_cb_data", callback_data, 0, NULL, NULL );
-}
-
-/** Get the metadata about a service.
- *
- * Returns NULL if service or its metadata are unavailable.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \param type a service class
- * \param service the name of a service
- * \return the service metadata as a structured properties list
- */
-
-mlt_properties mlt_repository_metadata( mlt_repository self, mlt_service_type type, const char *service )
-{
- mlt_properties metadata = NULL;
- mlt_properties properties = get_service_properties( self, type, service );
-
- // If this is a valid service
- if ( properties )
- {
- // Lookup cached metadata
- metadata = mlt_properties_get_data( properties, "metadata", NULL );
- if ( ! metadata )
- {
- // Not cached, so get the registered metadata callback function
- mlt_metadata_callback callback = mlt_properties_get_data( properties, "metadata_cb", NULL );
-
- // If a metadata callback function is registered
- if ( callback )
- {
- // Fetch the callback data arg
- void *data = mlt_properties_get_data( properties, "metadata_cb_data", NULL );
-
- // Fetch the metadata through the callback
- metadata = callback( type, service, data );
-
- // Cache the metadata
- if ( metadata )
- // Include dellocation and serialisation
- mlt_properties_set_data( properties, "metadata", metadata, 0, ( mlt_destructor )mlt_properties_close, ( mlt_serialiser )mlt_properties_serialise_yaml );
- }
- }
- }
- return metadata;
-}
-
-/** Try to determine the locale from some commonly used environment variables.
- *
- * \private \memberof mlt_repository_s
- * \return a string containing the locale id or NULL if unknown
- */
-
-static char *getenv_locale()
-{
- char *s = getenv( "LANGUAGE" );
- if ( s && s[0] )
- return s;
- s = getenv( "LC_ALL" );
- if ( s && s[0] )
- return s;
- s = getenv( "LC_MESSAGES" );
- if ( s && s[0] )
- return s;
- s = getenv( "LANG" );
- if ( s && s[0] )
- return s;
- return NULL;
-}
-
-/** Return a list of user-preferred language codes taken from environment variables.
- *
- * A module should use this to locate a localized YAML Tiny file from which to build
- * its metadata strucutured properties.
- *
- * \public \memberof mlt_repository_s
- * \param self a repository
- * \return a properties list that is a list (not a map) of locales, defaults to "en" if not
- * overridden by environment variables, in order: LANGUAGE, LC_ALL, LC_MESSAGES, LANG
- */
-
-mlt_properties mlt_repository_languages( mlt_repository self )
-{
- mlt_properties languages = mlt_properties_get_data( &self->parent, "languages", NULL );
- if ( languages )
- return languages;
-
- languages = mlt_properties_new();
- char *locale = getenv_locale();
- if ( locale )
- {
- locale = strdup( locale );
- mlt_tokeniser tokeniser = mlt_tokeniser_init();
- int count = mlt_tokeniser_parse_new( tokeniser, locale, ":" );
- if ( count )
- {
- int i;
- for ( i = 0; i < count; i++ )
- {
- char *locale = mlt_tokeniser_get_string( tokeniser, i );
- if ( strcmp( locale, "C" ) == 0 || strcmp( locale, "POSIX" ) == 0 )
- locale = "en";
- else if ( strlen( locale ) > 2 )
- locale[2] = 0;
- char string[21];
- snprintf( string, sizeof(string), "%d", i );
- mlt_properties_set( languages, string, locale );
- }
- }
- else
- {
- mlt_properties_set( languages, "0", "en" );
- }
- free( locale );
- mlt_tokeniser_close( tokeniser );
- }
- else
- {
- mlt_properties_set( languages, "0", "en" );
- }
- mlt_properties_set_data( &self->parent, "languages", languages, 0, ( mlt_destructor )mlt_properties_close, NULL );
- return languages;
-}
+++ /dev/null
-/**
- * \file mlt_repository.h
- * \brief provides a map between service and shared objects
- * \see mlt_repository_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- * \author Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_REPOSITORY_H_
-#define _MLT_REPOSITORY_H_
-
-#include "mlt_types.h"
-#include "mlt_profile.h"
-
-/** This callback is the main entry point into a module, which must be exported
- * with the symbol "mlt_register".
- *
- * Inside the callback, the module registers the additional callbacks below.
- */
-
-typedef void ( *mlt_repository_callback )( mlt_repository );
-
-/** The callback function that modules implement to construct a service.
- */
-
-typedef void *( *mlt_register_callback )( mlt_profile, mlt_service_type, const char * /* service name */, const void * /* arg */ );
-
-/** The callback function that modules implement to supply metadata as a properties list.
- */
-
-typedef mlt_properties ( *mlt_metadata_callback )( mlt_service_type, const char * /* service name */, void * /* callback_data */ );
-
-/** A convenience macro to create an entry point for service registration. */
-#define MLT_REPOSITORY void mlt_register( mlt_repository repository )
-
-/** A convenience macro to a register service in a more declarative manner. */
-#define MLT_REGISTER( type, service, symbol ) ( mlt_repository_register( repository, (type), (service), ( mlt_register_callback )(symbol) ) )
-
-/** A convenience macro to a register metadata in a more declarative manner. */
-#define MLT_REGISTER_METADATA( type, service, callback, data ) ( mlt_repository_register_metadata( repository, (type), (service), ( mlt_metadata_callback )(callback), (data) ) )
-
-extern mlt_repository mlt_repository_init( const char *directory );
-extern void mlt_repository_register( mlt_repository self, mlt_service_type service_type, const char *service, mlt_register_callback );
-extern void *mlt_repository_create( mlt_repository self, mlt_profile profile, mlt_service_type type, const char *service, const void *arg );
-extern void mlt_repository_close( mlt_repository self );
-extern mlt_properties mlt_repository_consumers( mlt_repository self );
-extern mlt_properties mlt_repository_filters( mlt_repository self );
-extern mlt_properties mlt_repository_producers( mlt_repository self );
-extern mlt_properties mlt_repository_transitions( mlt_repository self );
-extern void mlt_repository_register_metadata( mlt_repository self, mlt_service_type type, const char *service, mlt_metadata_callback, void *callback_data );
-extern mlt_properties mlt_repository_metadata( mlt_repository self, mlt_service_type type, const char *service );
-extern mlt_properties mlt_repository_languages( mlt_repository self );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_service.c
- * \brief interface definition for all service classes
- * \see mlt_service_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_service.h"
-#include "mlt_filter.h"
-#include "mlt_frame.h"
-#include "mlt_cache.h"
-#include "mlt_factory.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-
-
-/* IMPORTANT NOTES
-
- The base service implements a null frame producing service - as such,
- it is functional without extension and will produce test cards frames
- and PAL sized audio frames.
-
- PLEASE DO NOT CHANGE THIS BEHAVIOUR!!! OVERRIDE THE METHODS THAT
- CONTROL THIS IN EXTENDING CLASSES.
-*/
-
-/** \brief private service definition */
-
-typedef struct
-{
- int size;
- int count;
- mlt_service *in;
- mlt_service out;
- int filter_count;
- int filter_size;
- mlt_filter *filters;
- pthread_mutex_t mutex;
-}
-mlt_service_base;
-
-/* Private methods
- */
-
-static void mlt_service_disconnect( mlt_service this );
-static void mlt_service_connect( mlt_service this, mlt_service that );
-static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-static void mlt_service_property_changed( mlt_listener, mlt_properties owner, mlt_service this, void **args );
-static void purge_cache( mlt_service self );
-
-/** Initialize a service.
- *
- * \public \memberof mlt_service_s
- * \param this the service structure to initialize
- * \param child pointer to the child object for the subclass
- * \return true if there was an error
- */
-
-int mlt_service_init( mlt_service this, void *child )
-{
- int error = 0;
-
- // Initialise everything to NULL
- memset( this, 0, sizeof( struct mlt_service_s ) );
-
- // Assign the child
- this->child = child;
-
- // Generate local space
- this->local = calloc( sizeof( mlt_service_base ), 1 );
-
- // Associate the methods
- this->get_frame = service_get_frame;
-
- // Initialise the properties
- error = mlt_properties_init( &this->parent, this );
- if ( error == 0 )
- {
- this->parent.close = ( mlt_destructor )mlt_service_close;
- this->parent.close_object = this;
-
- mlt_events_init( &this->parent );
- mlt_events_register( &this->parent, "service-changed", NULL );
- mlt_events_register( &this->parent, "property-changed", ( mlt_transmitter )mlt_service_property_changed );
- pthread_mutex_init( &( ( mlt_service_base * )this->local )->mutex, NULL );
- }
-
- return error;
-}
-
-/** The transmitter for property changes.
- *
- * Invokes the listener.
- *
- * \private \memberof mlt_service_s
- * \param listener a function pointer that will be invoked
- * \param owner a properties list that will be passed to \p listener
- * \param this 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
- */
-
-static void mlt_service_property_changed( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( char * )args[ 0 ] );
-}
-
-/** Acquire a mutual exclusion lock on this service.
- *
- * \public \memberof mlt_service_s
- * \param this the service to lock
- */
-
-void mlt_service_lock( mlt_service this )
-{
- if ( this != NULL )
- pthread_mutex_lock( &( ( mlt_service_base * )this->local )->mutex );
-}
-
-/** Release a mutual exclusion lock on this service.
- *
- * \public \memberof mlt_service_s
- * \param this the service to unlock
- */
-
-void mlt_service_unlock( mlt_service this )
-{
- if ( this != NULL )
- pthread_mutex_unlock( &( ( mlt_service_base * )this->local )->mutex );
-}
-
-/** Identify the subclass of the service.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the subclass
- */
-
-mlt_service_type mlt_service_identify( mlt_service this )
-{
- mlt_service_type type = invalid_type;
- if ( this != NULL )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( this );
- char *mlt_type = mlt_properties_get( properties, "mlt_type" );
- char *resource = mlt_properties_get( properties, "resource" );
- if ( mlt_type == NULL )
- type = unknown_type;
- else if (resource != NULL && !strcmp( resource, "<playlist>" ) )
- type = playlist_type;
- else if (resource != NULL && !strcmp( resource, "<tractor>" ) )
- type = tractor_type;
- else if (resource != NULL && !strcmp( resource, "<multitrack>" ) )
- type = multitrack_type;
- else if ( !strcmp( mlt_type, "producer" ) )
- type = producer_type;
- else if ( !strcmp( mlt_type, "filter" ) )
- type = filter_type;
- else if ( !strcmp( mlt_type, "transition" ) )
- type = transition_type;
- else if ( !strcmp( mlt_type, "consumer" ) )
- type = consumer_type;
- else
- type = unknown_type;
- }
- return type;
-}
-
-/** Connect a producer to the service.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param producer a producer
- * \param index which of potentially multiple producers to this service (0 based)
- * \return > 0 warning, == 0 success, < 0 serious error,
- * 1 = this service does not accept input,
- * 2 = the producer is invalid,
- * 3 = the producer is already registered with this consumer
- */
-
-int mlt_service_connect_producer( mlt_service this, mlt_service producer, int index )
-{
- int i = 0;
-
- // Get the service base
- mlt_service_base *base = this->local;
-
- // Special case 'track' index - only works for last filter(s) in a particular chain
- // but allows a filter to apply to the output frame regardless of which track it comes from
- if ( index == -1 )
- index = 0;
-
- // Check if the producer is already registered with this service
- for ( i = 0; i < base->count; i ++ )
- if ( base->in[ i ] == producer )
- return 3;
-
- // Allocate space
- if ( index >= base->size )
- {
- int new_size = base->size + index + 10;
- base->in = realloc( base->in, new_size * sizeof( mlt_service ) );
- if ( base->in != NULL )
- {
- for ( i = base->size; i < new_size; i ++ )
- base->in[ i ] = NULL;
- base->size = new_size;
- }
- }
-
- // If we have space, assign the input
- if ( base->in != NULL && index >= 0 && index < base->size )
- {
- // Get the current service
- mlt_service current = base->in[ index ];
-
- // Increment the reference count on this producer
- if ( producer != NULL )
- mlt_properties_inc_ref( MLT_SERVICE_PROPERTIES( producer ) );
-
- // Now we disconnect the producer service from its consumer
- mlt_service_disconnect( producer );
-
- // Add the service to index specified
- base->in[ index ] = producer;
-
- // Determine the number of active tracks
- if ( index >= base->count )
- base->count = index + 1;
-
- // Now we connect the producer to its connected consumer
- mlt_service_connect( producer, this );
-
- // Close the current service
- mlt_service_close( current );
-
- // Inform caller that all went well
- return 0;
- }
- else
- {
- return -1;
- }
-}
-
-/** Disconnect this service from its consumer.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- */
-
-static void mlt_service_disconnect( mlt_service this )
-{
- if ( this != NULL )
- {
- // Get the service base
- mlt_service_base *base = this->local;
-
- // Disconnect
- base->out = NULL;
- }
-}
-
-/** Obtain the consumer this service is connected to.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the consumer
- */
-
-mlt_service mlt_service_consumer( mlt_service this )
-{
- // Get the service base
- mlt_service_base *base = this->local;
-
- // Return the connected consumer
- return base->out;
-}
-
-/** Obtain the producer this service is connected to.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the last-most producer
- */
-
-mlt_service mlt_service_producer( mlt_service this )
-{
- // Get the service base
- mlt_service_base *base = this->local;
-
- // Return the connected producer
- return base->count > 0 ? base->in[ base->count - 1 ] : NULL;
-}
-
-/** Associate this service to a consumer.
- *
- * Overwrites connection to any existing consumer.
- * \private \memberof mlt_service_s
- * \param this a service
- * \param that a consumer
- */
-
-static void mlt_service_connect( mlt_service this, mlt_service that )
-{
- if ( this != NULL )
- {
- // Get the service base
- mlt_service_base *base = this->local;
-
- // There's a bit more required here...
- base->out = that;
- }
-}
-
-/** Get the first connected producer.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the first producer
- */
-
-mlt_service mlt_service_get_producer( mlt_service this )
-{
- mlt_service producer = NULL;
-
- // Get the service base
- mlt_service_base *base = this->local;
-
- if ( base->in != NULL )
- producer = base->in[ 0 ];
-
- return producer;
-}
-
-/** Default implementation of the get_frame virtual function.
- *
- * \private \memberof mlt_service_s
- * \param this a service
- * \param[out] frame a frame by reference
- * \param index as determined by the producer
- * \return false
- */
-
-static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
-{
- mlt_service_base *base = this->local;
- if ( index < base->count )
- {
- mlt_service producer = base->in[ index ];
- if ( producer != NULL )
- return mlt_service_get_frame( producer, frame, index );
- }
- *frame = mlt_frame_init( this );
- return 0;
-}
-
-/** Return the properties object.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the properties
- */
-
-mlt_properties mlt_service_properties( mlt_service this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Recursively apply attached filters.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param frame a frame
- * \param index used to track depth of recursion, top caller should supply 0
- */
-
-void mlt_service_apply_filters( mlt_service this, mlt_frame frame, int index )
-{
- int i;
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
- mlt_properties service_properties = MLT_SERVICE_PROPERTIES( this );
- mlt_service_base *base = this->local;
- mlt_position position = mlt_frame_get_position( frame );
- mlt_position this_in = mlt_properties_get_position( service_properties, "in" );
- mlt_position this_out = mlt_properties_get_position( service_properties, "out" );
-
- if ( index == 0 || mlt_properties_get_int( service_properties, "_filter_private" ) == 0 )
- {
- // Process the frame with the attached filters
- for ( i = 0; i < base->filter_count; i ++ )
- {
- if ( base->filters[ i ] != NULL )
- {
- mlt_position in = mlt_filter_get_in( base->filters[ i ] );
- mlt_position out = mlt_filter_get_out( base->filters[ i ] );
- int disable = mlt_properties_get_int( MLT_FILTER_PROPERTIES( base->filters[ i ] ), "disable" );
- if ( !disable && ( ( in == 0 && out == 0 ) || ( position >= in && ( position <= out || out == 0 ) ) ) )
- {
- mlt_properties_set_position( frame_properties, "in", in == 0 ? this_in : in );
- mlt_properties_set_position( frame_properties, "out", out == 0 ? this_out : out );
- mlt_filter_process( base->filters[ i ], frame );
- mlt_service_apply_filters( MLT_FILTER_SERVICE( base->filters[ i ] ), frame, index + 1 );
- }
- }
- }
- }
-}
-
-/** Obtain a frame.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param[out] frame a frame by reference
- * \param index as determined by the producer
- * \return true if there was an error
- */
-
-int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
-{
- int result = 0;
-
- // Lock the service
- mlt_service_lock( this );
-
- // Ensure that the frame is NULL
- *frame = NULL;
-
- // Only process if we have a valid service
- if ( this != NULL && this->get_frame != NULL )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( this );
- mlt_position in = mlt_properties_get_position( properties, "in" );
- mlt_position out = mlt_properties_get_position( properties, "out" );
-
- result = this->get_frame( this, frame, index );
-
- if ( result == 0 )
- {
- mlt_properties_inc_ref( properties );
- properties = MLT_FRAME_PROPERTIES( *frame );
- if ( in >=0 && out > 0 )
- {
- mlt_properties_set_position( properties, "in", in );
- mlt_properties_set_position( properties, "out", out );
- }
- mlt_service_apply_filters( this, *frame, 1 );
- mlt_deque_push_back( MLT_FRAME_SERVICE_STACK( *frame ), this );
- }
- }
-
- // Make sure we return a frame
- if ( *frame == NULL )
- *frame = mlt_frame_init( this );
-
- // Unlock the service
- mlt_service_unlock( this );
-
- return result;
-}
-
-/** The service-changed event handler.
- *
- * \private \memberof mlt_service_s
- * \param owner ignored
- * \param this the service on which the "service-changed" event is fired
- */
-
-static void mlt_service_filter_changed( mlt_service owner, mlt_service this )
-{
- mlt_events_fire( MLT_SERVICE_PROPERTIES( this ), "service-changed", NULL );
-}
-
-/** Attach a filter.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param filter the filter to attach
- * \return true if there was an error
- */
-
-int mlt_service_attach( mlt_service this, mlt_filter filter )
-{
- int error = this == NULL || filter == NULL;
- if ( error == 0 )
- {
- int i = 0;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( this );
- mlt_service_base *base = this->local;
-
- for ( i = 0; error == 0 && i < base->filter_count; i ++ )
- if ( base->filters[ i ] == filter )
- error = 1;
-
- if ( error == 0 )
- {
- if ( base->filter_count == base->filter_size )
- {
- base->filter_size += 10;
- base->filters = realloc( base->filters, base->filter_size * sizeof( mlt_filter ) );
- }
-
- if ( base->filters != NULL )
- {
- mlt_properties props = MLT_FILTER_PROPERTIES( filter );
- mlt_properties_inc_ref( MLT_FILTER_PROPERTIES( filter ) );
- base->filters[ base->filter_count ++ ] = filter;
- mlt_events_fire( properties, "service-changed", NULL );
- mlt_events_listen( props, this, "service-changed", ( mlt_listener )mlt_service_filter_changed );
- mlt_events_listen( props, this, "property-changed", ( mlt_listener )mlt_service_filter_changed );
- }
- else
- {
- error = 2;
- }
- }
- }
- return error;
-}
-
-/** Detach a filter.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param filter the filter to detach
- * \return true if there was an error
- */
-
-int mlt_service_detach( mlt_service this, mlt_filter filter )
-{
- int error = this == NULL || filter == NULL;
- if ( error == 0 )
- {
- int i = 0;
- mlt_service_base *base = this->local;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( this );
-
- for ( i = 0; i < base->filter_count; i ++ )
- if ( base->filters[ i ] == filter )
- break;
-
- if ( i < base->filter_count )
- {
- base->filters[ i ] = NULL;
- for ( i ++ ; i < base->filter_count; i ++ )
- base->filters[ i - 1 ] = base->filters[ i ];
- base->filter_count --;
- mlt_events_disconnect( MLT_FILTER_PROPERTIES( filter ), this );
- mlt_filter_close( filter );
- mlt_events_fire( properties, "service-changed", NULL );
- }
- }
- return error;
-}
-
-/** Retrieve a filter.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \param index which one of potentially multiple filters
- * \return the filter or null if there was an error
- */
-
-mlt_filter mlt_service_filter( mlt_service this, int index )
-{
- mlt_filter filter = NULL;
- if ( this != NULL )
- {
- mlt_service_base *base = this->local;
- if ( index >= 0 && index < base->filter_count )
- filter = base->filters[ index ];
- }
- return filter;
-}
-
-/** Retrieve the profile.
- *
- * \public \memberof mlt_service_s
- * \param this a service
- * \return the profile
- */
-
-mlt_profile mlt_service_profile( mlt_service this )
-{
- return mlt_properties_get_data( MLT_SERVICE_PROPERTIES( this ), "_profile", NULL );
-}
-
-/** Destroy a service.
- *
- * \public \memberof mlt_service_s
- * \param this the service to destroy
- */
-
-void mlt_service_close( mlt_service this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_SERVICE_PROPERTIES( this ) ) <= 0 )
- {
- if ( this->close != NULL )
- {
- this->close( this->close_object );
- }
- else
- {
- mlt_service_base *base = this->local;
- int i = 0;
- int count = base->filter_count;
- mlt_events_block( MLT_SERVICE_PROPERTIES( this ), this );
- while( count -- )
- mlt_service_detach( this, base->filters[ 0 ] );
- free( base->filters );
- for ( i = 0; i < base->count; i ++ )
- if ( base->in[ i ] != NULL )
- mlt_service_close( base->in[ i ] );
- this->parent.close = NULL;
- free( base->in );
- pthread_mutex_destroy( &base->mutex );
- free( base );
- purge_cache( this );
- mlt_properties_close( &this->parent );
- }
- }
- else
- {
- mlt_service_unlock( this );
- }
-}
-
-/** Release a service's cache items.
- *
- * \private \memberof mlt_service_s
- * \param self a service
- */
-
-static void purge_cache( mlt_service self )
-{
- mlt_properties caches = mlt_properties_get_data( mlt_global_properties(), "caches", NULL );
-
- if ( caches )
- {
- int i = mlt_properties_count( caches );
- while ( i-- )
- {
- mlt_cache_purge( mlt_properties_get_data_at( caches, i, NULL ), self );
- mlt_properties_set_data( mlt_global_properties(), mlt_properties_get_name( caches, i ), NULL, 0, NULL, NULL );
- }
- }
-}
-
-/** Lookup the cache object for a service.
- *
- * \private \memberof mlt_service_s
- * \param self a service
- * \param name a name for the object
- * \return a cache
- */
-
-static mlt_cache get_cache( mlt_service self, const char *name )
-{
- mlt_cache result = NULL;
- mlt_properties caches = mlt_properties_get_data( mlt_global_properties(), "caches", NULL );
-
- if ( !caches )
- {
- caches = mlt_properties_new();
- mlt_properties_set_data( mlt_global_properties(), "caches", caches, 0, ( mlt_destructor )mlt_properties_close, NULL );
- }
- if ( caches )
- {
- result = mlt_properties_get_data( caches, name, NULL );
- if ( !result )
- {
- result = mlt_cache_init();
- mlt_properties_set_data( caches, name, result, 0, ( mlt_destructor )mlt_cache_close, NULL );
- }
- }
-
- return result;
-}
-
-/** Put an object into a service's cache.
- *
- * \public \memberof mlt_service_s
- * \param self a service
- * \param name a name for the object that is unique to the service class, but not to the instance
- * \param data an opaque pointer to the object to put into the cache
- * \param size the number of bytes pointed to by data
- * \param destructor a function that releases the data
- */
-
-void mlt_service_cache_put( mlt_service self, const char *name, void* data, int size, mlt_destructor destructor )
-{
- mlt_log( self, MLT_LOG_DEBUG, "%s: name %s object %p data %p\n", __FUNCTION__, name, self, data );
- mlt_cache cache = get_cache( self, name );
-
- if ( cache )
- mlt_cache_put( cache, self, data, size, destructor );
-}
-
-/** Get an object from a service's cache.
- *
- * \public \memberof mlt_service_s
- * \param self a service
- * \param name a name for the object that is unique to the service class, but not to the instance
- * \return a cache item or NULL if an object is not found
- * \see mlt_cache_item_data
- */
-
-mlt_cache_item mlt_service_cache_get( mlt_service self, const char *name )
-{
- mlt_log( self, MLT_LOG_DEBUG, "%s: name %s object %p\n", __FUNCTION__, name, self );
- mlt_cache_item result = NULL;
- mlt_cache cache = get_cache( self, name );
-
- if ( cache )
- result = mlt_cache_get( cache, self );
-
- return result;
-}
+++ /dev/null
-/**
- * \file mlt_service.h
- * \brief interface declaration for all service classes
- * \see mlt_service_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_SERVICE_H_
-#define _MLT_SERVICE_H_
-
-#include "mlt_properties.h"
-#include "mlt_types.h"
-
-/** \brief Service abstract base class
- *
- * \extends mlt_properties
- * The service is the base class for all of the interesting classes and
- * plugins for MLT. A service can have multiple inputs connections to
- * other services called its "producers" but only a single output to another
- * service called its "consumer." A service that has both producer and
- * consumer connections is called a filter. Any service can have zero or more
- * filters "attached" to it. We call any collection of services and their
- * connections a "service network," which is similar to what DirectShow calls
- * a filter graph or what gstreamer calls an element pipeline.
- *
- * \event \em service-changed
- * \event \em property-changed
- * \properties \em mlt_type identifies the subclass
- * \properties \em _mlt_service_hidden a flag that indicates whether to hide the mlt_service
- * \properties \em mlt_service is the name of the implementation of the service
- * \properties \em resource is either the stream identifier or grandchild-class
- * \properties \em in when to start, what is started is service-specific
- * \properties \em out when to stop
- * \properties \em _filter_private Set this on a service to ensure that attached filters are handled privately.
- * See modules/core/filter_region.c and modules/core/filter_watermark.c for examples.
- * \properties \em disable Set this on a filter to disable it while keeping it in the object model.
- * \properties \em _profile stores the mlt_profile for a service
- * \properties \em _unique_id is a unique identifier
- */
-
-struct mlt_service_s
-{
- struct mlt_properties_s parent; /**< \private */
-
- /** Get a frame of data (virtual function).
- *
- * \param mlt_producer a producer
- * \param mlt_frame_ptr a frame pointer by reference
- * \param int an index
- * \return true if there was an error
- */
- int ( *get_frame )( mlt_service self, mlt_frame_ptr frame, int index );
-
- /** the destructor virtual function */
- mlt_destructor close;
- void *close_object; /**< the object supplied to the close virtual function */
-
- void *local; /**< \private instance object */
- void *child; /**< \private the object of a subclass */
-};
-
-#define MLT_SERVICE_PROPERTIES( service ) ( &( service )->parent )
-
-extern int mlt_service_init( mlt_service self, void *child );
-extern void mlt_service_lock( mlt_service self );
-extern void mlt_service_unlock( mlt_service self );
-extern mlt_service_type mlt_service_identify( mlt_service self );
-extern int mlt_service_connect_producer( mlt_service self, mlt_service producer, int index );
-extern mlt_service mlt_service_get_producer( mlt_service self );
-extern int mlt_service_get_frame( mlt_service self, mlt_frame_ptr frame, int index );
-extern mlt_properties mlt_service_properties( mlt_service self );
-extern mlt_service mlt_service_consumer( mlt_service self );
-extern mlt_service mlt_service_producer( mlt_service self );
-extern int mlt_service_attach( mlt_service self, mlt_filter filter );
-extern int mlt_service_detach( mlt_service self, mlt_filter filter );
-extern void mlt_service_apply_filters( mlt_service self, mlt_frame frame, int index );
-extern mlt_filter mlt_service_filter( mlt_service self, int index );
-extern mlt_profile mlt_service_profile( mlt_service self );
-extern void mlt_service_close( mlt_service self );
-extern void mlt_service_cache_put( mlt_service self, const char *name, void* data, int size, mlt_destructor destructor );
-extern mlt_cache_item mlt_service_cache_get( mlt_service self, const char *name );
-
-#endif
-
+++ /dev/null
-/**
- * \file mlt_tokeniser.c
- * \brief string tokeniser
- * \see mlt_tokeniser_s
- *
- * Copyright (C) 2002-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* System header files */
-#include <stdlib.h>
-#include <string.h>
-
-/* Application header files */
-#include "mlt_tokeniser.h"
-
-/** Initialise a tokeniser.
-*/
-
-mlt_tokeniser mlt_tokeniser_init( )
-{
- return calloc( 1, sizeof( mlt_tokeniser_t ) );
-}
-
-/** Clear the tokeniser.
-*/
-
-static void mlt_tokeniser_clear( mlt_tokeniser tokeniser )
-{
- int index = 0;
- for ( index = 0; index < tokeniser->count; index ++ )
- free( tokeniser->tokens[ index ] );
- tokeniser->count = 0;
- free( tokeniser->input );
- tokeniser->input = NULL;
-}
-
-/** Append a string to the tokeniser.
-*/
-
-static int mlt_tokeniser_append( mlt_tokeniser tokeniser, char *token )
-{
- int error = 0;
-
- if ( tokeniser->count == tokeniser->size )
- {
- tokeniser->size += 20;
- tokeniser->tokens = realloc( tokeniser->tokens, tokeniser->size * sizeof( char * ) );
- }
-
- if ( tokeniser->tokens != NULL )
- {
- tokeniser->tokens[ tokeniser->count ++ ] = strdup( token );
- }
- else
- {
- tokeniser->count = 0;
- error = -1;
- }
- return error;
-}
-
-/** Parse a string by splitting on the delimiter provided.
-*/
-
-int mlt_tokeniser_parse_new( mlt_tokeniser tokeniser, char *string, const char *delimiter )
-{
- int count = 0;
- int length = strlen( string );
- int delimiter_size = strlen( delimiter );
- int index = 0;
- char *token = strdup( string );
-
- mlt_tokeniser_clear( tokeniser );
- tokeniser->input = strdup( string );
- strcpy( token, "" );
-
- for ( index = 0; index < length; )
- {
- char *start = string + index;
- char *end = strstr( start, delimiter );
-
- if ( end == NULL )
- {
- strcat( token, start );
- mlt_tokeniser_append( tokeniser, token );
- index = length;
- count ++;
- }
- else if ( start != end )
- {
- strncat( token, start, end - start );
- index += end - start;
- if ( strchr( token, '\"' ) == NULL || token[ strlen( token ) - 1 ] == '\"' )
- {
- mlt_tokeniser_append( tokeniser, token );
- strcpy( token, "" );
- count ++;
- }
- else while ( strncmp( string + index, delimiter, delimiter_size ) == 0 )
- {
- strncat( token, delimiter, delimiter_size );
- index += delimiter_size;
- }
- }
- else
- {
- index += strlen( delimiter );
- }
- }
-
- /* Special case - malformed string condition */
- if ( !strcmp( token, "" ) )
- {
- count = 0 - ( count - 1 );
- mlt_tokeniser_append( tokeniser, token );
- }
-
- free( token );
- return count;
-}
-
-/** Get the original input.
-*/
-
-char *mlt_tokeniser_get_input( mlt_tokeniser tokeniser )
-{
- return tokeniser->input;
-}
-
-/** Get the number of tokens.
-*/
-
-int mlt_tokeniser_count( mlt_tokeniser tokeniser )
-{
- return tokeniser->count;
-}
-
-/** Get a token as a string.
-*/
-
-char *mlt_tokeniser_get_string( mlt_tokeniser tokeniser, int index )
-{
- if ( index < tokeniser->count )
- return tokeniser->tokens[ index ];
- else
- return NULL;
-}
-
-/** Close the tokeniser.
-*/
-
-void mlt_tokeniser_close( mlt_tokeniser tokeniser )
-{
- mlt_tokeniser_clear( tokeniser );
- free( tokeniser->tokens );
- free( tokeniser );
-}
+++ /dev/null
-/**
- * \file mlt_tokeniser.h
- * \brief string tokeniser
- * \see mlt_tokeniser_s
- *
- * Copyright (C) 2002-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_TOKENISER_H_
-#define _MLT_TOKENISER_H_
-
-/** \brief Tokeniser class
- *
- */
-
-typedef struct
-{
- char *input;
- char **tokens;
- int count;
- int size;
-}
-*mlt_tokeniser, mlt_tokeniser_t;
-
-/* Remote parser API.
-*/
-
-extern mlt_tokeniser mlt_tokeniser_init( );
-extern int mlt_tokeniser_parse_new( mlt_tokeniser self, char *text, const char *delimiter );
-extern char *mlt_tokeniser_get_input( mlt_tokeniser self );
-extern int mlt_tokeniser_count( mlt_tokeniser self );
-extern char *mlt_tokeniser_get_string( mlt_tokeniser self, int index );
-extern void mlt_tokeniser_close( mlt_tokeniser self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_tractor.c
- * \brief tractor service class
- * \see mlt_tractor_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_tractor.h"
-#include "mlt_frame.h"
-#include "mlt_multitrack.h"
-#include "mlt_field.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-/* Forward references to static methods.
-*/
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track );
-static void mlt_tractor_listener( mlt_multitrack tracks, mlt_tractor this );
-
-/** Construct a tractor without a field or multitrack.
- *
- * Sets the resource property to "<tractor>", the mlt_type to "mlt_producer",
- * and mlt_service to "tractor".
- *
- * \public \memberof mlt_tractor_s
- * \return the new tractor
- */
-
-mlt_tractor mlt_tractor_init( )
-{
- mlt_tractor this = calloc( sizeof( struct mlt_tractor_s ), 1 );
- if ( this != NULL )
- {
- mlt_producer producer = &this->parent;
- if ( mlt_producer_init( producer, this ) == 0 )
- {
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- mlt_properties_set( properties, "resource", "<tractor>" );
- mlt_properties_set( properties, "mlt_type", "mlt_producer" );
- mlt_properties_set( properties, "mlt_service", "tractor" );
- mlt_properties_set_int( properties, "in", 0 );
- mlt_properties_set_int( properties, "out", -1 );
- mlt_properties_set_int( properties, "length", 0 );
-
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )mlt_tractor_close;
- producer->close_object = this;
- }
- else
- {
- free( this );
- this = NULL;
- }
- }
- return this;
-}
-
-/** Construct a tractor as well as a field and multitrack.
- *
- * Sets the resource property to "<tractor>", the mlt_type to "mlt_producer",
- * and mlt_service to "tractor".
- *
- * \public \memberof mlt_tractor_s
- * \return the new tractor
- */
-
-mlt_tractor mlt_tractor_new( )
-{
- mlt_tractor this = calloc( sizeof( struct mlt_tractor_s ), 1 );
- if ( this != NULL )
- {
- mlt_producer producer = &this->parent;
- if ( mlt_producer_init( producer, this ) == 0 )
- {
- mlt_multitrack multitrack = mlt_multitrack_init( );
- mlt_field field = mlt_field_new( multitrack, this );
- mlt_properties props = MLT_PRODUCER_PROPERTIES( producer );
-
- mlt_properties_set( props, "resource", "<tractor>" );
- mlt_properties_set( props, "mlt_type", "mlt_producer" );
- mlt_properties_set( props, "mlt_service", "tractor" );
- mlt_properties_set_position( props, "in", 0 );
- mlt_properties_set_position( props, "out", 0 );
- mlt_properties_set_position( props, "length", 0 );
- mlt_properties_set_data( props, "multitrack", multitrack, 0, ( mlt_destructor )mlt_multitrack_close, NULL );
- mlt_properties_set_data( props, "field", field, 0, ( mlt_destructor )mlt_field_close, NULL );
-
- mlt_events_listen( MLT_MULTITRACK_PROPERTIES( multitrack ), this, "producer-changed", ( mlt_listener )mlt_tractor_listener );
-
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )mlt_tractor_close;
- producer->close_object = this;
- }
- else
- {
- free( this );
- this = NULL;
- }
- }
- return this;
-}
-
-/** Get the service object associated to the tractor.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \return the parent service object
- * \see MLT_TRACTOR_SERVICE
- */
-
-mlt_service mlt_tractor_service( mlt_tractor this )
-{
- return MLT_PRODUCER_SERVICE( &this->parent );
-}
-
-/** Get the producer object associated to the tractor.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \return the parent producer object
- * \see MLT_TRACTOR_PRODUCER
- */
-
-mlt_producer mlt_tractor_producer( mlt_tractor this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the properties object associated to the tractor.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \return the tractor's property list
- * \see MLT_TRACTOR_PROPERTIES
- */
-
-mlt_properties mlt_tractor_properties( mlt_tractor this )
-{
- return MLT_PRODUCER_PROPERTIES( &this->parent );
-}
-
-/** Get the field this tractor is harvesting.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \return a field or NULL if there is no field for this tractor
- */
-
-mlt_field mlt_tractor_field( mlt_tractor this )
-{
- return mlt_properties_get_data( MLT_TRACTOR_PROPERTIES( this ), "field", NULL );
-}
-
-/** Get the multitrack this tractor is pulling.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \return a multitrack or NULL if there is none
- */
-
-mlt_multitrack mlt_tractor_multitrack( mlt_tractor this )
-{
- return mlt_properties_get_data( MLT_TRACTOR_PROPERTIES( this ), "multitrack", NULL );
-}
-
-/** Ensure the tractors in/out points match the multitrack.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- */
-
-void mlt_tractor_refresh( mlt_tractor this )
-{
- mlt_multitrack multitrack = mlt_tractor_multitrack( this );
- mlt_properties properties = MLT_MULTITRACK_PROPERTIES( multitrack );
- mlt_properties self = MLT_TRACTOR_PROPERTIES( this );
- mlt_events_block( properties, self );
- mlt_events_block( self, self );
- mlt_multitrack_refresh( multitrack );
- mlt_properties_set_position( self, "in", 0 );
- mlt_properties_set_position( self, "out", mlt_properties_get_position( properties, "out" ) );
- mlt_events_unblock( self, self );
- mlt_events_unblock( properties, self );
- mlt_properties_set_position( self, "length", mlt_properties_get_position( properties, "length" ) );
-}
-
-static void mlt_tractor_listener( mlt_multitrack tracks, mlt_tractor this )
-{
- mlt_tractor_refresh( this );
-}
-
-/** Connect the tractor.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \param producer a producer
- * \return true on error
- */
-
-int mlt_tractor_connect( mlt_tractor this, mlt_service producer )
-{
- int ret = mlt_service_connect_producer( MLT_TRACTOR_SERVICE( this ), producer, 0 );
-
- // This is the producer we're going to connect to
- if ( ret == 0 )
- this->producer = producer;
-
- return ret;
-}
-
-/** Set the producer for a specific track.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \param producer a producer
- * \param index the 0-based track index
- * \return true on error
- */
-
-int mlt_tractor_set_track( mlt_tractor this, mlt_producer producer, int index )
-{
- return mlt_multitrack_connect( mlt_tractor_multitrack( this ), producer, index );
-}
-
-/** Get the producer for a specific track.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- * \param index the 0-based track index
- * \return the producer for track \p index
- */
-
-mlt_producer mlt_tractor_get_track( mlt_tractor this, int index )
-{
- return mlt_multitrack_track( mlt_tractor_multitrack( this ), index );
-}
-
-static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- uint8_t *data = NULL;
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- mlt_frame frame = mlt_frame_pop_service( this );
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
- mlt_properties_set( frame_properties, "rescale.interp", mlt_properties_get( properties, "rescale.interp" ) );
- mlt_properties_set_int( frame_properties, "resize_alpha", mlt_properties_get_int( properties, "resize_alpha" ) );
- mlt_properties_set_int( frame_properties, "distort", mlt_properties_get_int( properties, "distort" ) );
- mlt_properties_set_double( frame_properties, "consumer_aspect_ratio", mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
- mlt_properties_set_int( frame_properties, "consumer_deinterlace", mlt_properties_get_int( properties, "consumer_deinterlace" ) );
- mlt_properties_set( frame_properties, "deinterlace_method", mlt_properties_get( properties, "deinterlace_method" ) );
- mlt_properties_set_int( frame_properties, "normalised_width", mlt_properties_get_int( properties, "normalised_width" ) );
- mlt_properties_set_int( frame_properties, "normalised_height", mlt_properties_get_int( properties, "normalised_height" ) );
- mlt_frame_get_image( frame, buffer, format, width, height, writable );
- mlt_properties_set_data( properties, "image", *buffer, *width * *height * 2, NULL, NULL );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
- mlt_properties_set_int( properties, "format", *format );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_frame_get_aspect_ratio( frame ) );
- mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( frame_properties, "progressive" ) );
- mlt_properties_set_int( properties, "distort", mlt_properties_get_int( frame_properties, "distort" ) );
- data = mlt_frame_get_alpha_mask( frame );
- mlt_properties_set_data( properties, "alpha", data, 0, NULL, NULL );
- return 0;
-}
-
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- mlt_frame frame = mlt_frame_pop_audio( this );
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- mlt_properties_set_data( properties, "audio", *buffer, 0, NULL, NULL );
- mlt_properties_set_int( properties, "frequency", *frequency );
- mlt_properties_set_int( properties, "channels", *channels );
- return 0;
-}
-
-static void destroy_data_queue( void *arg )
-{
- if ( arg != NULL )
- {
- // Assign the correct type
- mlt_deque queue = arg;
-
- // Iterate through each item and destroy them
- while ( mlt_deque_peek_front( queue ) != NULL )
- mlt_properties_close( mlt_deque_pop_back( queue ) );
-
- // Close the deque
- mlt_deque_close( queue );
- }
-}
-
-/** Get the next frame.
- *
- * \private \memberof mlt_tractor_s
- * \param parent the producer interface to the tractor
- * \param[out] frame a frame by reference
- * \param track the 0-based track index
- * \return true on error
- */
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int track )
-{
- mlt_tractor this = parent->child;
-
- // We only respond to the first track requests
- if ( track == 0 && this->producer != NULL )
- {
- int i = 0;
- int done = 0;
- mlt_frame temp = NULL;
- int count = 0;
- int image_count = 0;
-
- // Get the properties of the parent producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( parent );
-
- // Try to obtain the multitrack associated to the tractor
- mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );
-
- // Or a specific producer
- mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // The output frame will hold the 'global' data feeds (ie: those which are targetted for the final frame)
- mlt_deque data_queue = mlt_deque_init( );
-
- // Determine whether this tractor feeds to the consumer or stops here
- int global_feed = mlt_properties_get_int( properties, "global_feed" );
-
- // If we don't have one, we're in trouble...
- if ( multitrack != NULL )
- {
- // Used to garbage collect all frames
- char label[ 30 ];
-
- // Get the id of the tractor
- char *id = mlt_properties_get( properties, "_unique_id" );
-
- // Will be used to store the frame properties object
- mlt_properties frame_properties = NULL;
-
- // We'll store audio and video frames to use here
- mlt_frame audio = NULL;
- mlt_frame video = NULL;
- mlt_frame first_video = NULL;
-
- // Temporary properties
- mlt_properties temp_properties = NULL;
-
- // Get the multitrack's producer
- mlt_producer target = MLT_MULTITRACK_PRODUCER( multitrack );
- mlt_producer_seek( target, mlt_producer_frame( parent ) );
- mlt_producer_set_speed( target, mlt_producer_get_speed( parent ) );
-
- // We will create one frame and attach everything to it
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );
-
- // Get the properties of the frame
- frame_properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Loop through each of the tracks we're harvesting
- for ( i = 0; !done; i ++ )
- {
- // Get a frame from the producer
- mlt_service_get_frame( this->producer, &temp, i );
-
- // Get the temporary properties
- temp_properties = MLT_FRAME_PROPERTIES( temp );
-
- // Check for last track
- done = mlt_properties_get_int( temp_properties, "last_track" );
-
- // Handle fx only tracks
- if ( mlt_properties_get_int( temp_properties, "fx_cut" ) )
- {
- int hide = ( video == NULL ? 1 : 0 ) | ( audio == NULL ? 2 : 0 );
- mlt_properties_set_int( temp_properties, "hide", hide );
- }
-
- // We store all frames with a destructor on the output frame
- sprintf( label, "_%s_%d", id, count ++ );
- mlt_properties_set_data( frame_properties, label, temp, 0, ( mlt_destructor )mlt_frame_close, NULL );
-
- // We want to append all 'final' feeds to the global queue
- if ( !done && mlt_properties_get_data( temp_properties, "data_queue", NULL ) != NULL )
- {
- // Move the contents of this queue on to the output frames data queue
- mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "data_queue", NULL );
- mlt_deque temp = mlt_deque_init( );
- while ( global_feed && mlt_deque_count( sub_queue ) )
- {
- mlt_properties p = mlt_deque_pop_back( sub_queue );
- if ( mlt_properties_get_int( p, "final" ) )
- mlt_deque_push_back( data_queue, p );
- else
- mlt_deque_push_back( temp, p );
- }
- while( mlt_deque_count( temp ) )
- mlt_deque_push_front( sub_queue, mlt_deque_pop_back( temp ) );
- mlt_deque_close( temp );
- }
-
- // Now do the same with the global queue but without the conditional behaviour
- if ( mlt_properties_get_data( temp_properties, "global_queue", NULL ) != NULL )
- {
- mlt_deque sub_queue = mlt_properties_get_data( MLT_FRAME_PROPERTIES( temp ), "global_queue", NULL );
- while ( mlt_deque_count( sub_queue ) )
- {
- mlt_properties p = mlt_deque_pop_back( sub_queue );
- mlt_deque_push_back( data_queue, p );
- }
- }
-
- // Pick up first video and audio frames
- if ( !done && !mlt_frame_is_test_audio( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 2 ) )
- {
- // Order of frame creation is starting to get problematic
- if ( audio != NULL )
- {
- mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), producer_get_audio );
- mlt_deque_push_front( MLT_FRAME_AUDIO_STACK( temp ), audio );
- }
- audio = temp;
- }
- if ( !done && !mlt_frame_is_test_card( temp ) && !( mlt_properties_get_int( temp_properties, "hide" ) & 1 ) )
- {
- if ( video != NULL )
- {
- mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), producer_get_image );
- mlt_deque_push_front( MLT_FRAME_IMAGE_STACK( temp ), video );
- }
- video = temp;
- if ( first_video == NULL )
- first_video = temp;
-
- // Ensure that all frames know the aspect ratio of the background
- mlt_properties_set_double( temp_properties, "output_ratio",
- mlt_properties_get_double( MLT_FRAME_PROPERTIES( first_video ), "aspect_ratio" ) );
-
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( temp ), "image_count", ++ image_count );
- image_count = 1;
- }
- }
-
- // Now stack callbacks
- if ( audio != NULL )
- {
- mlt_frame_push_audio( *frame, audio );
- mlt_frame_push_audio( *frame, producer_get_audio );
- }
-
- if ( video != NULL )
- {
- mlt_properties video_properties = MLT_FRAME_PROPERTIES( first_video );
- mlt_frame_push_service( *frame, video );
- mlt_frame_push_service( *frame, producer_get_image );
- if ( global_feed )
- mlt_properties_set_data( frame_properties, "data_queue", data_queue, 0, NULL, NULL );
- mlt_properties_set_data( video_properties, "global_queue", data_queue, 0, destroy_data_queue, NULL );
- mlt_properties_set_int( frame_properties, "width", mlt_properties_get_int( video_properties, "width" ) );
- mlt_properties_set_int( frame_properties, "height", mlt_properties_get_int( video_properties, "height" ) );
- mlt_properties_set_int( frame_properties, "real_width", mlt_properties_get_int( video_properties, "real_width" ) );
- mlt_properties_set_int( frame_properties, "real_height", mlt_properties_get_int( video_properties, "real_height" ) );
- mlt_properties_set_int( frame_properties, "progressive", mlt_properties_get_int( video_properties, "progressive" ) );
- mlt_properties_set_double( frame_properties, "aspect_ratio", mlt_properties_get_double( video_properties, "aspect_ratio" ) );
- mlt_properties_set_int( frame_properties, "image_count", image_count );
- }
- else
- {
- destroy_data_queue( data_queue );
- }
-
- mlt_frame_set_position( *frame, mlt_producer_frame( parent ) );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_audio", audio == NULL );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", video == NULL );
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "consumer_lock_service", this, 0, NULL, NULL );
- }
- else if ( producer != NULL )
- {
- mlt_producer_seek( producer, mlt_producer_frame( parent ) );
- mlt_producer_set_speed( producer, mlt_producer_get_speed( parent ) );
- mlt_service_get_frame( this->producer, frame, track );
- }
- else
- {
- mlt_log( MLT_PRODUCER_SERVICE( parent ), MLT_LOG_ERROR, "tractor without a multitrack!!\n" );
- mlt_service_get_frame( this->producer, frame, track );
- }
-
- // Prepare the next frame
- mlt_producer_prepare_next( parent );
-
- // Indicate our found status
- return 0;
- }
- else
- {
- // Generate a test card
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( parent ) );
- return 0;
- }
-}
-
-/** Close the tractor and free its resources.
- *
- * \public \memberof mlt_tractor_s
- * \param this a tractor
- */
-
-void mlt_tractor_close( mlt_tractor this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_TRACTOR_PROPERTIES( this ) ) <= 0 )
- {
- this->parent.close = NULL;
- mlt_producer_close( &this->parent );
- free( this );
- }
-}
-
+++ /dev/null
-/**
- * \file mlt_tractor.h
- * \brief tractor service class
- * \see mlt_tractor_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_TRACTOR_H_
-#define _MLT_TRACTOR_H_
-
-#include "mlt_producer.h"
-
-/** \brief Tractor class
- *
- * The tractor is a convenience class that works with the field class
- * to manage a multitrack, track filters, and transitions.
- *
- * \extends mlt_producer_s
- * \properties \em multitrack holds a reference to the mulitrack object that a tractor manages
- * \properties \em field holds a reference to the field object that a tractor manages
- * \properties \em producer holds a reference to an encapsulated producer
- * \properties \em global_feed a flag to indicate whether this tractor feeds to the consumer or stops here
- * \properties \em global_queue is something for the data_feed functionality in the core module
- * \properties \em data_queue is something for the data_feed functionality in the core module
- */
-
-struct mlt_tractor_s
-{
- struct mlt_producer_s parent;
- mlt_service producer;
-};
-
-#define MLT_TRACTOR_PRODUCER( tractor ) ( &( tractor )->parent )
-#define MLT_TRACTOR_SERVICE( tractor ) MLT_PRODUCER_SERVICE( MLT_TRACTOR_PRODUCER( tractor ) )
-#define MLT_TRACTOR_PROPERTIES( tractor ) MLT_SERVICE_PROPERTIES( MLT_TRACTOR_SERVICE( tractor ) )
-
-extern mlt_tractor mlt_tractor_init( );
-extern mlt_tractor mlt_tractor_new( );
-extern mlt_service mlt_tractor_service( mlt_tractor self );
-extern mlt_producer mlt_tractor_producer( mlt_tractor self );
-extern mlt_properties mlt_tractor_properties( mlt_tractor self );
-extern mlt_field mlt_tractor_field( mlt_tractor self );
-extern mlt_multitrack mlt_tractor_multitrack( mlt_tractor self );
-extern int mlt_tractor_connect( mlt_tractor self, mlt_service service );
-extern void mlt_tractor_refresh( mlt_tractor self );
-extern int mlt_tractor_set_track( mlt_tractor self, mlt_producer producer, int index );
-extern mlt_producer mlt_tractor_get_track( mlt_tractor self, int index );
-extern void mlt_tractor_close( mlt_tractor self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_transition.c
- * \brief abstraction for all transition services
- * \see mlt_transition_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "mlt_transition.h"
-#include "mlt_frame.h"
-#include "mlt_log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Forward references */
-
-static int transition_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
-
-/** Initialize a new transition.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \param child the object of a subclass
- * \return true on error
- */
-
-int mlt_transition_init( mlt_transition this, void *child )
-{
- mlt_service service = &this->parent;
- memset( this, 0, sizeof( struct mlt_transition_s ) );
- this->child = child;
- if ( mlt_service_init( service, this ) == 0 )
- {
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- service->get_frame = transition_get_frame;
- service->close = ( mlt_destructor )mlt_transition_close;
- service->close_object = this;
-
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 0 );
- mlt_properties_set_int( properties, "a_track", 0 );
- mlt_properties_set_int( properties, "b_track", 1 );
-
- return 0;
- }
- return 1;
-}
-
-/** Create and initialize a new transition.
- *
- * \public \memberof mlt_transition_s
- * \return a new transition
- */
-
-mlt_transition mlt_transition_new( )
-{
- mlt_transition this = calloc( 1, sizeof( struct mlt_transition_s ) );
- if ( this != NULL )
- mlt_transition_init( this, NULL );
- return this;
-}
-
-/** Get the service class interface.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the service class
- * \see MLT_TRANSITION_SERVICE
- */
-
-mlt_service mlt_transition_service( mlt_transition this )
-{
- return this != NULL ? &this->parent : NULL;
-}
-
-/** Get the properties interface.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the transition's properties
- * \see MLT_TRANSITION_PROPERTIES
- */
-
-mlt_properties mlt_transition_properties( mlt_transition this )
-{
- return MLT_TRANSITION_PROPERTIES( this );
-}
-
-/** Connect this transition with a producers a and b tracks.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \param producer a producer
- * \param a_track the track index of the first input
- * \param b_track the track index of the second index
- * \return true on error
- */
-
-int mlt_transition_connect( mlt_transition this, mlt_service producer, int a_track, int b_track )
-{
- int ret = mlt_service_connect_producer( &this->parent, producer, a_track );
- if ( ret == 0 )
- {
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- this->producer = producer;
- mlt_properties_set_int( properties, "a_track", a_track );
- mlt_properties_set_int( properties, "b_track", b_track );
- }
- return ret;
-}
-
-/** Set the starting and ending time for when the transition is active.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \param in the starting time
- * \param out the ending time
- */
-
-void mlt_transition_set_in_and_out( mlt_transition this, mlt_position in, mlt_position out )
-{
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- mlt_properties_set_position( properties, "in", in );
- mlt_properties_set_position( properties, "out", out );
-}
-
-/** Get the index of the a track.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the 0-based index of the track of the first producer
- */
-
-int mlt_transition_get_a_track( mlt_transition this )
-{
- return mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "a_track" );
-}
-
-/** Get the index of the b track.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the 0-based index of the track of the second producer
- */
-
-int mlt_transition_get_b_track( mlt_transition this )
-{
- return mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "b_track" );
-}
-
-/** Get the in point.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the starting time
- */
-
-mlt_position mlt_transition_get_in( mlt_transition this )
-{
- return mlt_properties_get_position( MLT_TRANSITION_PROPERTIES( this ), "in" );
-}
-
-/** Get the out point.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \return the ending time
- */
-
-mlt_position mlt_transition_get_out( mlt_transition this )
-{
- return mlt_properties_get_position( MLT_TRANSITION_PROPERTIES( this ), "out" );
-}
-
-/** Process the frame.
- *
- * If we have no process method (unlikely), we simply return the a_frame unmolested.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- * \param a_frame a frame from the first producer
- * \param b_frame a frame from the second producer
- * \return a frame
- */
-
-mlt_frame mlt_transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
-{
- if ( this->process == NULL )
- return a_frame;
- else
- return this->process( this, a_frame, b_frame );
-}
-
-/** Get a frame from this transition.
-
- The logic is complex here. A transition is typically applied to frames on the a and
- b tracks specified in the connect method above and only if both contain valid info
- for the transition type (this is either audio or image).
-
- However, the fixed a_track may not always contain data of the correct type, eg:
-<pre>
- +---------+ +-------+
- |c1 | |c5 | <-- A(0,1) <-- B(0,2) <-- get frame
- +---------+ +---------+-+-----+ | |
- |c4 | <------+ |
- +----------+-----------+-+---------+ |
- |c2 |c3 | <-----------------+
- +----------+-------------+
-</pre>
- During the overlap of c1 and c2, there is nothing for the A transition to do, so this
- results in a no operation, but B is triggered. During the overlap of c2 and c3, again,
- the A transition is inactive and because the B transition is pointing at track 0,
- it too would be inactive. This isn't an ideal situation - it's better if the B
- transition simply treats the frames from c3 as though they're the a track.
-
- For this to work, we cache all frames coming from all tracks between the a and b
- tracks. Before we process, we determine that the b frame contains someting of the
- right type and then we determine which frame to use as the a frame (selecting a
- matching frame from a_track to b_track - 1). If both frames contain data of the
- correct type, we process the transition.
-
- This method is invoked for each track and we return the cached frames as needed.
- We clear the cache only when the requested frame is flagged as a 'last_track' frame.
-
- * \private \memberof mlt_transition_s
- * \param service a service
- * \param[out] frame a frame by reference
- * \param index 0-based track index
- * \return true on error
- */
-
-static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
-{
- int error = 0;
- mlt_transition this = service->child;
-
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- int accepts_blanks = mlt_properties_get_int( properties, "accepts_blanks" );
- int a_track = mlt_properties_get_int( properties, "a_track" );
- int b_track = mlt_properties_get_int( properties, "b_track" );
- mlt_position in = mlt_properties_get_position( properties, "in" );
- mlt_position out = mlt_properties_get_position( properties, "out" );
- int always_active = mlt_properties_get_int( properties, "always_active" );
- int type = mlt_properties_get_int( properties, "_transition_type" );
- int reverse_order = 0;
-
- // Ensure that we have the correct order
- if ( a_track > b_track )
- {
- reverse_order = 1;
- a_track = b_track;
- b_track = mlt_properties_get_int( properties, "a_track" );
- }
-
- // Only act on this operation once per multitrack iteration from the tractor
- if ( !this->held )
- {
- int active = 0;
- int i = 0;
- int a_frame = a_track;
- int b_frame = b_track;
- mlt_position position;
- int ( *invalid )( mlt_frame ) = type == 1 ? mlt_frame_is_test_card : mlt_frame_is_test_audio;
-
- // Initialise temporary store
- if ( this->frames == NULL )
- this->frames = calloc( sizeof( mlt_frame ), b_track + 1 );
-
- // Get all frames between a and b
- for( i = a_track; i <= b_track; i ++ )
- mlt_service_get_frame( this->producer, &this->frames[ i ], i );
-
- // We're holding these frames until the last_track frame property is received
- this->held = 1;
-
- // When we need to locate the a_frame
- switch( type )
- {
- case 1:
- case 2:
- // Some transitions (esp. audio) may accept blank frames
- active = accepts_blanks;
-
- // If we're not active then...
- if ( !active )
- {
- // Hunt for the a_frame
- while( a_frame <= b_frame && invalid( this->frames[ a_frame ] ) )
- a_frame ++;
-
- // Determine if we're active now
- active = a_frame != b_frame && !invalid( this->frames[ b_frame ] );
- }
- break;
-
- default:
- mlt_log( service, MLT_LOG_ERROR, "invalid transition type\n" );
- break;
- }
-
- // Now handle the non-always active case
- if ( active && !always_active )
- {
- // For non-always-active transitions, we need the current position of the a frame
- position = mlt_frame_get_position( this->frames[ a_frame ] );
-
- // If a is in range, we're active
- active = position >= in && position <= out;
- }
-
- // Finally, process the a and b frames
- if ( active )
- {
- mlt_frame a_frame_ptr = this->frames[ !reverse_order ? a_frame : b_frame ];
- mlt_frame b_frame_ptr = this->frames[ !reverse_order ? b_frame : a_frame ];
- int a_hide = mlt_properties_get_int( MLT_FRAME_PROPERTIES( a_frame_ptr ), "hide" );
- int b_hide = mlt_properties_get_int( MLT_FRAME_PROPERTIES( b_frame_ptr ), "hide" );
- if ( !( a_hide & type ) && !( b_hide & type ) )
- {
- // Process the transition
- *frame = mlt_transition_process( this, a_frame_ptr, b_frame_ptr );
-
- // We need to ensure that the tractor doesn't consider this frame for output
- if ( *frame == a_frame_ptr )
- b_hide |= type;
- else
- a_hide |= type;
-
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( a_frame_ptr ), "hide", a_hide );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( b_frame_ptr ), "hide", b_hide );
- }
- }
- }
-
- // Obtain the frame from the cache or the producer we're attached to
- if ( index >= a_track && index <= b_track )
- *frame = this->frames[ index ];
- else
- error = mlt_service_get_frame( this->producer, frame, index );
-
- // Determine if that was the last track
- this->held = !mlt_properties_get_int( MLT_FRAME_PROPERTIES( *frame ), "last_track" );
-
- return error;
-}
-
-/** Close and destroy the transition.
- *
- * \public \memberof mlt_transition_s
- * \param this a transition
- */
-
-void mlt_transition_close( mlt_transition this )
-{
- if ( this != NULL && mlt_properties_dec_ref( MLT_TRANSITION_PROPERTIES( this ) ) <= 0 )
- {
- this->parent.close = NULL;
- if ( this->close != NULL )
- {
- this->close( this );
- }
- else
- {
- mlt_service_close( &this->parent );
- free( this->frames );
- free( this );
- }
- }
-}
+++ /dev/null
-/**
- * \file mlt_transition.h
- * \brief abstraction for all transition services
- * \see mlt_transition_s
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_TRANSITION_H_
-#define _MLT_TRANSITION_H_
-
-#include "mlt_service.h"
-
-/** \brief Transition abstract service class
- *
- * A transition may modify the output of a producer based on the output of a second producer.
- *
- * \extends mlt_service_s
- * \properties \em a_track the track index (0-based) of a multitrack of the first producer
- * \properties \em b_track the track index (0-based) of a multitrack of the second producer
- * \properties \em accepts_blanks a flag to indicate if the transition should accept blank frames
- * \properties \em always_active a flag to indicate that the in and out points do not apply
- * \properties \em _transition_type 1 for video, 2 for audio
- */
-
-struct mlt_transition_s
-{
- /** We're implementing service here */
- struct mlt_service_s parent;
-
- /** public virtual */
- void ( *close )( mlt_transition );
-
- /** protected transition method */
- mlt_frame ( *process )( mlt_transition, mlt_frame, mlt_frame );
-
- /** Protected */
- void *child;
-
- /** track and in/out points */
- mlt_service producer;
-
- /** Private */
- mlt_frame *frames;
- int held;
-};
-
-#define MLT_TRANSITION_SERVICE( transition ) ( &( transition )->parent )
-#define MLT_TRANSITION_PROPERTIES( transition ) MLT_SERVICE_PROPERTIES( MLT_TRANSITION_SERVICE( transition ) )
-
-extern int mlt_transition_init( mlt_transition self, void *child );
-extern mlt_transition mlt_transition_new( );
-extern mlt_service mlt_transition_service( mlt_transition self );
-extern mlt_properties mlt_transition_properties( mlt_transition self );
-extern int mlt_transition_connect( mlt_transition self, mlt_service producer, int a_track, int b_track );
-extern void mlt_transition_set_in_and_out( mlt_transition self, mlt_position in, mlt_position out );
-extern int mlt_transition_get_a_track( mlt_transition self );
-extern int mlt_transition_get_b_track( mlt_transition self );
-extern mlt_position mlt_transition_get_in( mlt_transition self );
-extern mlt_position mlt_transition_get_out( mlt_transition self );
-extern mlt_frame mlt_transition_process( mlt_transition self, mlt_frame a_frame, mlt_frame b_frame );
-extern void mlt_transition_close( mlt_transition self );
-
-#endif
+++ /dev/null
-/**
- * \file mlt_types.h
- * \brief Provides forward definitions of all public types
- *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
- * \author Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _MLT_TYPES_H_
-#define _MLT_TYPES_H_
-
-#ifndef GCC_VERSION
-#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#endif
-
-#include <stdint.h>
-
-#include "mlt_pool.h"
-
-/** The set of supported image formats */
-
-typedef enum
-{
- mlt_image_none = 0,/**< image not available */
- mlt_image_rgb24, /**< 8-bit RGB */
- mlt_image_rgb24a, /**< 8-bit RGB with alpha channel */
- mlt_image_yuv422, /**< 8-bit YUV 4:2:2 packed */
- mlt_image_yuv420p, /**< 8-bit YUV 4:2:0 planar */
- mlt_image_opengl /**< suitable for OpenGL texture */
-}
-mlt_image_format;
-
-/** The set of supported audio formats */
-
-typedef enum
-{
- mlt_audio_none = 0,/**< audio not available */
- mlt_audio_pcm /**< signed 16-bit interleaved PCM */
-}
-mlt_audio_format;
-
-/** The relative time qualifiers */
-
-typedef enum
-{
- mlt_whence_relative_start, /**< relative to the beginning */
- mlt_whence_relative_current,/**< relative to the current position */
- mlt_whence_relative_end /**< relative to the end */
-}
-mlt_whence;
-
-/** The recognized subclasses of mlt_service */
-
-typedef enum
-{
- invalid_type, /**< invalid service */
- unknown_type, /**< unknown class */
- producer_type, /**< Producer class */
- tractor_type, /**< Tractor class */
- playlist_type, /**< Playlist class */
- multitrack_type, /**< Multitrack class */
- filter_type, /**< Filter class */
- transition_type, /**< Transition class */
- consumer_type, /**< Consumer class */
- field_type /**< Field class */
-}
-mlt_service_type;
-
-/* I don't want to break anyone's applications without warning. -Zach */
-#undef DOUBLE_MLT_POSITION
-#ifdef DOUBLE_MLT_POSITION
-typedef double mlt_position;
-#else
-typedef int32_t mlt_position;
-#endif
-
-typedef struct mlt_frame_s *mlt_frame, **mlt_frame_ptr; /**< pointer to Frame object */
-typedef struct mlt_property_s *mlt_property; /**< pointer to Property object */
-typedef struct mlt_properties_s *mlt_properties; /**< pointer to Properties object */
-typedef struct mlt_event_struct *mlt_event; /**< pointer to Event object */
-typedef struct mlt_service_s *mlt_service; /**< pointer to Service object */
-typedef struct mlt_producer_s *mlt_producer; /**< pointer to Producer object */
-typedef struct mlt_playlist_s *mlt_playlist; /**< pointer to Playlist object */
-typedef struct mlt_multitrack_s *mlt_multitrack; /**< pointer to Multitrack object */
-typedef struct mlt_filter_s *mlt_filter; /**< pointer to Filter object */
-typedef struct mlt_transition_s *mlt_transition; /**< pointer to Transition object */
-typedef struct mlt_tractor_s *mlt_tractor; /**< pointer to Tractor object */
-typedef struct mlt_field_s *mlt_field; /**< pointer to Field object */
-typedef struct mlt_consumer_s *mlt_consumer; /**< pointer to Consumer object */
-typedef struct mlt_parser_s *mlt_parser; /**< pointer to Properties object */
-typedef struct mlt_deque_s *mlt_deque; /**< pointer to Deque object */
-typedef struct mlt_geometry_s *mlt_geometry; /**< pointer to Geometry object */
-typedef struct mlt_geometry_item_s *mlt_geometry_item; /**< pointer to Geometry Item object */
-typedef struct mlt_profile_s *mlt_profile; /**< pointer to Profile object */
-typedef struct mlt_repository_s *mlt_repository; /**< pointer to Repository object */
-typedef struct mlt_cache_s *mlt_cache; /**< pointer to Cache object */
-typedef struct mlt_cache_item_s *mlt_cache_item; /**< pointer to CacheItem object */
-
-typedef void ( *mlt_destructor )( void * ); /**< pointer to destructor function */
-typedef char *( *mlt_serialiser )( void *, int length );/**< pointer to serialization function */
-
-#define MLT_SERVICE(x) ( ( mlt_service )( x ) ) /**< Cast to a Service pointer */
-#define MLT_PRODUCER(x) ( ( mlt_producer )( x ) ) /**< Cast to a Producer pointer */
-#define MLT_MULTITRACK(x) ( ( mlt_multitrack )( x ) ) /**< Cast to a Multitrack pointer */
-#define MLT_PLAYLIST(x) ( ( mlt_playlist )( x ) ) /**< Cast to a Playlist pointer */
-#define MLT_TRACTOR(x) ( ( mlt_tractor )( x ) ) /**< Cast to a Tractor pointer */
-#define MLT_FILTER(x) ( ( mlt_filter )( x ) ) /**< Cast to a Filter pointer */
-#define MLT_TRANSITION(x) ( ( mlt_transition )( x ) ) /**< Cast to a Transition pointer */
-
-#endif
+++ /dev/null
-include ../../config.mak
-
-TARGET = inigo
-
-OBJS = inigo.o \
- io.o
-
-CFLAGS += -I.. $(RDYNAMIC) -DVERSION=\"$(version)\"
-
-LDFLAGS += -L../framework -lmlt -lpthread
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -d "$(DESTDIR)$(bindir)"
- install -c -s -m 755 $(TARGET) "$(DESTDIR)$(bindir)"
-
-uninstall:
- rm -f "$(DESTDIR)$(bindir)/$(TARGET)"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * inigo.c -- MLT command line utility
- * Copyright (C) 2002-2008 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sched.h>
-
-#include <framework/mlt.h>
-
-#ifdef __DARWIN__
-#include <SDL.h>
-#endif
-
-#include "io.h"
-
-static void transport_action( mlt_producer producer, char *value )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL );
- mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL );
-
- mlt_properties_set_int( properties, "stats_off", 1 );
-
- if ( strlen( value ) == 1 )
- {
- switch( value[ 0 ] )
- {
- case 'q':
- mlt_properties_set_int( properties, "done", 1 );
- break;
- case '0':
- mlt_producer_set_speed( producer, 1 );
- mlt_producer_seek( producer, 0 );
- break;
- case '1':
- mlt_producer_set_speed( producer, -10 );
- break;
- case '2':
- mlt_producer_set_speed( producer, -5 );
- break;
- case '3':
- mlt_producer_set_speed( producer, -2 );
- break;
- case '4':
- mlt_producer_set_speed( producer, -1 );
- break;
- case '5':
- mlt_producer_set_speed( producer, 0 );
- break;
- case '6':
- case ' ':
- mlt_producer_set_speed( producer, 1 );
- break;
- case '7':
- mlt_producer_set_speed( producer, 2 );
- break;
- case '8':
- mlt_producer_set_speed( producer, 5 );
- break;
- case '9':
- mlt_producer_set_speed( producer, 10 );
- break;
- case 'd':
- if ( multitrack != NULL )
- {
- int i = 0;
- mlt_position last = -1;
- fprintf( stderr, "\n" );
- for ( i = 0; 1; i ++ )
- {
- mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_start, i );
- if ( time == last )
- break;
- last = time;
- fprintf( stderr, "%d: %d\n", i, (int)time );
- }
- }
- break;
-
- case 'g':
- if ( multitrack != NULL )
- {
- mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 0 );
- mlt_producer_seek( producer, time );
- }
- break;
- case 'H':
- if ( producer != NULL )
- {
- mlt_position position = mlt_producer_position( producer );
- mlt_producer_seek( producer, position - ( mlt_producer_get_fps( producer ) * 60 ) );
- }
- break;
- case 'h':
- if ( producer != NULL )
- {
- mlt_position position = mlt_producer_position( producer );
- mlt_producer_set_speed( producer, 0 );
- mlt_producer_seek( producer, position - 1 );
- }
- break;
- case 'j':
- if ( multitrack != NULL )
- {
- mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, 1 );
- mlt_producer_seek( producer, time );
- }
- break;
- case 'k':
- if ( multitrack != NULL )
- {
- mlt_position time = mlt_multitrack_clip( multitrack, mlt_whence_relative_current, -1 );
- mlt_producer_seek( producer, time );
- }
- break;
- case 'l':
- if ( producer != NULL )
- {
- mlt_position position = mlt_producer_position( producer );
- if ( mlt_producer_get_speed( producer ) != 0 )
- mlt_producer_set_speed( producer, 0 );
- else
- mlt_producer_seek( producer, position + 1 );
- }
- break;
- case 'L':
- if ( producer != NULL )
- {
- mlt_position position = mlt_producer_position( producer );
- mlt_producer_seek( producer, position + ( mlt_producer_get_fps( producer ) * 60 ) );
- }
- break;
- }
-
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "refresh", 1 );
- }
-
- mlt_properties_set_int( properties, "stats_off", 0 );
-}
-
-static mlt_consumer create_consumer( mlt_profile profile, char *id )
-{
- char *arg = id != NULL ? strchr( id, ':' ) : NULL;
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_consumer consumer = mlt_factory_consumer( profile, id, arg );
- if ( consumer != NULL )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
- mlt_properties_set_data( properties, "transport_callback", transport_action, 0, NULL, NULL );
- }
- return consumer;
-}
-
-#ifdef __DARWIN__
-
-static void event_handling( mlt_producer producer, mlt_consumer consumer )
-{
- SDL_Event event;
-
- while ( SDL_PollEvent( &event ) )
- {
- switch( event.type )
- {
- case SDL_QUIT:
- mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( consumer ), "done", 1 );
- break;
-
- case SDL_KEYDOWN:
- if ( event.key.keysym.unicode < 0x80 && event.key.keysym.unicode > 0 )
- {
- char keyboard[ 2 ] = { event.key.keysym.unicode, 0 };
- transport_action( producer, keyboard );
- }
- break;
- }
- }
-}
-
-#endif
-
-static void transport( mlt_producer producer, mlt_consumer consumer )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- int silent = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "silent" );
- int progress = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "progress" );
- struct timespec tm = { 0, 40000 };
- int total_length = mlt_producer_get_length( producer );
- int last_position = 0;
-
- if ( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) )
- {
- if ( !silent && !progress )
- {
- term_init( );
-
- fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" );
- fprintf( stderr, "|1=-10| |2= -5| |3= -2| |4= -1| |5= 0| |6= 1| |7= 2| |8= 5| |9= 10|\n" );
- fprintf( stderr, "+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+\n" );
-
- fprintf( stderr, "+---------------------------------------------------------------------+\n" );
- fprintf( stderr, "| H = back 1 minute, L = forward 1 minute |\n" );
- fprintf( stderr, "| h = previous frame, l = next frame |\n" );
- fprintf( stderr, "| g = start of clip, j = next clip, k = previous clip |\n" );
- fprintf( stderr, "| 0 = restart, q = quit, space = play |\n" );
- fprintf( stderr, "+---------------------------------------------------------------------+\n" );
- }
-
- while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) )
- {
- int value = ( silent || progress )? -1 : term_read( );
-
- if ( value != -1 )
- {
- char string[ 2 ] = { value, 0 };
- transport_action( producer, string );
- }
-
-#ifdef __DARWIN__
- event_handling( producer, consumer );
-#endif
-
- if ( !silent && mlt_properties_get_int( properties, "stats_off" ) == 0 )
- {
- if ( progress )
- {
- int current_position = mlt_producer_position( producer );
- if ( current_position > last_position )
- {
- fprintf( stderr, "Current Frame: %10d, percentage: %10d\r",
- current_position, 100 * current_position / total_length );
- last_position = current_position;
- }
- }
- else
- {
- fprintf( stderr, "Current Position: %10d\r", (int)mlt_producer_position( producer ) );
- }
- }
-
- if ( silent )
- nanosleep( &tm, NULL );
- }
-
- if ( !silent )
- fprintf( stderr, "\n" );
- }
-}
-
-static void query_metadata( mlt_repository repo, mlt_service_type type, const char *typestr, char *id )
-{
- mlt_properties metadata = mlt_repository_metadata( repo, type, id );
- if ( metadata )
- {
- char *s = mlt_properties_serialise_yaml( metadata );
- fprintf( stderr, "%s", s );
- free( s );
- }
- else
- {
- fprintf( stderr, "# No metadata for %s \"%s\"\n", typestr, id );
- }
-}
-
-static void query_services( mlt_repository repo, mlt_service_type type )
-{
- mlt_properties services = NULL;
- const char *typestr = NULL;
- switch ( type )
- {
- case consumer_type:
- services = mlt_repository_consumers( repo );
- typestr = "consumers";
- break;
- case filter_type:
- services = mlt_repository_filters( repo );
- typestr = "filters";
- break;
- case producer_type:
- services = mlt_repository_producers( repo );
- typestr = "producers";
- break;
- case transition_type:
- services = mlt_repository_transitions( repo );
- typestr = "transitions";
- break;
- default:
- return;
- }
- fprintf( stderr, "---\n%s:\n", typestr );
- if ( services )
- {
- int j;
- for ( j = 0; j < mlt_properties_count( services ); j++ )
- fprintf( stderr, " - %s\n", mlt_properties_get_name( services, j ) );
- }
- fprintf( stderr, "...\n" );
-}
-
-int main( int argc, char **argv )
-{
- int i;
- mlt_consumer consumer = NULL;
- mlt_producer inigo = NULL;
- FILE *store = NULL;
- char *name = NULL;
- mlt_profile profile = NULL;
- int is_progress = 0;
- int is_silent = 0;
-
- // Construct the factory
- mlt_repository repo = mlt_factory_init( NULL );
-
- for ( i = 1; i < argc; i ++ )
- {
- // Check for serialisation switch
- if ( !strcmp( argv[ i ], "-serialise" ) )
- {
- name = argv[ ++ i ];
- if ( name != NULL && strstr( name, ".inigo" ) )
- store = fopen( name, "w" );
- else
- {
- if ( name == NULL || name[0] == '-' )
- store = stdout;
- name = NULL;
- }
- }
- // Look for the profile option
- else if ( !strcmp( argv[ i ], "-profile" ) )
- {
- const char *pname = argv[ ++ i ];
- if ( pname && pname[0] != '-' )
- profile = mlt_profile_init( pname );
- }
- else if ( !strcmp( argv[ i ], "-progress" ) )
- {
- is_progress = 1;
- }
- // Look for the query option
- else if ( !strcmp( argv[ i ], "-query" ) )
- {
- const char *pname = argv[ ++ i ];
- if ( pname && pname[0] != '-' )
- {
- if ( !strcmp( pname, "consumers" ) || !strcmp( pname, "consumer" ) )
- query_services( repo, consumer_type );
- else if ( !strcmp( pname, "filters" ) || !strcmp( pname, "filter" ) )
- query_services( repo, filter_type );
- else if ( !strcmp( pname, "producers" ) || !strcmp( pname, "producer" ) )
- query_services( repo, producer_type );
- else if ( !strcmp( pname, "transitions" ) || !strcmp( pname, "transition" ) )
- query_services( repo, transition_type );
-
- else if ( !strncmp( pname, "consumer=", 9 ) )
- query_metadata( repo, consumer_type, "consumer", strchr( pname, '=' ) + 1 );
- else if ( !strncmp( pname, "filter=", 7 ) )
- query_metadata( repo, filter_type, "filter", strchr( pname, '=' ) + 1 );
- else if ( !strncmp( pname, "producer=", 9 ) )
- query_metadata( repo, producer_type, "producer", strchr( pname, '=' ) + 1 );
- else if ( !strncmp( pname, "transition=", 11 ) )
- query_metadata( repo, transition_type, "transition", strchr( pname, '=' ) + 1 );
- else
- goto query_all;
- }
- else
- {
-query_all:
- query_services( repo, consumer_type );
- query_services( repo, filter_type );
- query_services( repo, producer_type );
- query_services( repo, transition_type );
- fprintf( stderr, "# You can query the metadata for a specific service using:\n"
- "# -query <type>=<identifer>\n"
- "# where <type> is one of: consumer, filter, producer, or transition.\n" );
- }
- goto exit_factory;
- }
- else if ( !strcmp( argv[ i ], "-silent" ) )
- {
- is_silent = 1;
- }
- else if ( !strcmp( argv[ i ], "-verbose" ) )
- {
- mlt_log_set_level( MLT_LOG_VERBOSE );
- }
- else if ( !strcmp( argv[ i ], "-version" ) || !strcmp( argv[ i ], "--version" ) )
- {
- fprintf( stderr, "MLT inigo " VERSION "\n"
- "Copyright (C) 2002-2008 Ushodaya Enterprises Limited\n"
- "<http://www.mltframework.org/>\n"
- "This is free software; see the source for copying conditions. There is NO\n"
- "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
- );
- goto exit_factory;
- }
- else if ( !strcmp( argv[ i ], "-debug" ) )
- {
- mlt_log_set_level( MLT_LOG_DEBUG );
- }
- }
-
- // Create profile if not set explicitly
- if ( profile == NULL )
- profile = mlt_profile_init( NULL );
-
- // Look for the consumer option
- for ( i = 1; i < argc; i ++ )
- {
- if ( !strcmp( argv[ i ], "-consumer" ) )
- {
- consumer = create_consumer( profile, argv[ ++ i ] );
- if ( consumer )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
- while ( argv[ i + 1 ] != NULL && strstr( argv[ i + 1 ], "=" ) )
- mlt_properties_parse( properties, argv[ ++ i ] );
- }
- }
- }
-
- // If we have no consumer, default to sdl
- if ( store == NULL && consumer == NULL )
- consumer = create_consumer( profile, NULL );
-
- // Get inigo producer
- if ( argc > 1 )
- inigo = mlt_factory_producer( profile, "inigo", &argv[ 1 ] );
-
- // Set transport properties on consumer and produder
- if ( consumer != NULL && inigo != NULL )
- {
- mlt_properties_set_data( MLT_CONSUMER_PROPERTIES( consumer ), "transport_producer", inigo, 0, NULL, NULL );
- mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( inigo ), "transport_consumer", consumer, 0, NULL, NULL );
- if ( is_progress )
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "progress", is_progress );
- if ( is_silent )
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( consumer ), "silent", is_silent );
- }
-
- if ( argc > 1 && inigo != NULL && mlt_producer_get_length( inigo ) > 0 )
- {
- // Parse the arguments
- for ( i = 1; i < argc; i ++ )
- {
- if ( !strcmp( argv[ i ], "-serialise" ) )
- {
- if ( store != stdout )
- i ++;
- }
- else
- {
- if ( store != NULL )
- fprintf( store, "%s\n", argv[ i ] );
-
- i ++;
-
- while ( argv[ i ] != NULL && argv[ i ][ 0 ] != '-' )
- {
- if ( store != NULL )
- fprintf( store, "%s\n", argv[ i ] );
- i += 1;
- }
-
- i --;
- }
- }
-
- if ( consumer != NULL && store == NULL )
- {
- // Get inigo's properties
- mlt_properties inigo_props = MLT_PRODUCER_PROPERTIES( inigo );
-
- // Get the last group
- mlt_properties group = mlt_properties_get_data( inigo_props, "group", 0 );
-
- // Apply group settings
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
- mlt_properties_inherit( properties, group );
-
- // Connect consumer to inigo
- mlt_consumer_connect( consumer, MLT_PRODUCER_SERVICE( inigo ) );
-
- // Start the consumer
- mlt_consumer_start( consumer );
-
- // Transport functionality
- transport( inigo, consumer );
-
- // Stop the consumer
- mlt_consumer_stop( consumer );
- }
- else if ( store != NULL && store != stdout && name != NULL )
- {
- fprintf( stderr, "Project saved as %s.\n", name );
- fclose( store );
- }
- }
- else
- {
- fprintf( stderr,
-"Usage: inigo [options] [producer [name=value]* ]+\n"
-"Options:\n"
-" -attach filter[:arg] [name=value]* Attach a filter to the output\n"
-" -attach-cut filter[:arg] [name=value]* Attach a filter to a cut\n"
-" -attach-track filter[:arg] [name=value]* Attach a filter to a track\n"
-" -attach-clip filter[:arg] [name=value]* Attach a filter to a producer\n"
-" -audio-track | -hide-video Add an audio-only track\n"
-" -blank frames Add blank silence to a track\n"
-" -consumer id[:arg] [name=value]* Set the consumer (sink)\n"
-" -debug Set the logging level to debug\n"
-" -filter filter[:arg] [name=value]* Add a filter to the current track\n"
-" -group [name=value]* Apply properties repeatedly\n"
-" -help Show this message\n"
-" -join clips Join multiple clips into one cut\n"
-" -mix length Add a mix between the last two cuts\n"
-" -mixer transition Add a transition to the mix\n"
-" -null-track | -hide-track Add a hidden track\n"
-" -profile name Set the processing settings\n"
-" -progress Display progress along with position\n"
-" -remove Remove the most recent cut\n"
-" -repeat times Repeat the last cut\n"
-" -query List all of the registered services\n"
-" -query \"consumers\" | \"consumer\"=id List consumers or show info about one\n"
-" -query \"filters\" | \"filter\"=id List filters or show info about one\n"
-" -query \"producers\" | \"producer\"=id List producers or show info about one\n"
-" -query \"transitions\" | \"transition\"=id List transitions, show info about one\n"
-" -serialise [filename] Write the commands to a text file\n"
-" -silent Do not display position/transport\n"
-" -split relative-frame Split the last cut into two cuts\n"
-" -swap Rearrange the last two cuts\n"
-" -track Add a track\n"
-" -transition id[:arg] [name=value]* Add a transition\n"
-" -verbose Set the logging level to verbose\n"
-" -version Show the version and copyright\n"
-" -video-track | -hide-audio Add a video-only track\n"
-"For more help: <http://www.mltframework.org/>\n" );
- }
-
- // Close the consumer
- if ( consumer != NULL )
- mlt_consumer_close( consumer );
-
- // Close the producer
- if ( inigo != NULL )
- mlt_producer_close( inigo );
-
- // Close the factory
- mlt_profile_close( profile );
-
-exit_factory:
-
- mlt_factory_close( );
-
- return 0;
-}
+++ /dev/null
-/*
- * io.c -- inigo input/output
- * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* System header files */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-/* Application header files */
-#include "io.h"
-
-char *chomp( char *input )
-{
- if ( input != NULL )
- {
- int length = strlen( input );
- if ( length && input[ length - 1 ] == '\n' )
- input[ length - 1 ] = '\0';
- if ( length > 1 && input[ length - 2 ] == '\r' )
- input[ length - 2 ] = '\0';
- }
- return input;
-}
-
-char *trim( char *input )
-{
- if ( input != NULL )
- {
- int length = strlen( input );
- int first = 0;
- while( first < length && isspace( input[ first ] ) )
- first ++;
- memmove( input, input + first, length - first + 1 );
- length = length - first;
- while ( length > 0 && isspace( input[ length - 1 ] ) )
- input[ -- length ] = '\0';
- }
- return input;
-}
-
-char *strip_quotes( char *input )
-{
- if ( input != NULL )
- {
- char *ptr = strrchr( input, '\"' );
- if ( ptr != NULL )
- *ptr = '\0';
- if ( input[ 0 ] == '\"' )
- strcpy( input, input + 1 );
- }
- return input;
-}
-
-int *get_int( int *output, int use )
-{
- int *value = NULL;
- char temp[ 132 ];
- *output = use;
- if ( trim( chomp( fgets( temp, 132, stdin ) ) ) != NULL )
- {
- if ( strcmp( temp, "" ) )
- *output = atoi( temp );
- value = output;
- }
- return value;
-}
-
-/** This stores the previous settings
-*/
-
-static struct termios oldtty;
-static int mode = 0;
-
-/** This is called automatically on application exit to restore the
- previous tty settings.
-*/
-
-void term_exit(void)
-{
- if ( mode == 1 )
- {
- tcsetattr( 0, TCSANOW, &oldtty );
- mode = 0;
- }
-}
-
-/** Init terminal so that we can grab keys without blocking.
-*/
-
-void term_init( )
-{
- struct termios tty;
-
- tcgetattr( 0, &tty );
- oldtty = tty;
-
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
- tty.c_cflag &= ~(CSIZE|PARENB);
- tty.c_cflag |= CS8;
- tty.c_cc[ VMIN ] = 1;
- tty.c_cc[ VTIME ] = 0;
-
- tcsetattr( 0, TCSANOW, &tty );
-
- mode = 1;
-
- atexit( term_exit );
-}
-
-/** Check for a keypress without blocking infinitely.
- Returns: ASCII value of keypress or -1 if no keypress detected.
-*/
-
-int term_read( )
-{
- int n = 1;
- unsigned char ch;
- struct timeval tv;
- fd_set rfds;
-
- FD_ZERO( &rfds );
- FD_SET( 0, &rfds );
- tv.tv_sec = 0;
- tv.tv_usec = 40000;
- n = select( 1, &rfds, NULL, NULL, &tv );
- if (n > 0)
- {
- n = read( 0, &ch, 1 );
- tcflush( 0, TCIFLUSH );
- if (n == 1)
- return ch;
- return n;
- }
- return -1;
-}
-
-char get_keypress( )
-{
- char value = '\0';
- int pressed = 0;
-
- fflush( stdout );
-
- term_init( );
- while ( ( pressed = term_read( ) ) == -1 ) ;
- term_exit( );
-
- value = (char)pressed;
-
- return value;
-}
-
-void wait_for_any_key( char *message )
-{
- if ( message == NULL )
- printf( "Press any key to continue: " );
- else
- printf( "%s", message );
-
- get_keypress( );
-
- printf( "\n\n" );
-}
-
-void beep( )
-{
- printf( "%c", 7 );
- fflush( stdout );
-}
+++ /dev/null
-/*
- * io.h -- inigo input/output
- * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DEMO_IO_H_
-#define _DEMO_IO_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-extern char *chomp( char * );
-extern char *trim( char * );
-extern char *strip_quotes( char * );
-extern char *get_string( char *, int, char * );
-extern int *get_int( int *, int );
-extern void term_init( );
-extern int term_read( );
-extern void term_exit( );
-extern char get_keypress( );
-extern void wait_for_any_key( char * );
-extern void beep( );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-include ../../config.mak
-include make.inc
-
-all clean depend:
- list='$(SUBDIRS)'; \
- for subdir in $$list; do \
- if [ -f $$subdir/Makefile -a ! -f disable-$$subdir ] ; \
- then $(MAKE) -C $$subdir $@ || exit 1; \
- fi \
- done
-
-distclean:
- rm -f consumers.dat filters.dat producers.dat transitions.dat make.inc; \
- list='$(SUBDIRS)'; \
- for subdir in $$list; do \
- if [ -f $$subdir/Makefile -a ! -f disable-$$subdir ] ; \
- then $(MAKE) -C $$subdir $@ || exit 1; \
- fi \
- done
-
-install:
- list='$(SUBDIRS)'; \
- for subdir in $$list; do \
- if [ -f $$subdir/Makefile -a ! -f disable-$$subdir ] ; \
- then $(MAKE) DESTDIR=$(DESTDIR) -C $$subdir $@ || exit 1; \
- fi \
- done
-
-uninstall:
- rm -rf "$(DESTDIR)$(libdir)/mlt"
-
+++ /dev/null
-include ../../../config.mak
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-include config.mak
-
-LDFLAGS += -lavformat$(AVFORMAT_SUFFIX)
-LDFLAGS += -lavcodec$(AVFORMAT_SUFFIX)
-LDFLAGS += -lavutil$(AVFORMAT_SUFFIX)
-LDFLAGS += -lavdevice$(AVFORMAT_SUFFIX) $(EXTRA_LIBS)
-
-ifndef CODECS
-TARGET = ../libmltffmpeg$(LIBSUF)
-else
-TARGET = ../libmltavformat$(LIBSUF)
-endif
-
-OBJS = factory.o
-
-ifdef FILTERS
-OBJS += filter_avcolour_space.o \
- filter_avresample.o \
- filter_avdeinterlace.o
-ifdef SWSCALE
-OBJS += filter_swscale.o
-endif
-CFLAGS += -DFILTERS
-endif
-
-ifdef CODECS
-OBJS += producer_avformat.o \
- consumer_avformat.o
-CFLAGS += -DCODECS
-endif
-
-ifdef SWSCALE
-CFLAGS += -DSWSCALE
-LDFLAGS += -lswscale$(AVFORMAT_SUFFIX)
-endif
-
-ifdef LOCAL_FFMPEG
-LOCAL_FFMPEG_OBJS = ffmpeg/libavformat/libavformat$(AVFORMAT_SUFFIX) \
- ffmpeg/libavcodec/libavcodec$(AVFORMAT_SUFFIX) \
- ffmpeg/libavutil/libavutil$(AVFORMAT_SUFFIX) \
- ffmpeg/libavutil/libavdevice$(AVFORMAT_SUFFIX)
-endif
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(LOCAL_FFMPEG_OBJS):
- if [ $(LOCAL_FFMPEG) ] ; then \
- $(MAKE) -C ffmpeg ffmpeg ; \
- fi
-
-$(TARGET): $(OBJS) $(LOCAL_FFMPEG_OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- if [ $(LOCAL_FFMPEG) ] ; then $(MAKE) -C ffmpeg dep ; fi
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- if [ $(LOCAL_FFMPEG) ] ; then $(MAKE) -C ffmpeg distclean ; fi
- rm -f .depend
-
-clean:
- #if [ $(LOCAL_FFMPEG) ] ; then $(MAKE) -C ffmpeg clean ; fi
- rm -f $(OBJS) ../libmltffmpeg$(LIBSUF) ../libmltavformat$(LIBSUF)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
- install -d "$(DESTDIR)$(prefix)/share/mlt/avformat"
- install -m 644 producer_avformat.yml "$(DESTDIR)$(prefix)/share/mlt/avformat"
-
-uninstall:
- rm "$(DESTDIR)$(libdir)/mlt/libmltavformat$(LIBSUF)" 2> /dev/null || true
- rm "$(DESTDIR)$(libdir)/mlt/libmltffmpeg$(LIBSUF)" 2> /dev/null || true
- rm -rf "$(DESTDIR)$(prefix)/share/mlt/avformat"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * audio conversion
- * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
- * Copyright (c) 2008 Peter Ross
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_AUDIOCONVERT_H
-#define AVCODEC_AUDIOCONVERT_H
-
-/**
- * @file audioconvert.h
- * Audio format conversion routines
- */
-
-
-#include "avcodec.h"
-
-
-/**
- * Generate string corresponding to the sample format with
- * number sample_fmt, or a header if sample_fmt is negative.
- *
- * @param[in] buf the buffer where to write the string
- * @param[in] buf_size the size of buf
- * @param[in] sample_fmt the number of the sample format to print the corresponding info string, or
- * a negative value to print the corresponding header.
- * Meaningful values for obtaining a sample format info vary from 0 to SAMPLE_FMT_NB -1.
- */
-void avcodec_sample_fmt_string(char *buf, int buf_size, int sample_fmt);
-
-/**
- * @return NULL on error
- */
-const char *avcodec_get_sample_fmt_name(int sample_fmt);
-
-/**
- * @return SAMPLE_FMT_NONE on error
- */
-enum SampleFormat avcodec_get_sample_fmt(const char* name);
-
-/**
- * @return NULL on error
- */
-const char *avcodec_get_channel_name(int channel_id);
-
-/**
- * Return description of channel layout
- */
-void avcodec_get_channel_layout_string(char *buf, int buf_size, int nb_channels, int64_t channel_layout);
-
-/**
- * Guess the channel layout
- * @param nb_channels
- * @param codec_id Codec identifier, or CODEC_ID_NONE if unknown
- * @param fmt_name Format name, or NULL if unknown
- * @return Channel layout mask
- */
-int64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name);
-
-
-struct AVAudioConvert;
-typedef struct AVAudioConvert AVAudioConvert;
-
-/**
- * Create an audio sample format converter context
- * @param out_fmt Output sample format
- * @param out_channels Number of output channels
- * @param in_fmt Input sample format
- * @param in_channels Number of input channels
- * @param[in] matrix Channel mixing matrix (of dimension in_channel*out_channels). Set to NULL to ignore.
- * @param flags See FF_MM_xx
- * @return NULL on error
- */
-AVAudioConvert *av_audio_convert_alloc(enum SampleFormat out_fmt, int out_channels,
- enum SampleFormat in_fmt, int in_channels,
- const float *matrix, int flags);
-
-/**
- * Free audio sample format converter context
- */
-void av_audio_convert_free(AVAudioConvert *ctx);
-
-/**
- * Convert between audio sample formats
- * @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel.
- * @param[in] out_stride distance between consecutive input samples (measured in bytes)
- * @param[in] in array of input buffers for each channel
- * @param[in] in_stride distance between consecutive output samples (measured in bytes)
- * @param len length of audio frame size (measured in samples)
- */
-int av_audio_convert(AVAudioConvert *ctx,
- void * const out[6], const int out_stride[6],
- const void * const in[6], const int in_stride[6], int len);
-
-#endif /* AVCODEC_AUDIOCONVERT_H */
+++ /dev/null
-#!/bin/sh
-
-# Determine whether to recommend/use the HEAD revision of FFmpeg (unreleased)
-# or a specific revision based upon whether the last digit of our version
-# is even or odd. An odd MLT version number always represents unreleased.
-svn_rev="17887"
-micro_version=$(echo $version | cut -d . -f 3)
-odd_version=$(($micro_version % 2))
-[ "$odd_version" -eq "1" ] && svn_rev="HEAD"
-
-if [ "$help" = "1" ]
-then
- cat << EOF
-FFMPEG/avformat options:
-
- --avformat-svn - Obtain ffmpeg from Subversion
- --avformat-svn-extra - Add extra configure options for --avformat-svn
- --avformat-shared=path - Link against a shared installation of ffmpeg (default)
- --avformat-static=path - Link against a static ffmpeg dev tree
- --avformat-ldextra=libs - Provide additional libs to link with
- --avformat-suffix=suff - Specify a custom suffix for an ffmpeg shared build
- --avformat-swscale - Use ffmpeg libswcale instead of img_convert
- --avformat-no-codecs - Disable the producer and consumer to avoid the FFmpeg codecs
- --avformat-no-filters - Disable the filters to make a codecs+muxers-only plugin
-
- NOTE: The recommended version of FFmpeg is SVN-r$svn_rev.
-
-EOF
-
-else
- targetos=$(uname -s)
- case $targetos in
- Darwin)
- export LIBSUF=.dylib
- ;;
- Linux|FreeBSD)
- export LIBSUF=.so
- ;;
- *)
- ;;
- esac
-
- bits=$(uname -m)
- case $bits in
- x86_64)
- [ -d /usr/lib/lib64 ] && export LIBDIR=lib64 || export LIBDIR=lib
- ;;
- *)
- export LIBDIR=lib
- ;;
- esac
-
- echo > config.mak
-
- export static_ffmpeg=
- export shared_ffmpeg=$(pkg-config --variable=prefix libavformat)
- export extra_libs=
- export svn_ffmpeg=
- export svn_ffmpeg_extra=
- export avformat_suffix=
- export swscale=
- export codecs=true
- export filters=true
-
- for i in "$@"
- do
- case $i in
- --avformat-static=* ) static_ffmpeg="${i#--avformat-static=}" ;;
- --avformat-shared=* ) shared_ffmpeg="${i#--avformat-shared=}" ;;
- --avformat-ldextra=* ) extra_libs="${i#--avformat-ldextra=}" ;;
- --avformat-svn ) svn_ffmpeg=true ;;
- --avformat-svn-extra=* ) svn_ffmpeg_extra="${i#--avformat-svn-extra=}" ;;
- --avformat-cvs ) svn_ffmpeg=true ;;
- --avformat-suffix=* ) avformat_suffix="${i#--avformat-suffix=}" ;;
- --avformat-swscale ) swscale=true ;;
- --avformat-swscaler ) swscale=true ;;
- --avformat-no-codecs ) codecs=false ;;
- --avformat-no-filters ) filters=false ;;
- esac
- done
-
- if [ "$svn_ffmpeg" != "" ]
- then
- if [ "$gpl" = "true" ]
- then
- enable_gpl="--enable-gpl"
- [ "$swscale" != "" ] && [ "$svn_rev" = "17887" ] &&
- enable_swscale="--enable-swscale"
- fi
- if [ ! -d "ffmpeg" ]
- then
- echo
- echo "Checking out ffmpeg/avformat revision $svn_rev - no password required"
- echo
- if [ "$svn_rev" = "17887" ]; then
- svn checkout -r $svn_rev svn://svn.mplayerhq.hu/ffmpeg/branches/0.5 ffmpeg
- else
- svn checkout -r $svn_rev svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
- fi
- fi
- [ -d "ffmpeg" ] && ( cd ffmpeg ; ./configure $enable_gpl $enable_swscale $svn_ffmpeg_extra )
- #[ ! -f "ffmpeg/ffmpeg.patch" ] && ( cd ffmpeg ; cp ../ffmpeg.patch . ; patch -p0 < ffmpeg.patch )
- echo "CFLAGS+=-I`pwd`/ffmpeg -I`pwd`/ffmpeg/libavformat -I`pwd`/ffmpeg/libavcodec -I`pwd`/ffmpeg/libavutil -I`pwd`/ffmpeg/libavdevice" >> config.mak
- echo "LDFLAGS+=-L`pwd`/ffmpeg/libavformat -L`pwd`/ffmpeg/libavcodec -L`pwd`/ffmpeg/libavutil -L`pwd`/ffmpeg/libavdevice" >> config.mak
- if [ "$swscale" != "" ] || [ "$svn_rev" = "HEAD" ]
- then
- echo "CFLAGS+=-I`pwd`/ffmpeg/libswscale" >> config.mak
- echo "LDFLAGS+=-L`pwd`/ffmpeg/libswscale" >> config.mak
- echo "SWSCALE=1" >> config.mak
- fi
- [ $targetos = "Darwin" ] &&
- echo "LDFLAGS+=-single_module" >> config.mak
- echo "LOCAL_FFMPEG=1" >> config.mak
- echo "LDFLAGS+=-Wl,-Bsymbolic" >> config.mak
- extra_libs="$extra_libs -lz -lbz2"
- elif [ "$static_ffmpeg" != "" ]
- then
- if [ -d "$static_ffmpeg" ]
- then
- echo "CFLAGS+=-I$static_ffmpeg/libavformat -I$static_ffmpeg/libavcodec -I$static_ffmpeg/libavutil -I$static_ffmpeg/libavdevice" >> config.mak
- echo "LDFLAGS+=-L$static_ffmpeg/libavformat -L$static_ffmpeg/libavcodec -L$static_ffmpeg/libavutil -L$static_ffmpeg/libavdevice" >> config.mak
- [ $targetos = "Darwin" ] &&
- echo "LDFLAGS+=-single_module" >> config.mak
- if [ "$swscale" != "" ]
- then
- echo "CFLAGS+=-I$static_ffmpeg/libswscale" >> config.mak
- echo "LDFLAGS+=-L$static_ffmpeg/libswscale" >> config.mak
- echo "SWSCALE=1" >> config.mak
- fi
- echo "LDFLAGS+=-Wl,-Bsymbolic" >> config.mak
- extra_libs="$extra_libs -lz"
- else
- echo "avformat: Invalid path specified: $static_ffmpeg"
- touch ../disable-avformat
- echo 0
- fi
- elif [ "$shared_ffmpeg" != "" ]
- then
- echo "PREFIX=$shared_ffmpeg" >> config.mak
- echo "CFLAGS+=$(pkg-config --cflags libavformat) $TMP_CFLAGS" >> config.mak
- echo "LDFLAGS+=$(pkg-config --libs libavformat)" >> config.mak
- [ -d "$shared_ffmpeg/include/ffmpeg/libavformat" ] &&
- echo "CFLAGS+=-I$shared_ffmpeg/include/ffmpeg/libavformat -I$shared_ffmpeg/include/ffmpeg/libavcodec" >> config.mak
- [ -d "$shared_ffmpeg/include/libavformat" ] &&
- echo "CFLAGS+=-I$shared_ffmpeg/include/libavformat -I$shared_ffmpeg/include/libavcodec" >> config.mak
- avcodec_version=$(pkg-config --modversion libavcodec)
- if [ "$swscale" != "" ] || ( [ $(echo $avcodec_version | cut -d. -f1) -ge 52 ] && [ $(echo $avcodec_version | cut -d. -f2) -ge 21 ] )
- then
- [ -d "$shared_ffmpeg/include/ffmpeg/libswscale" ] &&
- echo "CFLAGS+=-I$shared_ffmpeg/include/ffmpeg/libswscale" >> config.mak
- [ -d "$shared_ffmpeg/include/libswscale" ] &&
- echo "CFLAGS+=-I$shared_ffmpeg/include/libswscale" >> config.mak
- echo "SWSCALE=1" >> config.mak
- fi
- else
- echo "avformat: No build environment found. "
- echo " Try configuring mlt with --avformat-svn."
- touch ../disable-avformat
- exit 0
- fi
-
- echo "EXTRA_LIBS=$extra_libs" >> config.mak
- echo "AVFORMAT_SUFFIX=$avformat_suffix" >> config.mak
- [ "$codecs" = "true" ] && echo "CODECS=1" >> config.mak
- [ "$filters" = "true" ] && echo "FILTERS=1" >> config.mak
- exit 0
-
-fi
+++ /dev/null
-/*
- * consumer_avformat.c -- an encoder based on avformat
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- * Much code borrowed from ffmpeg.c: Copyright (c) 2000-2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// mlt Header files
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_profile.h>
-
-// System header files
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <pthread.h>
-#include <sys/time.h>
-#include <math.h>
-#include <unistd.h>
-
-// avformat header files
-#include <avformat.h>
-#ifdef SWSCALE
-#include <swscale.h>
-#endif
-#include <opt.h>
-
-#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_RGB32 PIX_FMT_RGBA32
-#define PIX_FMT_YUYV422 PIX_FMT_YUV422
-#endif
-
-//
-// This structure should be extended and made globally available in mlt
-//
-
-typedef struct
-{
- int16_t *buffer;
- int size;
- int used;
- double time;
- int frequency;
- int channels;
-}
-*sample_fifo, sample_fifo_s;
-
-sample_fifo sample_fifo_init( int frequency, int channels )
-{
- sample_fifo this = calloc( 1, sizeof( sample_fifo_s ) );
- this->frequency = frequency;
- this->channels = channels;
- return this;
-}
-
-// sample_fifo_clear and check are temporarily aborted (not working as intended)
-
-void sample_fifo_clear( sample_fifo this, double time )
-{
- int words = ( float )( time - this->time ) * this->frequency * this->channels;
- if ( ( int )( ( float )time * 100 ) < ( int )( ( float )this->time * 100 ) && this->used > words && words > 0 )
- {
- memmove( this->buffer, &this->buffer[ words ], ( this->used - words ) * sizeof( int16_t ) );
- this->used -= words;
- this->time = time;
- }
- else if ( ( int )( ( float )time * 100 ) != ( int )( ( float )this->time * 100 ) )
- {
- this->used = 0;
- this->time = time;
- }
-}
-
-void sample_fifo_check( sample_fifo this, double time )
-{
- if ( this->used == 0 )
- {
- if ( ( int )( ( float )time * 100 ) < ( int )( ( float )this->time * 100 ) )
- this->time = time;
- }
-}
-
-void sample_fifo_append( sample_fifo this, int16_t *samples, int count )
-{
- if ( ( this->size - this->used ) < count )
- {
- this->size += count * 5;
- this->buffer = realloc( this->buffer, this->size * sizeof( int16_t ) );
- }
-
- memcpy( &this->buffer[ this->used ], samples, count * sizeof( int16_t ) );
- this->used += count;
-}
-
-int sample_fifo_used( sample_fifo this )
-{
- return this->used;
-}
-
-int sample_fifo_fetch( sample_fifo this, int16_t *samples, int count )
-{
- if ( count > this->used )
- count = this->used;
-
- memcpy( samples, this->buffer, count * sizeof( int16_t ) );
- this->used -= count;
- memmove( this->buffer, &this->buffer[ count ], this->used * sizeof( int16_t ) );
-
- this->time += ( double )count / this->channels / this->frequency;
-
- return count;
-}
-
-void sample_fifo_close( sample_fifo this )
-{
- free( this->buffer );
- free( this );
-}
-
-// 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 void *consumer_thread( void *arg );
-static void consumer_close( mlt_consumer this );
-
-/** Initialise the dv consumer.
-*/
-
-mlt_consumer consumer_avformat_init( mlt_profile profile, char *arg )
-{
- // Allocate the consumer
- mlt_consumer this = mlt_consumer_new( profile );
-
- // If memory allocated and initialises without error
- if ( this != NULL )
- {
- // Get properties from the consumer
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Assign close callback
- this->close = consumer_close;
-
- // Interpret the argument
- if ( arg != NULL )
- mlt_properties_set( properties, "target", arg );
-
- // sample and frame queue
- mlt_properties_set_data( properties, "frame_queue", mlt_deque_init( ), 0, ( mlt_destructor )mlt_deque_close, NULL );
-
- // Audio options not fully handled by AVOptions
-#define QSCALE_NONE (-99999)
- mlt_properties_set_int( properties, "aq", QSCALE_NONE );
-
- // Video options not fully handled by AVOptions
- mlt_properties_set_int( properties, "dc", 8 );
-
- // Muxer options not fully handled by AVOptions
- mlt_properties_set_double( properties, "muxdelay", 0.7 );
- mlt_properties_set_double( properties, "muxpreload", 0.5 );
-
- // Ensure termination at end of the stream
- mlt_properties_set_int( properties, "terminate_on_pause", 1 );
-
- // Default to separate processing threads for producer and consumer with no frame dropping!
- mlt_properties_set_int( properties, "real_time", -1 );
- mlt_properties_set_int( properties, "prefill", 1 );
-
- // Set up start/stop/terminated callbacks
- this->start = consumer_start;
- this->stop = consumer_stop;
- this->is_stopped = consumer_is_stopped;
- }
-
- // Return this
- return this;
-}
-
-/** Start the consumer.
-*/
-
-static int consumer_start( mlt_consumer this )
-{
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- int error = 0;
-
- // Report information about available muxers and codecs as YAML Tiny
- char *s = mlt_properties_get( properties, "f" );
- if ( s && strcmp( s, "list" ) == 0 )
- {
- fprintf( stderr, "---\nformats:\n" );
- AVOutputFormat *format = NULL;
- while ( ( format = av_oformat_next( format ) ) )
- fprintf( stderr, " - %s\n", format->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
- s = mlt_properties_get( properties, "acodec" );
- if ( s && strcmp( s, "list" ) == 0 )
- {
- fprintf( stderr, "---\naudio_codecs:\n" );
- AVCodec *codec = NULL;
- while ( ( codec = av_codec_next( codec ) ) )
- if ( codec->encode && codec->type == CODEC_TYPE_AUDIO )
- fprintf( stderr, " - %s\n", codec->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
- s = mlt_properties_get( properties, "vcodec" );
- if ( s && strcmp( s, "list" ) == 0 )
- {
- fprintf( stderr, "---\nvideo_codecs:\n" );
- AVCodec *codec = NULL;
- while ( ( codec = av_codec_next( codec ) ) )
- if ( codec->encode && codec->type == CODEC_TYPE_VIDEO )
- fprintf( stderr, " - %s\n", codec->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
-
- // Check that we're not already running
- if ( !error && !mlt_properties_get_int( properties, "running" ) )
- {
- // Allocate a thread
- pthread_t *thread = calloc( 1, sizeof( pthread_t ) );
-
- // Get the width and height
- int width = mlt_properties_get_int( properties, "width" );
- int height = mlt_properties_get_int( properties, "height" );
-
- // Obtain the size property
- char *size = mlt_properties_get( properties, "s" );
-
- // Interpret it
- if ( size != NULL )
- {
- int tw, th;
- if ( sscanf( size, "%dx%d", &tw, &th ) == 2 && tw > 0 && th > 0 )
- {
- width = tw;
- height = th;
- }
- else
- {
- fprintf( stderr, "%s: Invalid size property %s - ignoring.\n", __FILE__, size );
- }
- }
-
- // Now ensure we honour the multiple of two requested by libavformat
- width = ( width / 2 ) * 2;
- height = ( height / 2 ) * 2;
- mlt_properties_set_int( properties, "width", width );
- mlt_properties_set_int( properties, "height", height );
-
- // We need to set these on the profile as well because the s property is
- // an alias to mlt properties that correspond to profile settings.
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->width = width;
- profile->height = height;
- }
-
- // Handle the ffmpeg command line "-r" property for frame rate
- if ( mlt_properties_get( properties, "r" ) )
- {
- double frame_rate = mlt_properties_get_double( properties, "r" );
- AVRational rational = av_d2q( frame_rate, 255 );
- mlt_properties_set_int( properties, "frame_rate_num", rational.num );
- mlt_properties_set_int( properties, "frame_rate_den", rational.den );
- if ( profile )
- {
- profile->frame_rate_num = rational.num;
- profile->frame_rate_den = rational.den;
- mlt_properties_set_double( properties, "fps", mlt_profile_fps( profile ) );
- }
- }
-
- // Apply AVOptions that are synonyms for standard mlt_consumer options
- if ( mlt_properties_get( properties, "ac" ) )
- mlt_properties_set_int( properties, "channels", mlt_properties_get_int( properties, "ac" ) );
- if ( mlt_properties_get( properties, "ar" ) )
- mlt_properties_set_int( properties, "frequency", mlt_properties_get_int( properties, "ar" ) );
-
- // 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 error;
-}
-
-/** 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" );
-}
-
-/** Process properties as AVOptions and apply to AV context obj
-*/
-
-static void apply_properties( void *obj, mlt_properties properties, int flags )
-{
- int i;
- int count = mlt_properties_count( properties );
- for ( i = 0; i < count; i++ )
- {
- const char *opt_name = mlt_properties_get_name( properties, i );
- const AVOption *opt = av_find_opt( obj, opt_name, NULL, flags, flags );
- if ( opt != NULL )
-#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
- av_set_string3( obj, opt_name, mlt_properties_get( properties, opt_name), 0, NULL );
-#elif LIBAVCODEC_VERSION_INT >= ((51<<16)+(59<<8)+0)
- av_set_string2( obj, opt_name, mlt_properties_get( properties, opt_name), 0 );
-#else
- av_set_string( obj, opt_name, mlt_properties_get( properties, opt_name) );
-#endif
- }
-}
-
-/** Add an audio output stream
-*/
-
-static AVStream *add_audio_stream( mlt_consumer this, AVFormatContext *oc, int codec_id )
-{
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Create a new stream
- AVStream *st = av_new_stream( oc, 1 );
-
- // If created, then initialise from properties
- if ( st != NULL )
- {
- AVCodecContext *c = st->codec;
-
- // Establish defaults from AVOptions
- avcodec_get_context_defaults2( c, CODEC_TYPE_AUDIO );
-
- c->codec_id = codec_id;
- c->codec_type = CODEC_TYPE_AUDIO;
-
- // Setup multi-threading
- int thread_count = mlt_properties_get_int( properties, "threads" );
- if ( thread_count == 0 && getenv( "MLT_AVFORMAT_THREADS" ) )
- thread_count = atoi( getenv( "MLT_AVFORMAT_THREADS" ) );
- if ( thread_count > 1 )
- avcodec_thread_init( c, thread_count );
-
- if (oc->oformat->flags & AVFMT_GLOBALHEADER)
- c->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
- // Allow the user to override the audio fourcc
- if ( mlt_properties_get( properties, "atag" ) )
- {
- char *tail = NULL;
- char *arg = mlt_properties_get( properties, "atag" );
- int tag = strtol( arg, &tail, 0);
- if( !tail || *tail )
- tag = arg[ 0 ] + ( arg[ 1 ] << 8 ) + ( arg[ 2 ] << 16 ) + ( arg[ 3 ] << 24 );
- c->codec_tag = tag;
- }
-
- // Process properties as AVOptions
- apply_properties( c, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM );
-
- int audio_qscale = mlt_properties_get_int( properties, "aq" );
- if ( audio_qscale > QSCALE_NONE )
- {
- c->flags |= CODEC_FLAG_QSCALE;
- c->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
- }
-
- // Set parameters controlled by MLT
- c->sample_rate = mlt_properties_get_int( properties, "frequency" );
- c->channels = mlt_properties_get_int( properties, "channels" );
-
- if ( mlt_properties_get( properties, "alang" ) != NULL )
- strncpy( st->language, mlt_properties_get( properties, "alang" ), sizeof( st->language ) );
- }
- else
- {
- fprintf( stderr, "%s: Could not allocate a stream for audio\n", __FILE__ );
- }
-
- return st;
-}
-
-static int open_audio( AVFormatContext *oc, AVStream *st, int audio_outbuf_size )
-{
- // We will return the audio input size from here
- int audio_input_frame_size = 0;
-
- // Get the context
- AVCodecContext *c = st->codec;
-
- // Find the encoder
- AVCodec *codec = avcodec_find_encoder( c->codec_id );
-
- // Continue if codec found and we can open it
- if ( codec != NULL && avcodec_open( c, codec ) >= 0 )
- {
- // ugly hack for PCM codecs (will be removed ASAP with new PCM
- // support to compute the input frame size in samples
- if ( c->frame_size <= 1 )
- {
- audio_input_frame_size = audio_outbuf_size / c->channels;
- switch(st->codec->codec_id)
- {
- case CODEC_ID_PCM_S16LE:
- case CODEC_ID_PCM_S16BE:
- case CODEC_ID_PCM_U16LE:
- case CODEC_ID_PCM_U16BE:
- audio_input_frame_size >>= 1;
- break;
- default:
- break;
- }
- }
- else
- {
- audio_input_frame_size = c->frame_size;
- }
-
- // Some formats want stream headers to be seperate (hmm)
- if( !strcmp( oc->oformat->name, "mp4" ) ||
- !strcmp( oc->oformat->name, "mov" ) ||
- !strcmp( oc->oformat->name, "3gp" ) )
- c->flags |= CODEC_FLAG_GLOBAL_HEADER;
- }
- else
- {
- fprintf( stderr, "%s: Unable to encode audio - disabling audio output.\n", __FILE__ );
- }
-
- return audio_input_frame_size;
-}
-
-static void close_audio( AVFormatContext *oc, AVStream *st )
-{
- avcodec_close( st->codec );
-}
-
-/** Add a video output stream
-*/
-
-static AVStream *add_video_stream( mlt_consumer this, AVFormatContext *oc, int codec_id )
-{
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Create a new stream
- AVStream *st = av_new_stream( oc, 0 );
-
- if ( st != NULL )
- {
- char *pix_fmt = mlt_properties_get( properties, "pix_fmt" );
- AVCodecContext *c = st->codec;
-
- // Establish defaults from AVOptions
- avcodec_get_context_defaults2( c, CODEC_TYPE_VIDEO );
-
- c->codec_id = codec_id;
- c->codec_type = CODEC_TYPE_VIDEO;
-
- // Setup multi-threading
- int thread_count = mlt_properties_get_int( properties, "threads" );
- if ( thread_count == 0 && getenv( "MLT_AVFORMAT_THREADS" ) )
- thread_count = atoi( getenv( "MLT_AVFORMAT_THREADS" ) );
- if ( thread_count > 1 )
- avcodec_thread_init( c, thread_count );
-
- // Process properties as AVOptions
- apply_properties( c, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM );
-
- // Set options controlled by MLT
- c->width = mlt_properties_get_int( properties, "width" );
- c->height = mlt_properties_get_int( properties, "height" );
- c->time_base.num = mlt_properties_get_int( properties, "frame_rate_den" );
- c->time_base.den = mlt_properties_get_int( properties, "frame_rate_num" );
- if ( st->time_base.den == 0 )
- st->time_base = c->time_base;
- c->pix_fmt = pix_fmt ? avcodec_get_pix_fmt( pix_fmt ) : PIX_FMT_YUV420P;
-
- if ( mlt_properties_get( properties, "aspect" ) )
- {
- // "-aspect" on ffmpeg command line is display aspect ratio
- double ar = mlt_properties_get_double( properties, "aspect" );
- AVRational rational = av_d2q( ar, 255 );
-
- // Update the profile and properties as well since this is an alias
- // for mlt properties that correspond to profile settings
- mlt_properties_set_int( properties, "display_aspect_num", rational.num );
- mlt_properties_set_int( properties, "display_aspect_den", rational.den );
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( this ) );
- if ( profile )
- {
- profile->display_aspect_num = rational.num;
- profile->display_aspect_den = rational.den;
- mlt_properties_set_double( properties, "display_ratio", mlt_profile_dar( profile ) );
- }
-
- // Now compute the sample aspect ratio
- rational = av_d2q( ar * c->height / c->width, 255 );
- c->sample_aspect_ratio = rational;
- // Update the profile and properties as well since this is an alias
- // for mlt properties that correspond to profile settings
- mlt_properties_set_int( properties, "sample_aspect_num", rational.num );
- mlt_properties_set_int( properties, "sample_aspect_den", rational.den );
- if ( profile )
- {
- profile->sample_aspect_num = rational.num;
- profile->sample_aspect_den = rational.den;
- mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
- }
- }
- else
- {
- c->sample_aspect_ratio.num = mlt_properties_get_int( properties, "sample_aspect_num" );
- c->sample_aspect_ratio.den = mlt_properties_get_int( properties, "sample_aspect_den" );
- }
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0)
- st->sample_aspect_ratio = c->sample_aspect_ratio;
-#endif
-
- if ( mlt_properties_get_double( properties, "qscale" ) > 0 )
- {
- c->flags |= CODEC_FLAG_QSCALE;
- st->quality = FF_QP2LAMBDA * mlt_properties_get_double( properties, "qscale" );
- }
-
- // Allow the user to override the video fourcc
- if ( mlt_properties_get( properties, "vtag" ) )
- {
- char *tail = NULL;
- const char *arg = mlt_properties_get( properties, "vtag" );
- int tag = strtol( arg, &tail, 0);
- if( !tail || *tail )
- tag = arg[ 0 ] + ( arg[ 1 ] << 8 ) + ( arg[ 2 ] << 16 ) + ( arg[ 3 ] << 24 );
- c->codec_tag = tag;
- }
-
- // Some formats want stream headers to be seperate
- if ( oc->oformat->flags & AVFMT_GLOBALHEADER )
- c->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
- // Translate these standard mlt consumer properties to ffmpeg
- if ( mlt_properties_get_int( properties, "progressive" ) == 0 &&
- mlt_properties_get_int( properties, "deinterlace" ) == 0 )
- {
- if ( ! mlt_properties_get( properties, "ildct" ) || mlt_properties_get_int( properties, "ildct" ) )
- c->flags |= CODEC_FLAG_INTERLACED_DCT;
- if ( ! mlt_properties_get( properties, "ilme" ) || mlt_properties_get_int( properties, "ilme" ) )
- c->flags |= CODEC_FLAG_INTERLACED_ME;
- }
-
- // parse the ratecontrol override string
- int i;
- char *rc_override = mlt_properties_get( properties, "rc_override" );
- for ( i = 0; rc_override; i++ )
- {
- int start, end, q;
- int e = sscanf( rc_override, "%d,%d,%d", &start, &end, &q );
- if ( e != 3 )
- fprintf( stderr, "%s: Error parsing rc_override\n", __FILE__ );
- c->rc_override = av_realloc( c->rc_override, sizeof( RcOverride ) * ( i + 1 ) );
- c->rc_override[i].start_frame = start;
- c->rc_override[i].end_frame = end;
- if ( q > 0 )
- {
- c->rc_override[i].qscale = q;
- c->rc_override[i].quality_factor = 1.0;
- }
- else
- {
- c->rc_override[i].qscale = 0;
- c->rc_override[i].quality_factor = -q / 100.0;
- }
- rc_override = strchr( rc_override, '/' );
- if ( rc_override )
- rc_override++;
- }
- c->rc_override_count = i;
- if ( !c->rc_initial_buffer_occupancy )
- c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
- c->intra_dc_precision = mlt_properties_get_int( properties, "dc" ) - 8;
-
- // Setup dual-pass
- i = mlt_properties_get_int( properties, "pass" );
- if ( i == 1 )
- c->flags |= CODEC_FLAG_PASS1;
- else if ( i == 2 )
- c->flags |= CODEC_FLAG_PASS2;
- if ( codec_id != CODEC_ID_H264 && ( c->flags & ( CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2 ) ) )
- {
- char logfilename[1024];
- FILE *f;
- int size;
- char *logbuffer;
-
- snprintf( logfilename, sizeof(logfilename), "%s_2pass.log",
- mlt_properties_get( properties, "passlogfile" ) ? mlt_properties_get( properties, "passlogfile" ) : mlt_properties_get( properties, "target" ) );
- if ( c->flags & CODEC_FLAG_PASS1 )
- {
- f = fopen( logfilename, "w" );
- if ( !f )
- perror( logfilename );
- else
- mlt_properties_set_data( properties, "_logfile", f, 0, ( mlt_destructor )fclose, NULL );
- }
- else
- {
- /* read the log file */
- f = fopen( logfilename, "r" );
- if ( !f )
- {
- perror(logfilename);
- }
- else
- {
- mlt_properties_set( properties, "_logfilename", logfilename );
- fseek( f, 0, SEEK_END );
- size = ftell( f );
- fseek( f, 0, SEEK_SET );
- logbuffer = av_malloc( size + 1 );
- if ( !logbuffer )
- fprintf( stderr, "%s: Could not allocate log buffer\n", __FILE__ );
- else
- {
- size = fread( logbuffer, 1, size, f );
- fclose( f );
- logbuffer[size] = '\0';
- c->stats_in = logbuffer;
- mlt_properties_set_data( properties, "_logbuffer", logbuffer, 0, ( mlt_destructor )av_free, NULL );
- }
- }
- }
- }
- }
- else
- {
- fprintf( stderr, "%s: Could not allocate a stream for video\n", __FILE__ );
- }
-
- return st;
-}
-
-static AVFrame *alloc_picture( int pix_fmt, int width, int height )
-{
- // Allocate a frame
- AVFrame *picture = avcodec_alloc_frame();
-
- // Determine size of the
- int size = avpicture_get_size(pix_fmt, width, height);
-
- // Allocate the picture buf
- uint8_t *picture_buf = av_malloc(size);
-
- // If we have both, then fill the image
- if ( picture != NULL && picture_buf != NULL )
- {
- // Fill the frame with the allocated buffer
- avpicture_fill( (AVPicture *)picture, picture_buf, pix_fmt, width, height);
- }
- else
- {
- // Something failed - clean up what we can
- av_free( picture );
- av_free( picture_buf );
- picture = NULL;
- }
-
- return picture;
-}
-
-static int open_video(AVFormatContext *oc, AVStream *st)
-{
- // Get the codec
- AVCodecContext *video_enc = st->codec;
-
- // find the video encoder
- AVCodec *codec = avcodec_find_encoder( video_enc->codec_id );
-
- if( codec && codec->pix_fmts )
- {
- const enum PixelFormat *p = codec->pix_fmts;
- for( ; *p!=-1; p++ )
- {
- if( *p == video_enc->pix_fmt )
- break;
- }
- if( *p == -1 )
- video_enc->pix_fmt = codec->pix_fmts[ 0 ];
- }
-
- // Open the codec safely
- return codec != NULL && avcodec_open( video_enc, codec ) >= 0;
-}
-
-void close_video(AVFormatContext *oc, AVStream *st)
-{
- avcodec_close(st->codec);
-}
-
-static inline long time_difference( struct timeval *time1 )
-{
- struct timeval time2;
- gettimeofday( &time2, NULL );
- return time2.tv_sec * 1000000 + time2.tv_usec - time1->tv_sec * 1000000 - time1->tv_usec;
-}
-
-/** The main thread - the argument is simply the consumer.
-*/
-
-static void *consumer_thread( void *arg )
-{
- // Map the argument to the object
- mlt_consumer this = arg;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the terminate on pause property
- int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
- int terminated = 0;
-
- // Determine if feed is slow (for realtime stuff)
- int real_time_output = mlt_properties_get_int( properties, "real_time" );
-
- // Time structures
- struct timeval ante;
-
- // Get the frame rate
- double fps = mlt_properties_get_double( properties, "fps" );
-
- // Get width and height
- int width = mlt_properties_get_int( properties, "width" );
- int height = mlt_properties_get_int( properties, "height" );
- int img_width = width;
- int img_height = height;
-
- // Get default audio properties
- mlt_audio_format aud_fmt = mlt_audio_pcm;
- int channels = mlt_properties_get_int( properties, "channels" );
- int frequency = mlt_properties_get_int( properties, "frequency" );
- int16_t *pcm = NULL;
- int samples = 0;
-
- // AVFormat audio buffer and frame size
- int audio_outbuf_size = 10000;
- uint8_t *audio_outbuf = av_malloc( audio_outbuf_size );
- int audio_input_frame_size = 0;
-
- // AVFormat video buffer and frame count
- int frame_count = 0;
- int video_outbuf_size = ( 1024 * 1024 );
- uint8_t *video_outbuf = av_malloc( video_outbuf_size );
-
- // Used for the frame properties
- mlt_frame frame = NULL;
- mlt_properties frame_properties = NULL;
-
- // Get the queues
- mlt_deque queue = mlt_properties_get_data( properties, "frame_queue", NULL );
- sample_fifo fifo = mlt_properties_get_data( properties, "sample_fifo", NULL );
-
- // Need two av pictures for converting
- AVFrame *output = NULL;
- AVFrame *input = alloc_picture( PIX_FMT_YUYV422, width, height );
-
- // For receiving images from an mlt_frame
- uint8_t *image;
- mlt_image_format img_fmt = mlt_image_yuv422;
-
- // For receiving audio samples back from the fifo
- int16_t *buffer = av_malloc( 48000 * 2 );
- int count = 0;
-
- // Allocate the context
- AVFormatContext *oc = av_alloc_format_context( );
-
- // Streams
- AVStream *audio_st = NULL;
- AVStream *video_st = NULL;
-
- // Time stamps
- double audio_pts = 0;
- double video_pts = 0;
-
- // Loop variable
- int i;
-
- // Frames despatched
- long int frames = 0;
- long int total_time = 0;
-
- // Determine the format
- AVOutputFormat *fmt = NULL;
- const char *filename = mlt_properties_get( properties, "target" );
- char *format = mlt_properties_get( properties, "f" );
- char *vcodec = mlt_properties_get( properties, "vcodec" );
- char *acodec = mlt_properties_get( properties, "acodec" );
-
- // Used to store and override codec ids
- int audio_codec_id;
- int video_codec_id;
-
- // Check for user selected format first
- if ( format != NULL )
- fmt = guess_format( format, NULL, NULL );
-
- // Otherwise check on the filename
- if ( fmt == NULL && filename != NULL )
- fmt = guess_format( NULL, filename, NULL );
-
- // Otherwise default to mpeg
- if ( fmt == NULL )
- fmt = guess_format( "mpeg", NULL, NULL );
-
- // We need a filename - default to stdout?
- if ( filename == NULL || !strcmp( filename, "" ) )
- filename = "pipe:";
-
- // Get the codec ids selected
- audio_codec_id = fmt->audio_codec;
- video_codec_id = fmt->video_codec;
-
- // Check for audio codec overides
- if ( ( acodec && strcmp( "acodec", "none" ) == 0 ) || mlt_properties_get_int( properties, "an" ) )
- audio_codec_id = CODEC_ID_NONE;
- else if ( acodec )
- {
- AVCodec *p = avcodec_find_encoder_by_name( acodec );
- if ( p != NULL )
- audio_codec_id = p->id;
- else
- fprintf( stderr, "%s: audio codec %s unrecognised - ignoring\n", __FILE__, acodec );
- }
-
- // Check for video codec overides
- if ( ( vcodec && strcmp( "vcodec", "none" ) == 0 ) || mlt_properties_get_int( properties, "vn" ) )
- video_codec_id = CODEC_ID_NONE;
- else if ( vcodec )
- {
- AVCodec *p = avcodec_find_encoder_by_name( vcodec );
- if ( p != NULL )
- video_codec_id = p->id;
- else
- fprintf( stderr, "%s: video codec %s unrecognised - ignoring\n", __FILE__, vcodec );
- }
-
- // Write metadata
- char *tmp = NULL;
- int metavalue;
-
- tmp = mlt_properties_get( properties, "meta.attr.title.markup");
- if (tmp != NULL) snprintf( oc->title, sizeof(oc->title), "%s", tmp );
-
- tmp = mlt_properties_get( properties, "meta.attr.comment.markup");
- if (tmp != NULL) snprintf( oc->comment, sizeof(oc->comment), "%s", tmp );
-
- tmp = mlt_properties_get( properties, "meta.attr.author.markup");
- if (tmp != NULL) snprintf( oc->author, sizeof(oc->author), "%s", tmp );
-
- tmp = mlt_properties_get( properties, "meta.attr.copyright.markup");
- if (tmp != NULL) snprintf( oc->copyright, sizeof(oc->copyright), "%s", tmp );
-
- tmp = mlt_properties_get( properties, "meta.attr.album.markup");
- if (tmp != NULL) snprintf( oc->album, sizeof(oc->album), "%s", tmp );
-
- metavalue = mlt_properties_get_int( properties, "meta.attr.year.markup");
- if (metavalue != 0) oc->year = metavalue;
-
- metavalue = mlt_properties_get_int( properties, "meta.attr.track.markup");
- if (metavalue != 0) oc->track = metavalue;
-
- oc->oformat = fmt;
- snprintf( oc->filename, sizeof(oc->filename), "%s", filename );
-
- // Add audio and video streams
- if ( video_codec_id != CODEC_ID_NONE )
- video_st = add_video_stream( this, oc, video_codec_id );
- if ( audio_codec_id != CODEC_ID_NONE )
- audio_st = add_audio_stream( this, oc, audio_codec_id );
-
- // Set the parameters (even though we have none...)
- if ( av_set_parameters(oc, NULL) >= 0 )
- {
- oc->preload = ( int )( mlt_properties_get_double( properties, "muxpreload" ) * AV_TIME_BASE );
- oc->max_delay= ( int )( mlt_properties_get_double( properties, "muxdelay" ) * AV_TIME_BASE );
-
- // Process properties as AVOptions
- apply_properties( oc, properties, AV_OPT_FLAG_ENCODING_PARAM );
-
- if ( video_st && !open_video( oc, video_st ) )
- video_st = NULL;
- if ( audio_st )
- audio_input_frame_size = open_audio( oc, audio_st, audio_outbuf_size );
-
- // Open the output file, if needed
- if ( !( fmt->flags & AVFMT_NOFILE ) )
- {
- if ( url_fopen( &oc->pb, filename, URL_WRONLY ) < 0 )
- {
- fprintf( stderr, "%s: Could not open '%s'\n", __FILE__, filename );
- mlt_properties_set_int( properties, "running", 0 );
- }
- }
-
- // Write the stream header, if any
- if ( mlt_properties_get_int( properties, "running" ) )
- av_write_header( oc );
- }
- else
- {
- fprintf( stderr, "%s: Invalid output format parameters\n", __FILE__ );
- mlt_properties_set_int( properties, "running", 0 );
- }
-
- // Allocate picture
- if ( video_st )
- output = alloc_picture( video_st->codec->pix_fmt, width, height );
-
- // Last check - need at least one stream
- if ( audio_st == NULL && video_st == NULL )
- mlt_properties_set_int( properties, "running", 0 );
-
- // Get the starting time (can ignore the times above)
- gettimeofday( &ante, NULL );
-
- // Loop while running
- while( mlt_properties_get_int( properties, "running" ) && !terminated )
- {
- // Get the frame
- frame = mlt_consumer_rt_frame( this );
-
- // Check that we have a frame to work with
- if ( frame != NULL )
- {
- // Increment frames despatched
- frames ++;
-
- // Default audio args
- frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Check for the terminated condition
- terminated = terminate_on_pause && mlt_properties_get_double( frame_properties, "_speed" ) == 0.0;
-
- // Get audio and append to the fifo
- if ( !terminated && audio_st )
- {
- samples = mlt_sample_calculator( fps, frequency, count ++ );
- mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
-
- // Create the fifo if we don't have one
- if ( fifo == NULL )
- {
- fifo = sample_fifo_init( frequency, channels );
- mlt_properties_set_data( properties, "sample_fifo", fifo, 0, ( mlt_destructor )sample_fifo_close, NULL );
- }
-
- if ( mlt_properties_get_double( frame_properties, "_speed" ) != 1.0 )
- memset( pcm, 0, samples * channels * 2 );
-
- // Append the samples
- sample_fifo_append( fifo, pcm, samples * channels );
- total_time += ( samples * 1000000 ) / frequency;
- }
-
- // Encode the image
- if ( !terminated && video_st )
- mlt_deque_push_back( queue, frame );
- else
- mlt_frame_close( frame );
- }
-
- // While we have stuff to process, process...
- while ( 1 )
- {
- if (audio_st)
- audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
- else
- audio_pts = 0.0;
-
- if (video_st)
- video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
- else
- video_pts = 0.0;
-
- // Write interleaved audio and video frames
- if ( !video_st || ( video_st && audio_st && audio_pts < video_pts ) )
- {
- if ( channels * audio_input_frame_size < sample_fifo_used( fifo ) )
- {
- AVCodecContext *c;
- AVPacket pkt;
- av_init_packet( &pkt );
-
- c = audio_st->codec;
-
- sample_fifo_fetch( fifo, buffer, channels * audio_input_frame_size );
-
- pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, buffer );
- // Write the compressed frame in the media file
- if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE )
- pkt.pts = av_rescale_q( c->coded_frame->pts, c->time_base, audio_st->time_base );
- pkt.flags |= PKT_FLAG_KEY;
- pkt.stream_index= audio_st->index;
- pkt.data= audio_outbuf;
-
- if ( pkt.size )
- if ( av_interleaved_write_frame( oc, &pkt ) != 0)
- fprintf( stderr, "%s: Error while writing audio frame\n", __FILE__ );
-
- audio_pts += c->frame_size;
- }
- else
- {
- break;
- }
- }
- else if ( video_st )
- {
- if ( mlt_deque_count( queue ) )
- {
- int out_size, ret;
- AVCodecContext *c;
-
- frame = mlt_deque_pop_front( queue );
- frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- c = video_st->codec;
-
- if ( mlt_properties_get_int( frame_properties, "rendered" ) )
- {
- int i = 0;
- int j = 0;
- uint8_t *p;
- uint8_t *q;
-
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
-
- mlt_frame_get_image( frame, &image, &img_fmt, &img_width, &img_height, 0 );
-
- q = image;
-
- // Convert the mlt frame to an AVPicture
- for ( i = 0; i < height; i ++ )
- {
- p = input->data[ 0 ] + i * input->linesize[ 0 ];
- j = width;
- while( j -- )
- {
- *p ++ = *q ++;
- *p ++ = *q ++;
- }
- }
-
- // Do the colour space conversion
-#ifdef SWSCALE
- struct SwsContext *context = sws_getContext( width, height, PIX_FMT_YUYV422,
- width, height, video_st->codec->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- sws_scale( context, input->data, input->linesize, 0, height,
- output->data, output->linesize);
- sws_freeContext( context );
-#else
- img_convert( ( AVPicture * )output, video_st->codec->pix_fmt, ( AVPicture * )input, PIX_FMT_YUYV422, width, height );
-#endif
-
- // Apply the alpha if applicable
- if ( video_st->codec->pix_fmt == PIX_FMT_RGB32 )
- {
- uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
- register int n;
-
- for ( i = 0; i < height; i ++ )
- {
- n = ( width + 7 ) / 8;
- p = output->data[ 0 ] + i * output->linesize[ 0 ];
-
- #ifndef __DARWIN__
- p += 3;
- #endif
-
- switch( width % 8 )
- {
- case 0: do { *p = *alpha++; p += 4;
- case 7: *p = *alpha++; p += 4;
- case 6: *p = *alpha++; p += 4;
- case 5: *p = *alpha++; p += 4;
- case 4: *p = *alpha++; p += 4;
- case 3: *p = *alpha++; p += 4;
- case 2: *p = *alpha++; p += 4;
- case 1: *p = *alpha++; p += 4;
- }
- while( --n );
- }
- }
- }
- }
-
- if (oc->oformat->flags & AVFMT_RAWPICTURE)
- {
- // raw video case. The API will change slightly in the near future for that
- AVPacket pkt;
- av_init_packet(&pkt);
-
- pkt.flags |= PKT_FLAG_KEY;
- pkt.stream_index= video_st->index;
- pkt.data= (uint8_t *)output;
- pkt.size= sizeof(AVPicture);
-
- ret = av_write_frame(oc, &pkt);
- video_pts += c->frame_size;
- }
- else
- {
- // Set the quality
- output->quality = video_st->quality;
-
- // Set frame interlace hints
- output->interlaced_frame = !mlt_properties_get_int( frame_properties, "progressive" );
- output->top_field_first = mlt_properties_get_int( frame_properties, "top_field_first" );
-
- // Encode the image
- out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, output );
-
- // If zero size, it means the image was buffered
- if (out_size > 0)
- {
- AVPacket pkt;
- av_init_packet( &pkt );
-
- if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE )
- pkt.pts= av_rescale_q( c->coded_frame->pts, c->time_base, video_st->time_base );
- if( c->coded_frame && c->coded_frame->key_frame )
- pkt.flags |= PKT_FLAG_KEY;
- pkt.stream_index= video_st->index;
- pkt.data= video_outbuf;
- pkt.size= out_size;
-
- // write the compressed frame in the media file
- ret = av_interleaved_write_frame(oc, &pkt);
- video_pts += c->frame_size;
-
- // Dual pass logging
- if ( mlt_properties_get_data( properties, "_logfile", NULL ) && c->stats_out)
- fprintf( mlt_properties_get_data( properties, "_logfile", NULL ), "%s", c->stats_out );
- }
- else
- {
- fprintf( stderr, "%s: error with video encode\n", __FILE__ );
- }
- }
- frame_count++;
- mlt_frame_close( frame );
- }
- else
- {
- break;
- }
- }
- }
-
- if ( real_time_output == 1 && frames % 12 == 0 )
- {
- long passed = time_difference( &ante );
- if ( fifo != NULL )
- {
- long pending = ( ( ( long )sample_fifo_used( fifo ) * 1000 ) / frequency ) * 1000;
- passed -= pending;
- }
- if ( passed < total_time )
- {
- long total = ( total_time - passed );
- struct timespec t = { total / 1000000, ( total % 1000000 ) * 1000 };
- nanosleep( &t, NULL );
- }
- }
- }
-
-#ifdef FLUSH
- if ( ! real_time_output )
- {
- // Flush audio fifo
- if ( audio_st && audio_st->codec->frame_size > 1 ) for (;;)
- {
- AVCodecContext *c = audio_st->codec;
- AVPacket pkt;
- av_init_packet( &pkt );
- pkt.size = 0;
-
- if ( /*( c->capabilities & CODEC_CAP_SMALL_LAST_FRAME ) &&*/
- ( channels * audio_input_frame_size < sample_fifo_used( fifo ) ) )
- {
- sample_fifo_fetch( fifo, buffer, channels * audio_input_frame_size );
- pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, buffer );
- }
- if ( pkt.size <= 0 )
- pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, NULL );
- if ( pkt.size <= 0 )
- break;
-
- // Write the compressed frame in the media file
- if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE )
- pkt.pts = av_rescale_q( c->coded_frame->pts, c->time_base, audio_st->time_base );
- pkt.flags |= PKT_FLAG_KEY;
- pkt.stream_index = audio_st->index;
- pkt.data = audio_outbuf;
- if ( av_interleaved_write_frame( oc, &pkt ) != 0 )
- {
- fprintf( stderr, "%s: Error while writing flushed audio frame\n", __FILE__ );
- break;
- }
- }
-
- // Flush video
- if ( video_st && !( oc->oformat->flags & AVFMT_RAWPICTURE ) ) for (;;)
- {
- AVCodecContext *c = video_st->codec;
- AVPacket pkt;
- av_init_packet( &pkt );
-
- // Encode the image
- pkt.size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, NULL );
- if ( pkt.size <= 0 )
- break;
-
- if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE )
- pkt.pts= av_rescale_q( c->coded_frame->pts, c->time_base, video_st->time_base );
- if( c->coded_frame && c->coded_frame->key_frame )
- pkt.flags |= PKT_FLAG_KEY;
- pkt.stream_index = video_st->index;
- pkt.data = video_outbuf;
-
- // write the compressed frame in the media file
- if ( av_interleaved_write_frame( oc, &pkt ) != 0 )
- {
- fprintf( stderr, "%s: Error while writing flushed video frame\n". __FILE__ );
- break;
- }
- }
- }
-#endif
-
- // close each codec
- if (video_st)
- close_video(oc, video_st);
- if (audio_st)
- close_audio(oc, audio_st);
-
- // Write the trailer, if any
- av_write_trailer(oc);
-
- // Free the streams
- for(i = 0; i < oc->nb_streams; i++)
- av_freep(&oc->streams[i]);
-
- // Close the output file
- if (!(fmt->flags & AVFMT_NOFILE))
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
- url_fclose(oc->pb);
-#else
- url_fclose(&oc->pb);
-#endif
-
- // Clean up input and output frames
- if ( output )
- av_free( output->data[0] );
- av_free( output );
- av_free( input->data[0] );
- av_free( input );
- av_free( video_outbuf );
- av_free( buffer );
-
- // Free the stream
- av_free(oc);
-
- // Just in case we terminated on pause
- mlt_properties_set_int( properties, "running", 0 );
-
- mlt_consumer_stopped( this );
-
- if ( mlt_properties_get_int( properties, "pass" ) == 2 )
- {
- // Remove the dual pass log file
- if ( mlt_properties_get( properties, "_logfilename" ) )
- remove( mlt_properties_get( properties, "_logfilename" ) );
-
- // Remove the x264 dual pass logs
- char *cwd = getcwd( NULL, 0 );
- const char *file = "x264_2pass.log";
- char *full = malloc( strlen( cwd ) + strlen( file ) + 2 );
- sprintf( full, "%s/%s", cwd, file );
- remove( full );
- free( full );
- file = "x264_2pass.log.temp";
- full = malloc( strlen( cwd ) + strlen( file ) + 2 );
- sprintf( full, "%s/%s", cwd, file );
- remove( full );
- free( full );
- free( cwd );
- remove( "x264_2pass.log.temp" );
- }
-
- return NULL;
-}
-
-/** Close the consumer.
-*/
-
-static void consumer_close( mlt_consumer this )
-{
- // Stop the consumer
- mlt_consumer_stop( this );
-
- // Close the parent
- mlt_consumer_close( this );
-
- // Free the memory
- free( this );
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <pthread.h>
-#include <limits.h>
-
-#include <framework/mlt.h>
-
-extern mlt_consumer consumer_avformat_init( mlt_profile profile, char *file );
-extern mlt_filter filter_avcolour_space_init( void *arg );
-extern mlt_filter filter_avdeinterlace_init( void *arg );
-extern mlt_filter filter_avresample_init( char *arg );
-extern mlt_filter filter_swscale_init( mlt_profile profile, char *arg );
-extern mlt_producer producer_avformat_init( mlt_profile profile, char *file );
-
-// ffmpeg Header files
-#include <avformat.h>
-
-// A static flag used to determine if avformat has been initialised
-static int avformat_initialised = 0;
-
-// A locking mutex
-static pthread_mutex_t avformat_mutex;
-
-#if 0
-// These 3 functions should override the alloc functions in libavformat
-// but some formats or codecs seem to crash when used (wmv in particular)
-
-void *av_malloc( unsigned int size )
-{
- return mlt_pool_alloc( size );
-}
-
-void *av_realloc( void *ptr, unsigned int size )
-{
- return mlt_pool_realloc( ptr, size );
-}
-
-void av_free( void *ptr )
-{
- return mlt_pool_release( ptr );
-}
-#endif
-
-void avformat_destroy( void *ignore )
-{
- // Clean up
- // av_free_static( ); -XXX this is deprecated
-
- // Destroy the mutex
- pthread_mutex_destroy( &avformat_mutex );
-}
-
-void avformat_lock( )
-{
- // Lock the mutex now
- pthread_mutex_lock( &avformat_mutex );
-}
-
-void avformat_unlock( )
-{
- // Unlock the mutex now
- pthread_mutex_unlock( &avformat_mutex );
-}
-
-static void avformat_init( )
-{
- // Initialise avformat if necessary
- if ( avformat_initialised == 0 )
- {
- avformat_initialised = 1;
- pthread_mutex_init( &avformat_mutex, NULL );
- av_register_all( );
- mlt_factory_register_for_clean_up( NULL, avformat_destroy );
- av_log_set_level( mlt_log_get_level() );
- }
-}
-
-static void *create_service( mlt_profile profile, mlt_service_type type, const char *id, void *arg )
-{
- avformat_init( );
-#ifdef CODECS
- if ( !strcmp( id, "avformat" ) )
- {
- if ( type == producer_type )
- return producer_avformat_init( profile, arg );
- else if ( type == consumer_type )
- return consumer_avformat_init( profile, arg );
- }
-#endif
-#ifdef FILTERS
- if ( !strcmp( id, "avcolour_space" ) )
- return filter_avcolour_space_init( arg );
- if ( !strcmp( id, "avdeinterlace" ) )
- return filter_avdeinterlace_init( arg );
- if ( !strcmp( id, "avresample" ) )
- return filter_avresample_init( arg );
-#ifdef SWSCALE
- if ( !strcmp( id, "swscale" ) )
- return filter_swscale_init( profile, arg );
-#endif
-#endif
- return NULL;
-}
-
-static mlt_properties avformat_metadata( mlt_service_type type, const char *id, void *data )
-{
- char file[ PATH_MAX ];
- const char *service_type = NULL;
- switch ( type )
- {
- case consumer_type:
- service_type = "consumer";
- break;
- case filter_type:
- service_type = "filter";
- break;
- case producer_type:
- service_type = "producer";
- break;
- case transition_type:
- service_type = "transition";
- break;
- default:
- return NULL;
- }
- snprintf( file, PATH_MAX, "%s/avformat/%s_%s.yml", mlt_environment( "MLT_DATA" ), service_type, id );
- return mlt_properties_parse_yaml( file );
-}
-
-MLT_REPOSITORY
-{
-#ifdef CODECS
- MLT_REGISTER( consumer_type, "avformat", create_service );
- MLT_REGISTER( producer_type, "avformat", create_service );
- MLT_REGISTER_METADATA( producer_type, "avformat", avformat_metadata, NULL );
-#endif
-#ifdef FILTERS
- MLT_REGISTER( filter_type, "avcolour_space", create_service );
- MLT_REGISTER( filter_type, "avcolor_space", create_service );
- MLT_REGISTER( filter_type, "avdeinterlace", create_service );
- MLT_REGISTER( filter_type, "avresample", create_service );
-#ifdef SWSCALE
- MLT_REGISTER( filter_type, "swscale", create_service );
-#endif
-#endif
-}
+++ /dev/null
-/*
- * filter_avcolour_space.c -- Colour space filter
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-// ffmpeg Header files
-#include <avformat.h>
-#ifdef SWSCALE
-#include <swscale.h>
-#endif
-
-#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_RGB32 PIX_FMT_RGBA32
-#define PIX_FMT_YUYV422 PIX_FMT_YUV422
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-static inline int is_big_endian( )
-{
- union { int i; char c[ 4 ]; } big_endian_test;
- big_endian_test.i = 1;
-
- return big_endian_test.c[ 0 ] != 1;
-}
-
-static inline int convert_mlt_to_av_cs( mlt_image_format format )
-{
- int value = 0;
-
- switch( format )
- {
- case mlt_image_rgb24:
- value = PIX_FMT_RGB24;
- break;
- case mlt_image_rgb24a:
- value = PIX_FMT_RGB32;
- break;
- case mlt_image_yuv422:
- value = PIX_FMT_YUYV422;
- break;
- case mlt_image_yuv420p:
- value = PIX_FMT_YUV420P;
- break;
- case mlt_image_opengl:
- case mlt_image_none:
- fprintf( stderr, "Invalid format...\n" );
- break;
- }
-
- return value;
-}
-
-static inline void convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt, int width, int height )
-{
- AVPicture input;
- AVPicture output;
- avpicture_fill( &input, in, in_fmt, width, height );
- avpicture_fill( &output, out, out_fmt, width, height );
-#ifdef SWSCALE
- struct SwsContext *context = sws_getContext( width, height, in_fmt,
- width, height, out_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- sws_scale( context, input.data, input.linesize, 0, height,
- output.data, output.linesize);
- sws_freeContext( context );
-#else
- img_convert( &output, out_fmt, &input, in_fmt, width, height );
-#endif
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_filter filter = mlt_frame_pop_service( this );
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- int output_format = *format;
- mlt_image_format forced = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "forced" );
- int error = 0;
-
- // Allow this filter to force processing in a colour space other than requested
- *format = forced != 0 ? forced : *format;
-
- error = mlt_frame_get_image( this, image, format, width, height, 0 );
-
- if ( error == 0 && *format != output_format && *image != NULL && output_format != mlt_image_opengl )
- {
- int in_fmt = convert_mlt_to_av_cs( *format );
- int out_fmt = convert_mlt_to_av_cs( output_format );
- int size = avpicture_get_size( out_fmt, *width, *height );
- uint8_t *output = mlt_pool_alloc( size );
- convert_image( output, *image, out_fmt, in_fmt, *width, *height );
-
- // Special case for alpha rgb input
- if ( *format == mlt_image_rgb24a )
- {
- register uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- register int len = *width * *height;
- register uint8_t *bits = *image;
- register int n = ( len + 7 ) / 8;
-
- if( !is_big_endian( ) )
- bits += 3;
-
- // Extract alpha mask from the image using Duff's Device
- switch( len % 8 )
- {
- case 0: do { *alpha ++ = *bits; bits += 4;
- case 7: *alpha ++ = *bits; bits += 4;
- case 6: *alpha ++ = *bits; bits += 4;
- case 5: *alpha ++ = *bits; bits += 4;
- case 4: *alpha ++ = *bits; bits += 4;
- case 3: *alpha ++ = *bits; bits += 4;
- case 2: *alpha ++ = *bits; bits += 4;
- case 1: *alpha ++ = *bits; bits += 4;
- }
- while( --n );
- }
- }
-
- // Update the output
- *image = output;
- *format = output_format;
- mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "format", output_format );
-
- // Special case for alpha rgb output
- if ( *format == mlt_image_rgb24a )
- {
- // Fetch the alpha
- register uint8_t *alpha = mlt_frame_get_alpha_mask( this );
-
- if ( alpha != NULL )
- {
- register uint8_t *bits = *image;
- register int len = *width * *height;
- register int n = ( len + 7 ) / 8;
-
- if( !is_big_endian( ) )
- bits += 3;
-
- // Merge the alpha mask into the RGB image using Duff's Device
- switch( len % 8 )
- {
- case 0: do { *bits = *alpha++; bits += 4;
- case 7: *bits = *alpha++; bits += 4;
- case 6: *bits = *alpha++; bits += 4;
- case 5: *bits = *alpha++; bits += 4;
- case 4: *bits = *alpha++; bits += 4;
- case 3: *bits = *alpha++; bits += 4;
- case 2: *bits = *alpha++; bits += 4;
- case 1: *bits = *alpha++; bits += 4;
- }
- while( --n );
- }
- }
- }
- }
- else if ( error == 0 && *format != output_format && *image != NULL && output_format == mlt_image_opengl )
- {
- if ( *format == mlt_image_yuv422 )
- {
- int size = *width * *height * 4;
- uint8_t *output = mlt_pool_alloc( size );
- int h = *height;
- int w = *width;
- uint8_t *o = output + size;
- int ostride = w * 4;
- uint8_t *p = *image;
- uint8_t *alpha = mlt_frame_get_alpha_mask( this ) + *width * *height;
- int r, g, b;
-
- while( h -- )
- {
- w = *width;
- o -= ostride;
- alpha -= *width;
- while( w >= 2 )
- {
- YUV2RGB( *p, *( p + 1 ), *( p + 3 ), r, g, b );
- *o ++ = r;
- *o ++ = g;
- *o ++ = b;
- *o ++ = *alpha ++;
- YUV2RGB( *( p + 2 ), *( p + 1 ), *( p + 3 ), r, g, b );
- *o ++ = r;
- *o ++ = g;
- *o ++ = b;
- *o ++ = *alpha ++;
- w -= 2;
- p += 4;
- }
- o -= ostride;
- alpha -= *width;
- }
-
- mlt_properties_set_data( properties, "image", output, size, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "format", output_format );
- *image = output;
- *format = output_format;
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_avcolour_space_init( void *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- this->process = filter_process;
- return this;
-}
-
+++ /dev/null
-/*
- * filter_avdeinterlace.c -- deinterlace filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-// ffmpeg Header files
-#include <avformat.h>
-
-#ifdef USE_MMX
-#include "mmx.h"
-#else
-#define MAX_NEG_CROP 1024
-extern uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP];
-#endif
-
-#ifdef USE_MMX
-#define DEINT_INPLACE_LINE_LUM \
- movd_m2r(lum_m4[0],mm0);\
- movd_m2r(lum_m3[0],mm1);\
- movd_m2r(lum_m2[0],mm2);\
- movd_m2r(lum_m1[0],mm3);\
- movd_m2r(lum[0],mm4);\
- punpcklbw_r2r(mm7,mm0);\
- movd_r2m(mm2,lum_m4[0]);\
- punpcklbw_r2r(mm7,mm1);\
- punpcklbw_r2r(mm7,mm2);\
- punpcklbw_r2r(mm7,mm3);\
- punpcklbw_r2r(mm7,mm4);\
- paddw_r2r(mm3,mm1);\
- psllw_i2r(1,mm2);\
- paddw_r2r(mm4,mm0);\
- psllw_i2r(2,mm1);\
- paddw_r2r(mm6,mm2);\
- paddw_r2r(mm2,mm1);\
- psubusw_r2r(mm0,mm1);\
- psrlw_i2r(3,mm1);\
- packuswb_r2r(mm7,mm1);\
- movd_r2m(mm1,lum_m2[0]);
-
-#define DEINT_LINE_LUM \
- movd_m2r(lum_m4[0],mm0);\
- movd_m2r(lum_m3[0],mm1);\
- movd_m2r(lum_m2[0],mm2);\
- movd_m2r(lum_m1[0],mm3);\
- movd_m2r(lum[0],mm4);\
- punpcklbw_r2r(mm7,mm0);\
- punpcklbw_r2r(mm7,mm1);\
- punpcklbw_r2r(mm7,mm2);\
- punpcklbw_r2r(mm7,mm3);\
- punpcklbw_r2r(mm7,mm4);\
- paddw_r2r(mm3,mm1);\
- psllw_i2r(1,mm2);\
- paddw_r2r(mm4,mm0);\
- psllw_i2r(2,mm1);\
- paddw_r2r(mm6,mm2);\
- paddw_r2r(mm2,mm1);\
- psubusw_r2r(mm0,mm1);\
- psrlw_i2r(3,mm1);\
- packuswb_r2r(mm7,mm1);\
- movd_r2m(mm1,dst[0]);
-#endif
-
-#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_YUYV422 PIX_FMT_YUV422
-#endif
-
-/* filter parameters: [-1 4 2 4 -1] // 8 */
-static inline void deinterlace_line(uint8_t *dst,
- const uint8_t *lum_m4, const uint8_t *lum_m3,
- const uint8_t *lum_m2, const uint8_t *lum_m1,
- const uint8_t *lum,
- int size)
-{
-#ifndef USE_MMX
- uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
- int sum;
-
- for(;size > 0;size--) {
- sum = -lum_m4[0];
- sum += lum_m3[0] << 2;
- sum += lum_m2[0] << 1;
- sum += lum_m1[0] << 2;
- sum += -lum[0];
- dst[0] = cm[(sum + 4) >> 3];
- lum_m4++;
- lum_m3++;
- lum_m2++;
- lum_m1++;
- lum++;
- dst++;
- }
-#else
-
- {
- mmx_t rounder;
- rounder.uw[0]=4;
- rounder.uw[1]=4;
- rounder.uw[2]=4;
- rounder.uw[3]=4;
- pxor_r2r(mm7,mm7);
- movq_m2r(rounder,mm6);
- }
- for (;size > 3; size-=4) {
- DEINT_LINE_LUM
- lum_m4+=4;
- lum_m3+=4;
- lum_m2+=4;
- lum_m1+=4;
- lum+=4;
- dst+=4;
- }
-#endif
-}
-static inline void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
- int size)
-{
-#ifndef USE_MMX
- uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
- int sum;
-
- for(;size > 0;size--) {
- sum = -lum_m4[0];
- sum += lum_m3[0] << 2;
- sum += lum_m2[0] << 1;
- lum_m4[0]=lum_m2[0];
- sum += lum_m1[0] << 2;
- sum += -lum[0];
- lum_m2[0] = cm[(sum + 4) >> 3];
- lum_m4++;
- lum_m3++;
- lum_m2++;
- lum_m1++;
- lum++;
- }
-#else
-
- {
- mmx_t rounder;
- rounder.uw[0]=4;
- rounder.uw[1]=4;
- rounder.uw[2]=4;
- rounder.uw[3]=4;
- pxor_r2r(mm7,mm7);
- movq_m2r(rounder,mm6);
- }
- for (;size > 3; size-=4) {
- DEINT_INPLACE_LINE_LUM
- lum_m4+=4;
- lum_m3+=4;
- lum_m2+=4;
- lum_m1+=4;
- lum+=4;
- }
-#endif
-}
-
-/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
- top field is copied as is, but the bottom field is deinterlaced
- against the top field. */
-static inline void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
- const uint8_t *src1, int src_wrap,
- int width, int height)
-{
- const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
- int y;
-
- src_m2 = src1;
- src_m1 = src1;
- src_0=&src_m1[src_wrap];
- src_p1=&src_0[src_wrap];
- src_p2=&src_p1[src_wrap];
- for(y=0;y<(height-2);y+=2) {
- memcpy(dst,src_m1,width);
- dst += dst_wrap;
- deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
- src_m2 = src_0;
- src_m1 = src_p1;
- src_0 = src_p2;
- src_p1 += 2*src_wrap;
- src_p2 += 2*src_wrap;
- dst += dst_wrap;
- }
- memcpy(dst,src_m1,width);
- dst += dst_wrap;
- /* do last line */
- deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
-}
-
-static inline void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
- int width, int height)
-{
- uint8_t *src_m1, *src_0, *src_p1, *src_p2;
- int y;
- uint8_t *buf;
- buf = (uint8_t*)av_malloc(width);
-
- src_m1 = src1;
- memcpy(buf,src_m1,width);
- src_0=&src_m1[src_wrap];
- src_p1=&src_0[src_wrap];
- src_p2=&src_p1[src_wrap];
- for(y=0;y<(height-2);y+=2) {
- deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
- src_m1 = src_p1;
- src_0 = src_p2;
- src_p1 += 2*src_wrap;
- src_p2 += 2*src_wrap;
- }
- /* do last line */
- deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
- av_free(buf);
-}
-
-
-/* deinterlace - if not supported return -1 */
-static int mlt_avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
- int pix_fmt, int width, int height)
-{
- int i;
-
- if (pix_fmt != PIX_FMT_YUV420P &&
- pix_fmt != PIX_FMT_YUV422P &&
- pix_fmt != PIX_FMT_YUYV422 &&
- pix_fmt != PIX_FMT_YUV444P &&
- pix_fmt != PIX_FMT_YUV411P)
- return -1;
- if ((width & 3) != 0 || (height & 3) != 0)
- return -1;
-
- if ( pix_fmt != PIX_FMT_YUYV422 )
- {
- for(i=0;i<3;i++) {
- if (i == 1) {
- switch(pix_fmt) {
- case PIX_FMT_YUV420P:
- width >>= 1;
- height >>= 1;
- break;
- case PIX_FMT_YUV422P:
- width >>= 1;
- break;
- case PIX_FMT_YUV411P:
- width >>= 2;
- break;
- default:
- break;
- }
- }
- if (src == dst) {
- deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
- width, height);
- } else {
- deinterlace_bottom_field(dst->data[i],dst->linesize[i],
- src->data[i], src->linesize[i],
- width, height);
- }
- }
- }
- else {
- if (src == dst) {
- deinterlace_bottom_field_inplace(dst->data[0], dst->linesize[0],
- width<<1, height);
- } else {
- deinterlace_bottom_field(dst->data[0],dst->linesize[0],
- src->data[0], src->linesize[0],
- width<<1, height);
- }
- }
-
-#ifdef USE_MMX
- emms();
-#endif
- return 0;
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = 0;
- int deinterlace = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "consumer_deinterlace" );
-
- // Determine if we need a writable version or not
- if ( deinterlace && !writable )
- writable = !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" );
-
- // Get the input image
- error = mlt_frame_get_image( this, image, format, width, height, writable );
-
- // Check that we want progressive and we aren't already progressive
- if ( deinterlace && *format == mlt_image_yuv422 && *image != NULL && !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ) )
- {
- // Create a picture
- AVPicture *output = mlt_pool_alloc( sizeof( AVPicture ) );
-
- // Fill the picture
- if ( *format == mlt_image_yuv422 )
- {
- avpicture_fill( output, *image, PIX_FMT_YUYV422, *width, *height );
- mlt_avpicture_deinterlace( output, output, PIX_FMT_YUYV422, *width, *height );
- }
-
- // Free the picture
- mlt_pool_release( output );
-
- // Make sure that others know the frame is deinterlaced
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "progressive", 1 );
- }
-
- return error;
-}
-
-/** Deinterlace filter processing - this should be lazy evaluation here...
-*/
-
-static mlt_frame deinterlace_process( mlt_filter this, mlt_frame frame )
-{
- // Push the get_image method on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_avdeinterlace_init( void *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- this->process = deinterlace_process;
- return this;
-}
-
+++ /dev/null
-/*
- * filter_avresample.c -- adjust audio sample frequency
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-// ffmpeg Header files
-#include <avformat.h>
-
-/** Get the audio.
-*/
-
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_audio( frame );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the resample information
- int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
- int16_t *sample_buffer = mlt_properties_get_data( filter_properties, "buffer", NULL );
-
- // Obtain the resample context if it exists
- ReSampleContext *resample = mlt_properties_get_data( filter_properties, "audio_resample", NULL );
-
- // Used to return number of channels in the source
- int channels_avail = *channels;
-
- // Loop variable
- int i;
-
- // If no resample frequency is specified, default to requested value
- if ( output_rate == 0 )
- output_rate = *frequency;
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
- // Duplicate channels as necessary
- if ( channels_avail < *channels )
- {
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- int j, k = 0;
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
- k = ( k + 1 ) % channels_avail;
- }
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
- else if ( channels_avail == 6 && *channels == 2 )
- {
- // Nasty hack for ac3 5.1 audio - may be a cause of failure?
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- // Drop all but the first *channels
- for ( i = 0; i < *samples; i++ )
- {
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
-
- // Return now if no work to do
- if ( output_rate != *frequency )
- {
- // Will store number of samples created
- int used = 0;
-
- // Create a resampler if nececessary
- if ( resample == NULL || *frequency != mlt_properties_get_int( filter_properties, "last_frequency" ) )
- {
- // Create the resampler
- resample = audio_resample_init( *channels, *channels, output_rate, *frequency );
-
- // And store it on properties
- mlt_properties_set_data( filter_properties, "audio_resample", resample, 0, ( mlt_destructor )audio_resample_close, NULL );
-
- // And remember what it was created for
- mlt_properties_set_int( filter_properties, "last_frequency", *frequency );
- }
-
- // Resample the audio
- used = audio_resample( resample, sample_buffer, *buffer, *samples );
-
- // Resize if necessary
- if ( used > *samples )
- {
- *buffer = mlt_pool_realloc( *buffer, *samples * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( properties, "audio", *buffer, *channels * used * sizeof( int16_t ), mlt_pool_release, NULL );
- }
-
- // Copy samples
- memcpy( *buffer, sample_buffer, *channels * used * sizeof( int16_t ) );
-
- // Update output variables
- *samples = used;
- *frequency = output_rate;
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Only call this if we have a means to get audio
- if ( mlt_frame_is_test_audio( frame ) == 0 )
- {
- // Push the filter on to the stack
- mlt_frame_push_audio( frame, this );
-
- // Assign our get_audio method
- mlt_frame_push_audio( frame, resample_get_audio );
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_avresample_init( char *arg )
-{
- // Create a filter
- mlt_filter this = mlt_filter_new( );
-
- // Initialise if successful
- if ( this != NULL )
- {
- // Calculate size of the buffer
- int size = AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t );
-
- // Allocate the buffer
- int16_t *buffer = mlt_pool_alloc( size );
-
- // Assign the process method
- this->process = filter_process;
-
- // Deal with argument
- if ( arg != NULL )
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "frequency", arg );
-
- // Default to 2 channel output
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
-
- // Store the buffer
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "buffer", buffer, size, mlt_pool_release, NULL );
- }
-
- return this;
-}
+++ /dev/null
-/*
- * filter_swscale.c -- image scaling filter
- * Copyright (C) 2008-2009 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_factory.h>
-
-
-// ffmpeg Header files
-#include <avformat.h>
-#include <swscale.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_RGB32 PIX_FMT_RGBA32
-#define PIX_FMT_YUYV422 PIX_FMT_YUV422
-#endif
-
-static inline int is_big_endian( )
-{
- union { int i; char c[ 4 ]; } big_endian_test;
- big_endian_test.i = 1;
-
- return big_endian_test.c[ 0 ] != 1;
-}
-
-static inline int convert_mlt_to_av_cs( mlt_image_format format )
-{
- int value = 0;
-
- switch( format )
- {
- case mlt_image_rgb24:
- value = PIX_FMT_RGB24;
- break;
- case mlt_image_rgb24a:
- value = PIX_FMT_RGB32;
- break;
- case mlt_image_yuv422:
- value = PIX_FMT_YUYV422;
- break;
- case mlt_image_yuv420p:
- value = PIX_FMT_YUV420P;
- break;
- case mlt_image_opengl:
- case mlt_image_none:
- fprintf( stderr, "Invalid format...\n" );
- break;
- }
-
- return value;
-}
-
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight )
-{
- // Get the properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the requested interpolation method
- char *interps = mlt_properties_get( properties, "rescale.interp" );
-
- // Convert to the SwScale flag
- int interp = SWS_BILINEAR;
- if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
- interp = SWS_POINT;
- else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
- interp = SWS_FAST_BILINEAR;
- else if ( strcmp( interps, "bilinear" ) == 0 )
- interp = SWS_BILINEAR;
- else if ( strcmp( interps, "bicubic" ) == 0 )
- interp = SWS_BICUBIC;
- else if ( strcmp( interps, "bicublin" ) == 0 )
- interp = SWS_BICUBLIN;
- else if ( strcmp( interps, "gauss" ) == 0 )
- interp = SWS_GAUSS;
- else if ( strcmp( interps, "sinc" ) == 0 )
- interp = SWS_SINC;
- else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "lanczos" ) == 0 )
- interp = SWS_LANCZOS;
- else if ( strcmp( interps, "spline" ) == 0 )
- interp = SWS_SPLINE;
-
- AVPicture input;
- AVPicture output;
- uint8_t *outbuf = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- // Convert the pixel formats
- iformat = convert_mlt_to_av_cs( iformat );
- oformat = convert_mlt_to_av_cs( oformat );
-
- avpicture_fill( &input, *image, iformat, iwidth, iheight );
- avpicture_fill( &output, outbuf, oformat, owidth, oheight );
-
- // Extract the alpha channel
- if ( iformat == PIX_FMT_RGB32 && oformat == PIX_FMT_YUYV422 )
- {
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( iwidth * ( iheight + 1 ) );
- if ( alpha )
- {
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( *image, iwidth, iheight, iwidth * 4, outbuf, alpha );
- mlt_properties_set_data( properties, "alpha", alpha, iwidth * ( iheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
- iformat = PIX_FMT_YUYV422;
- avpicture_fill( &input, outbuf, iformat, iwidth, iheight );
- avpicture_fill( &output, *image, oformat, owidth, oheight );
- }
- }
-
- // Create the context and output image
- struct SwsContext *context = sws_getContext( iwidth, iheight, iformat, owidth, oheight, oformat, interp, NULL, NULL, NULL);
- assert(context);
-
- // Perform the scaling
- sws_scale( context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
- sws_freeContext( context );
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output.data[0], owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- // Return the output
- *image = output.data[0];
-
- // Scale the alpha channel only if exists and not correct size
- int alpha_size = 0;
- mlt_properties_get_data( properties, "alpha", &alpha_size );
- if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) )
- {
- // Create the context and output image
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- if ( alpha )
- {
- iformat = oformat = PIX_FMT_GRAY8;
- struct SwsContext *context = sws_getContext( iwidth, iheight, iformat, owidth, oheight, oformat, interp, NULL, NULL, NULL);
- avpicture_fill( &input, alpha, iformat, iwidth, iheight );
- outbuf = mlt_pool_alloc( owidth * oheight );
- avpicture_fill( &output, outbuf, oformat, owidth, oheight );
-
- // Perform the scaling
- sws_scale( context, input.data, input.linesize, 0, iheight, output.data, output.linesize);
- sws_freeContext( context );
-
- // Set it back on the frame
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", output.data[0], owidth * oheight, mlt_pool_release, NULL );
- }
- }
-
- return 0;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_swscale_init( mlt_profile profile, void *arg )
-{
- // Create a new scaler
- mlt_filter this = mlt_factory_filter( profile, "rescale", arg );
-
- // If successful, then initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Set the inerpolation
- mlt_properties_set( properties, "interpolation", arg == NULL ? "bilinear" : arg );
-
- // Set the method
- mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
- }
-
- return this;
-}
+++ /dev/null
-/*
- * mmx.h
- * Copyright (C) 1997-2001 H. Dietz and R. Fisher
- */
-#ifndef AVCODEC_I386MMX_H
-#define AVCODEC_I386MMX_H
-
-/*
- * The type of an value that fits in an MMX register (note that long
- * long constant values MUST be suffixed by LL and unsigned long long
- * values by ULL, lest they be truncated by the compiler)
- */
-
-typedef union {
- long long q; /* Quadword (64-bit) value */
- unsigned long long uq; /* Unsigned Quadword */
- int d[2]; /* 2 Doubleword (32-bit) values */
- unsigned int ud[2]; /* 2 Unsigned Doubleword */
- short w[4]; /* 4 Word (16-bit) values */
- unsigned short uw[4]; /* 4 Unsigned Word */
- char b[8]; /* 8 Byte (8-bit) values */
- unsigned char ub[8]; /* 8 Unsigned Byte */
- float s[2]; /* Single-precision (32-bit) value */
-} mmx_t; /* On an 8-byte (64-bit) boundary */
-
-
-#define mmx_i2r(op,imm,reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "i" (imm) )
-
-#define mmx_m2r(op,mem,reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "m" (mem))
-
-#define mmx_r2m(op,reg,mem) \
- __asm__ __volatile__ (#op " %%" #reg ", %0" \
- : "=m" (mem) \
- : /* nothing */ )
-
-#define mmx_r2r(op,regs,regd) \
- __asm__ __volatile__ (#op " %" #regs ", %" #regd)
-
-
-#define emms() __asm__ __volatile__ ("emms")
-
-#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
-#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
-#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
-
-#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
-#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
-#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
-
-#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
-#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
-#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
-#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
-
-#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
-#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
-
-#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
-#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
-#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
-#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
-#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
-#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
-
-#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
-#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
-#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
-#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
-
-#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
-#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
-#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
-#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
-
-#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
-#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
-
-#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
-#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
-
-#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
-#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
-#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
-#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
-#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
-#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
-
-#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
-#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
-#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
-#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
-#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
-#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
-
-#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
-#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
-
-#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
-#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
-
-#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
-#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
-
-#define por_m2r(var,reg) mmx_m2r (por, var, reg)
-#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
-
-#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
-#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
-#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
-#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
-#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
-#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
-#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
-#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
-#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
-
-#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
-#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
-#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
-#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
-#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
-#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
-
-#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
-#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
-#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
-#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
-#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
-#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
-#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
-#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
-#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
-
-#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
-#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
-#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
-#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
-#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
-#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
-
-#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
-#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
-#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
-#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
-
-#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
-#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
-#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
-#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
-
-#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
-#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
-#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
-#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
-#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
-#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
-
-#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
-#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
-#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
-#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
-#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
-#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
-
-#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
-#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
-
-
-/* 3DNOW extensions */
-
-#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
-#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
-
-
-/* AMD MMX extensions - also available in intel SSE */
-
-
-#define mmx_m2ri(op,mem,reg,imm) \
- __asm__ __volatile__ (#op " %1, %0, %%" #reg \
- : /* nothing */ \
- : "X" (mem), "X" (imm))
-#define mmx_r2ri(op,regs,regd,imm) \
- __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
- : /* nothing */ \
- : "X" (imm) )
-
-#define mmx_fetch(mem,hint) \
- __asm__ __volatile__ ("prefetch" #hint " %0" \
- : /* nothing */ \
- : "X" (mem))
-
-
-#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
-
-#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
-
-#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
-#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
-#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
-#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
-
-#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
-
-#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
-
-#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
-#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
-
-#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
-#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
-
-#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
-#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
-
-#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
-#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
-
-#define pmovmskb(mmreg,reg) \
- __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
-
-#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
-#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
-
-#define prefetcht0(mem) mmx_fetch (mem, t0)
-#define prefetcht1(mem) mmx_fetch (mem, t1)
-#define prefetcht2(mem) mmx_fetch (mem, t2)
-#define prefetchnta(mem) mmx_fetch (mem, nta)
-
-#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
-#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
-
-#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
-#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
-
-#define sfence() __asm__ __volatile__ ("sfence\n\t")
-
-#endif /* AVCODEC_I386MMX_H */
+++ /dev/null
-/*
- * producer_avformat.c -- avformat producer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- * Much code borrowed from ffmpeg.c: Copyright (c) 2000-2003 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// MLT Header files
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_profile.h>
-
-// ffmpeg Header files
-#include <avformat.h>
-#include <opt.h>
-#ifdef SWSCALE
-# include <swscale.h>
-#endif
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
-# include "audioconvert.h"
-#endif
-
-// System header files
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <math.h>
-
-#if LIBAVUTIL_VERSION_INT < (50<<16)
-#define PIX_FMT_YUYV422 PIX_FMT_YUV422
-#endif
-
-void avformat_lock( );
-void avformat_unlock( );
-
-// Forward references.
-static int producer_open( mlt_producer this, mlt_profile profile, char *file );
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
-
-/** Constructor for libavformat.
-*/
-
-mlt_producer producer_avformat_init( mlt_profile profile, char *file )
-{
- int error = 0;
-
- // Report information about available demuxers and codecs as YAML Tiny
- if ( file && strstr( file, "f-list" ) )
- {
- fprintf( stderr, "---\nformats:\n" );
- AVInputFormat *format = NULL;
- while ( ( format = av_iformat_next( format ) ) )
- fprintf( stderr, " - %s\n", format->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
- if ( file && strstr( file, "acodec-list" ) )
- {
- fprintf( stderr, "---\naudio_codecs:\n" );
- AVCodec *codec = NULL;
- while ( ( codec = av_codec_next( codec ) ) )
- if ( codec->decode && codec->type == CODEC_TYPE_AUDIO )
- fprintf( stderr, " - %s\n", codec->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
- if ( file && strstr( file, "vcodec-list" ) )
- {
- fprintf( stderr, "---\nvideo_codecs:\n" );
- AVCodec *codec = NULL;
- while ( ( codec = av_codec_next( codec ) ) )
- if ( codec->decode && codec->type == CODEC_TYPE_VIDEO )
- fprintf( stderr, " - %s\n", codec->name );
- fprintf( stderr, "...\n" );
- error = 1;
- }
- if ( error )
- return NULL;
-
- mlt_producer this = NULL;
-
- // Check that we have a non-NULL argument
- if ( file != NULL )
- {
- // Construct the producer
- this = calloc( 1, sizeof( struct mlt_producer_s ) );
-
- // Initialise it
- if ( mlt_producer_init( this, NULL ) == 0 )
- {
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Set the resource property (required for all producers)
- mlt_properties_set( properties, "resource", file );
-
- // Register our get_frame implementation
- this->get_frame = producer_get_frame;
-
- // Open the file
- if ( producer_open( this, profile, file ) != 0 )
- {
- // Clean up
- mlt_producer_close( this );
- this = NULL;
- }
- else
- {
- // Close the file to release resources for large playlists - reopen later as needed
- mlt_properties_set_data( properties, "dummy_context", NULL, 0, NULL, NULL );
- mlt_properties_set_data( properties, "audio_context", NULL, 0, NULL, NULL );
- mlt_properties_set_data( properties, "video_context", NULL, 0, NULL, NULL );
-
- // Default the user-selectable indices from the auto-detected indices
- mlt_properties_set_int( properties, "audio_index", mlt_properties_get_int( properties, "_audio_index" ) );
- mlt_properties_set_int( properties, "video_index", mlt_properties_get_int( properties, "_video_index" ) );
- }
- }
- }
-
- return this;
-}
-
-/** Find the default streams.
-*/
-
-static mlt_properties find_default_streams( mlt_properties meta_media, AVFormatContext *context, int *audio_index, int *video_index )
-{
- int i;
- char key[200];
-
- mlt_properties_set_int( meta_media, "meta.media.nb_streams", context->nb_streams );
-
- // Allow for multiple audio and video streams in the file and select first of each (if available)
- for( i = 0; i < context->nb_streams; i++ )
- {
- // Get the codec context
- AVStream *stream = context->streams[ i ];
- if ( ! stream ) continue;
- AVCodecContext *codec_context = stream->codec;
- if ( ! codec_context ) continue;
- AVCodec *codec = avcodec_find_decoder( codec_context->codec_id );
- if ( ! codec ) continue;
-
- snprintf( key, sizeof(key), "meta.media.%d.stream.type", i );
-
- // Determine the type and obtain the first index of each type
- switch( codec_context->codec_type )
- {
- case CODEC_TYPE_VIDEO:
- if ( *video_index < 0 )
- *video_index = i;
- mlt_properties_set( meta_media, key, "video" );
- snprintf( key, sizeof(key), "meta.media.%d.stream.frame_rate", i );
- mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->r_frame_rate ) );
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0)
- snprintf( key, sizeof(key), "meta.media.%d.stream.sample_aspect_ratio", i );
- mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->sample_aspect_ratio ) );
-#endif
- snprintf( key, sizeof(key), "meta.media.%d.codec.pix_fmt", i );
- mlt_properties_set( meta_media, key, avcodec_get_pix_fmt_name( codec_context->pix_fmt ) );
- snprintf( key, sizeof(key), "meta.media.%d.codec.sample_aspect_ratio", i );
- mlt_properties_set_double( meta_media, key, av_q2d( codec_context->sample_aspect_ratio ) );
- break;
- case CODEC_TYPE_AUDIO:
- if ( *audio_index < 0 )
- *audio_index = i;
- mlt_properties_set( meta_media, key, "audio" );
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- snprintf( key, sizeof(key), "meta.media.%d.codec.sample_fmt", i );
- mlt_properties_set( meta_media, key, avcodec_get_sample_fmt_name( codec_context->sample_fmt ) );
-#endif
- snprintf( key, sizeof(key), "meta.media.%d.codec.sample_rate", i );
- mlt_properties_set_int( meta_media, key, codec_context->sample_rate );
- snprintf( key, sizeof(key), "meta.media.%d.codec.channels", i );
- mlt_properties_set_int( meta_media, key, codec_context->channels );
- break;
- default:
- break;
- }
-// snprintf( key, sizeof(key), "meta.media.%d.stream.time_base", i );
-// mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->time_base ) );
- snprintf( key, sizeof(key), "meta.media.%d.codec.name", i );
- mlt_properties_set( meta_media, key, codec->name );
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(55<<8)+0))
- snprintf( key, sizeof(key), "meta.media.%d.codec.long_name", i );
- mlt_properties_set( meta_media, key, codec->long_name );
-#endif
- snprintf( key, sizeof(key), "meta.media.%d.codec.bit_rate", i );
- mlt_properties_set_int( meta_media, key, codec_context->bit_rate );
-// snprintf( key, sizeof(key), "meta.media.%d.codec.time_base", i );
-// mlt_properties_set_double( meta_media, key, av_q2d( codec_context->time_base ) );
- snprintf( key, sizeof(key), "meta.media.%d.codec.profile", i );
- mlt_properties_set_int( meta_media, key, codec_context->profile );
- snprintf( key, sizeof(key), "meta.media.%d.codec.level", i );
- mlt_properties_set_int( meta_media, key, codec_context->level );
- }
-
- return meta_media;
-}
-
-/** Producer file destructor.
-*/
-
-static void producer_file_close( void *context )
-{
- if ( context != NULL )
- {
- // Lock the mutex now
- avformat_lock( );
-
- // Close the file
- av_close_input_file( context );
-
- // Unlock the mutex now
- avformat_unlock( );
- }
-}
-
-/** Producer file destructor.
-*/
-
-static void producer_codec_close( void *codec )
-{
- if ( codec != NULL )
- {
- // Lock the mutex now
- avformat_lock( );
-
- // Close the file
- avcodec_close( codec );
-
- // Unlock the mutex now
- avformat_unlock( );
- }
-}
-
-static inline int dv_is_pal( AVPacket *pkt )
-{
- return pkt->data[3] & 0x80;
-}
-
-static int dv_is_wide( AVPacket *pkt )
-{
- int i = 80 /* block size */ *3 /* VAUX starts at block 3 */ +3 /* skip block header */;
-
- for ( ; i < pkt->size; i += 5 /* packet size */ )
- {
- if ( pkt->data[ i ] == 0x61 )
- {
- uint8_t x = pkt->data[ i + 2 ] & 0x7;
- return ( x == 2 ) || ( x == 7 );
- }
- }
- return 0;
-}
-
-static double get_aspect_ratio( AVStream *stream, AVCodecContext *codec_context, AVPacket *pkt )
-{
- double aspect_ratio = 1.0;
-
- if ( codec_context->codec_id == CODEC_ID_DVVIDEO )
- {
- if ( pkt )
- {
- if ( dv_is_pal( pkt ) )
- {
- aspect_ratio = dv_is_wide( pkt )
- ? 64.0/45.0 // 16:9 PAL
- : 16.0/15.0; // 4:3 PAL
- }
- else
- {
- aspect_ratio = dv_is_wide( pkt )
- ? 32.0/27.0 // 16:9 NTSC
- : 8.0/9.0; // 4:3 NTSC
- }
- }
- else
- {
- AVRational ar =
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0)
- stream->sample_aspect_ratio;
-#else
- codec_context->sample_aspect_ratio;
-#endif
- // Override FFmpeg's notion of DV aspect ratios, which are
- // based upon a width of 704. Since we do not have a normaliser
- // that crops (nor is cropping 720 wide ITU-R 601 video always desirable)
- // we just coerce the values to facilitate a passive behaviour through
- // the rescale normaliser when using equivalent producers and consumers.
- // = display_aspect / (width * height)
- if ( ar.num == 10 && ar.den == 11 )
- aspect_ratio = 8.0/9.0; // 4:3 NTSC
- else if ( ar.num == 59 && ar.den == 54 )
- aspect_ratio = 16.0/15.0; // 4:3 PAL
- else if ( ar.num == 40 && ar.den == 33 )
- aspect_ratio = 32.0/27.0; // 16:9 NTSC
- else if ( ar.num == 118 && ar.den == 81 )
- aspect_ratio = 64.0/45.0; // 16:9 PAL
- }
- }
- else
- {
- AVRational codec_sar = codec_context->sample_aspect_ratio;
- AVRational stream_sar =
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0)
- stream->sample_aspect_ratio;
-#else
- { 0, 1 };
-#endif
- if ( codec_sar.num > 0 )
- aspect_ratio = av_q2d( codec_sar );
- else if ( stream_sar.num > 0 )
- aspect_ratio = av_q2d( stream_sar );
- }
- return aspect_ratio;
-}
-
-/** Open the file.
-*/
-
-static int producer_open( mlt_producer this, mlt_profile profile, char *file )
-{
- // Return an error code (0 == no error)
- int error = 0;
-
- // Context for avformat
- AVFormatContext *context = NULL;
-
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // We will treat everything with the producer fps
- double fps = mlt_profile_fps( profile );
-
- // Lock the mutex now
- avformat_lock( );
-
- // If "MRL", then create AVInputFormat
- AVInputFormat *format = NULL;
- AVFormatParameters *params = NULL;
- char *standard = NULL;
- char *mrl = strchr( file, ':' );
-
- // AV option (0 = both, 1 = video, 2 = audio)
- int av = 0;
-
- // Setting lowest log level
- av_log_set_level( -1 );
-
- // Only if there is not a protocol specification that avformat can handle
- if ( mrl && !url_exist( file ) )
- {
- // 'file' becomes format abbreviation
- mrl[0] = 0;
-
- // Lookup the format
- format = av_find_input_format( file );
-
- // Eat the format designator
- file = ++mrl;
-
- if ( format )
- {
- // Allocate params
- params = calloc( sizeof( AVFormatParameters ), 1 );
-
- // These are required by video4linux (defaults)
- params->width = 640;
- params->height = 480;
- params->time_base= (AVRational){1,25};
- // params->device = file;
- params->channels = 2;
- params->sample_rate = 48000;
- }
-
- // XXX: this does not work anymore since avdevice
- // TODO: make producer_avddevice?
- // Parse out params
- mrl = strchr( file, '?' );
- while ( mrl )
- {
- mrl[0] = 0;
- char *name = strdup( ++mrl );
- char *value = strchr( name, ':' );
- if ( value )
- {
- value[0] = 0;
- value++;
- char *t = strchr( value, '&' );
- if ( t )
- t[0] = 0;
- if ( !strcmp( name, "frame_rate" ) )
- params->time_base.den = atoi( value );
- else if ( !strcmp( name, "frame_rate_base" ) )
- params->time_base.num = atoi( value );
- else if ( !strcmp( name, "sample_rate" ) )
- params->sample_rate = atoi( value );
- else if ( !strcmp( name, "channels" ) )
- params->channels = atoi( value );
- else if ( !strcmp( name, "width" ) )
- params->width = atoi( value );
- else if ( !strcmp( name, "height" ) )
- params->height = atoi( value );
- else if ( !strcmp( name, "standard" ) )
- {
- standard = strdup( value );
- params->standard = standard;
- }
- else if ( !strcmp( name, "av" ) )
- av = atoi( value );
- }
- free( name );
- mrl = strchr( mrl, '&' );
- }
- }
-
- // Now attempt to open the file
- error = av_open_input_file( &context, file, format, 0, params ) < 0;
-
- // Cleanup AVFormatParameters
- free( standard );
- free( params );
-
- // If successful, then try to get additional info
- if ( error == 0 )
- {
- // Get the stream info
- error = av_find_stream_info( context ) < 0;
-
- // Continue if no error
- if ( error == 0 )
- {
- // We will default to the first audio and video streams found
- int audio_index = -1;
- int video_index = -1;
- int av_bypass = 0;
-
- // Now set properties where we can (use default unknowns if required)
- if ( context->duration != AV_NOPTS_VALUE )
- {
- // This isn't going to be accurate for all formats
- mlt_position frames = ( mlt_position )( ( ( double )context->duration / ( double )AV_TIME_BASE ) * fps + 0.5 );
- mlt_properties_set_position( properties, "out", frames - 1 );
- mlt_properties_set_position( properties, "length", frames );
- }
-
- // Find default audio and video streams
- find_default_streams( properties, context, &audio_index, &video_index );
-
- if ( context->start_time != AV_NOPTS_VALUE )
- mlt_properties_set_double( properties, "_start_time", context->start_time );
-
- // Check if we're seekable (something funny about mpeg here :-/)
- if ( strcmp( file, "pipe:" ) && strncmp( file, "http://", 6 ) && strncmp( file, "udp:", 4 ) && strncmp( file, "tcp:", 4 ) && strncmp( file, "rtsp:", 5 ) && strncmp( file, "rtp:", 4 ) )
- {
- mlt_properties_set_int( properties, "seekable", av_seek_frame( context, -1, mlt_properties_get_double( properties, "_start_time" ), AVSEEK_FLAG_BACKWARD ) >= 0 );
- mlt_properties_set_data( properties, "dummy_context", context, 0, producer_file_close, NULL );
- av_open_input_file( &context, file, NULL, 0, NULL );
- av_find_stream_info( context );
- }
- else
- av_bypass = 1;
-
- // Store selected audio and video indexes on properties
- mlt_properties_set_int( properties, "_audio_index", audio_index );
- mlt_properties_set_int( properties, "_video_index", video_index );
- mlt_properties_set_int( properties, "_last_position", -1 );
-
- // Fetch the width, height and aspect ratio
- if ( video_index != -1 )
- {
- AVCodecContext *codec_context = context->streams[ video_index ]->codec;
- mlt_properties_set_int( properties, "width", codec_context->width );
- mlt_properties_set_int( properties, "height", codec_context->height );
-
- if ( codec_context->codec_id == CODEC_ID_DVVIDEO )
- {
- // Fetch the first frame of DV so we can read it directly
- AVPacket pkt;
- int ret = 0;
- while ( ret >= 0 )
- {
- ret = av_read_frame( context, &pkt );
- if ( ret >= 0 && pkt.stream_index == video_index && pkt.size > 0 )
- {
- mlt_properties_set_double( properties, "aspect_ratio",
- get_aspect_ratio( context->streams[ video_index ], codec_context, &pkt ) );
- break;
- }
- }
- }
- else
- {
- mlt_properties_set_double( properties, "aspect_ratio",
- get_aspect_ratio( context->streams[ video_index ], codec_context, NULL ) );
- }
- }
-
- // Read Metadata
- if (context->title != NULL)
- mlt_properties_set(properties, "meta.attr.title.markup", context->title );
- if (context->author != NULL)
- mlt_properties_set(properties, "meta.attr.author.markup", context->author );
- if (context->copyright != NULL)
- mlt_properties_set(properties, "meta.attr.copyright.markup", context->copyright );
- if (context->comment != NULL)
- mlt_properties_set(properties, "meta.attr.comment.markup", context->comment );
- if (context->album != NULL)
- mlt_properties_set(properties, "meta.attr.album.markup", context->album );
- if (context->year != 0)
- mlt_properties_set_int(properties, "meta.attr.year.markup", context->year );
- if (context->track != 0)
- mlt_properties_set_int(properties, "meta.attr.track.markup", context->track );
-
- // We're going to cheat here - for a/v files, we will have two contexts (reasoning will be clear later)
- if ( av == 0 && audio_index != -1 && video_index != -1 )
- {
- // We'll use the open one as our video_context
- mlt_properties_set_data( properties, "video_context", context, 0, producer_file_close, NULL );
-
- // And open again for our audio context
- av_open_input_file( &context, file, NULL, 0, NULL );
- av_find_stream_info( context );
-
- // Audio context
- mlt_properties_set_data( properties, "audio_context", context, 0, producer_file_close, NULL );
- }
- else if ( av != 2 && video_index != -1 )
- {
- // We only have a video context
- mlt_properties_set_data( properties, "video_context", context, 0, producer_file_close, NULL );
- }
- else if ( audio_index != -1 )
- {
- // We only have an audio context
- mlt_properties_set_data( properties, "audio_context", context, 0, producer_file_close, NULL );
- }
- else
- {
- // Something has gone wrong
- error = -1;
- }
-
- mlt_properties_set_int( properties, "av_bypass", av_bypass );
- }
- }
-
- // Unlock the mutex now
- avformat_unlock( );
-
- return error;
-}
-
-/** Convert a frame position to a time code.
-*/
-
-static double producer_time_of_frame( mlt_producer this, mlt_position position )
-{
- return ( double )position / mlt_producer_get_fps( this );
-}
-
-static inline void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt, mlt_image_format format, int width, int height )
-{
-#ifdef SWSCALE
- if ( format == mlt_image_yuv420p )
- {
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
- width, height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- AVPicture output;
- output.data[0] = buffer;
- output.data[1] = buffer + width * height;
- output.data[2] = buffer + ( 3 * width * height ) / 2;
- output.linesize[0] = width;
- output.linesize[1] = width >> 1;
- output.linesize[2] = width >> 1;
- sws_scale( context, frame->data, frame->linesize, 0, height,
- output.data, output.linesize);
- sws_freeContext( context );
- }
- else if ( format == mlt_image_rgb24 )
- {
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
- width, height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- AVPicture output;
- avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
- output.data, output.linesize);
- sws_freeContext( context );
- }
- else
- {
- struct SwsContext *context = sws_getContext( width, height, pix_fmt,
- width, height, PIX_FMT_YUYV422, SWS_FAST_BILINEAR, NULL, NULL, NULL);
- AVPicture output;
- avpicture_fill( &output, buffer, PIX_FMT_YUYV422, width, height );
- sws_scale( context, frame->data, frame->linesize, 0, height,
- output.data, output.linesize);
- sws_freeContext( context );
- }
-#else
- if ( format == mlt_image_yuv420p )
- {
- AVPicture pict;
- pict.data[0] = buffer;
- pict.data[1] = buffer + width * height;
- pict.data[2] = buffer + ( 3 * width * height ) / 2;
- pict.linesize[0] = width;
- pict.linesize[1] = width >> 1;
- pict.linesize[2] = width >> 1;
- img_convert( &pict, PIX_FMT_YUV420P, (AVPicture *)frame, pix_fmt, width, height );
- }
- else if ( format == mlt_image_rgb24 )
- {
- AVPicture output;
- avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
- img_convert( &output, PIX_FMT_RGB24, (AVPicture *)frame, pix_fmt, width, height );
- }
- else
- {
- AVPicture output;
- avpicture_fill( &output, buffer, PIX_FMT_YUYV422, width, height );
- img_convert( &output, PIX_FMT_YUYV422, (AVPicture *)frame, pix_fmt, width, height );
- }
-#endif
-}
-
-/** Allocate the image buffer and set it on the frame.
-*/
-
-static int allocate_buffer( mlt_properties frame_properties, AVCodecContext *codec_context, uint8_t **buffer, mlt_image_format *format, int *width, int *height )
-{
- int size = 0;
-
- if ( codec_context->width == 0 || codec_context->height == 0 )
- return size;
-
- *width = codec_context->width;
- *height = codec_context->height;
- mlt_properties_set_int( frame_properties, "width", *width );
- mlt_properties_set_int( frame_properties, "height", *height );
-
- switch ( *format )
- {
- case mlt_image_yuv420p:
- size = *width * 3 * ( *height + 1 ) / 2;
- break;
- case mlt_image_rgb24:
- size = *width * ( *height + 1 ) * 3;
- break;
- default:
- *format = mlt_image_yuv422;
- size = *width * ( *height + 1 ) * 2;
- break;
- }
-
- // Construct the output image
- *buffer = mlt_pool_alloc( size );
- if ( *buffer )
- mlt_properties_set_data( frame_properties, "image", *buffer, size, (mlt_destructor)mlt_pool_release, NULL );
- else
- size = 0;
-
- return size;
-}
-
-/** Get an image from a frame.
-*/
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the properties from the frame
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the frame number of this frame
- mlt_position position = mlt_properties_get_position( frame_properties, "avformat_position" );
-
- // Get the producer
- mlt_producer this = mlt_properties_get_data( frame_properties, "avformat_producer", NULL );
-
- // Get the producer properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fetch the video_context
- AVFormatContext *context = mlt_properties_get_data( properties, "video_context", NULL );
-
- // Get the video_index
- int index = mlt_properties_get_int( properties, "video_index" );
-
- // Obtain the expected frame numer
- mlt_position expected = mlt_properties_get_position( properties, "_video_expected" );
-
- // Get the video stream
- AVStream *stream = context->streams[ index ];
-
- // Get codec context
- AVCodecContext *codec_context = stream->codec;
-
- // Packet
- AVPacket pkt;
-
- // Get the conversion frame
- AVFrame *av_frame = mlt_properties_get_data( properties, "av_frame", NULL );
-
- // Special case pause handling flag
- int paused = 0;
-
- // Special case ffwd handling
- int ignore = 0;
-
- // We may want to use the source fps if available
- double source_fps = mlt_properties_get_double( properties, "source_fps" );
- double fps = mlt_producer_get_fps( this );
-
- // This is the physical frame position in the source
- int req_position = ( int )( position / fps * source_fps + 0.5 );
-
- // Get the seekable status
- int seekable = mlt_properties_get_int( properties, "seekable" );
-
- // Hopefully provide better support for streams...
- int av_bypass = mlt_properties_get_int( properties, "av_bypass" );
-
- // Determines if we have to decode all frames in a sequence
- int must_decode = 1;
-
- // Temporary hack to improve intra frame only
- must_decode = strcmp( codec_context->codec->name, "dnxhd" ) &&
- strcmp( codec_context->codec->name, "dvvideo" ) &&
- strcmp( codec_context->codec->name, "huffyuv" ) &&
- strcmp( codec_context->codec->name, "mjpeg" ) &&
- strcmp( codec_context->codec->name, "rawvideo" );
-
- // Seek if necessary
- if ( position != expected )
- {
- if ( av_frame != NULL && position + 1 == expected )
- {
- // We're paused - use last image
- paused = 1;
- }
- else if ( !seekable && position > expected && ( position - expected ) < 250 )
- {
- // Fast forward - seeking is inefficient for small distances - just ignore following frames
- ignore = ( int )( ( position - expected ) / fps * source_fps );
- }
- else if ( seekable && ( position < expected || position - expected >= 12 ) )
- {
- // Calculate the timestamp for the requested frame
- int64_t timestamp = ( int64_t )( ( double )req_position / source_fps * AV_TIME_BASE + 0.5 );
- if ( ( uint64_t )context->start_time != AV_NOPTS_VALUE )
- timestamp += context->start_time;
- if ( must_decode )
- timestamp -= AV_TIME_BASE;
- if ( timestamp < 0 )
- timestamp = 0;
-
- // Set to the timestamp
- av_seek_frame( context, -1, timestamp, AVSEEK_FLAG_BACKWARD );
-
- // Remove the cached info relating to the previous position
- mlt_properties_set_int( properties, "_current_position", -1 );
- mlt_properties_set_int( properties, "_last_position", -1 );
- mlt_properties_set_data( properties, "av_frame", NULL, 0, NULL, NULL );
- av_frame = NULL;
- }
- }
-
- // Duplicate the last image if necessary (see comment on rawvideo below)
- int current_position = mlt_properties_get_int( properties, "_current_position" );
- int got_picture = mlt_properties_get_int( properties, "_got_picture" );
- if ( av_frame != NULL && got_picture && ( paused || current_position >= req_position ) && av_bypass == 0 )
- {
- // Duplicate it
- if ( allocate_buffer( frame_properties, codec_context, buffer, format, width, height ) )
- convert_image( av_frame, *buffer, codec_context->pix_fmt, *format, *width, *height );
- else
- mlt_frame_get_image( frame, buffer, format, width, height, writable );
- }
- else
- {
- int ret = 0;
- int int_position = 0;
- got_picture = 0;
-
- av_init_packet( &pkt );
-
- // Construct an AVFrame for YUV422 conversion
- if ( av_frame == NULL )
- av_frame = avcodec_alloc_frame( );
-
- while( ret >= 0 && !got_picture )
- {
- // Read a packet
- ret = av_read_frame( context, &pkt );
-
- // We only deal with video from the selected video_index
- if ( ret >= 0 && pkt.stream_index == index && pkt.size > 0 )
- {
- // Determine time code of the packet
- int_position = ( int )( av_q2d( stream->time_base ) * pkt.dts * source_fps + 0.5 );
- if ( context->start_time != AV_NOPTS_VALUE )
- int_position -= ( int )( context->start_time * source_fps / AV_TIME_BASE + 0.5 );
- int last_position = mlt_properties_get_int( properties, "_last_position" );
- if ( int_position == last_position )
- int_position = last_position + 1;
- mlt_properties_set_int( properties, "_last_position", int_position );
-
- // Decode the image
- if ( must_decode || int_position >= req_position )
- ret = avcodec_decode_video( codec_context, av_frame, &got_picture, pkt.data, pkt.size );
-
- if ( got_picture )
- {
- // Handle ignore
- if ( int_position < req_position )
- {
- ignore = 0;
- got_picture = 0;
- }
- else if ( int_position >= req_position )
- {
- ignore = 0;
- }
- else if ( ignore -- )
- {
- got_picture = 0;
- }
- }
- av_free_packet( &pkt );
- }
- else if ( ret >= 0 )
- {
- av_free_packet( &pkt );
- }
-
- // Now handle the picture if we have one
- if ( got_picture )
- {
- if ( allocate_buffer( frame_properties, codec_context, buffer, format, width, height ) )
- {
- convert_image( av_frame, *buffer, codec_context->pix_fmt, *format, *width, *height );
- mlt_properties_set_int( frame_properties, "progressive", !av_frame->interlaced_frame );
- mlt_properties_set_int( properties, "top_field_first", av_frame->top_field_first );
- mlt_properties_set_int( properties, "_current_position", int_position );
- mlt_properties_set_int( properties, "_got_picture", 1 );
- mlt_properties_set_data( properties, "av_frame", av_frame, 0, av_free, NULL );
- }
- else
- {
- got_picture = 0;
- }
- }
- }
- if ( !got_picture )
- mlt_frame_get_image( frame, buffer, format, width, height, writable );
- }
-
- // Very untidy - for rawvideo, the packet contains the frame, hence the free packet
- // above will break the pause behaviour - so we wipe the frame now
- if ( !strcmp( codec_context->codec->name, "rawvideo" ) )
- mlt_properties_set_data( properties, "av_frame", NULL, 0, NULL, NULL );
-
- // Set the field order property for this frame
- mlt_properties_set_int( frame_properties, "top_field_first", mlt_properties_get_int( properties, "top_field_first" ) );
-
- // Regardless of speed, we expect to get the next frame (cos we ain't too bright)
- mlt_properties_set_position( properties, "_video_expected", position + 1 );
-
- return 0;
-}
-
-/** Process properties as AVOptions and apply to AV context obj
-*/
-
-static void apply_properties( void *obj, mlt_properties properties, int flags )
-{
- int i;
- int count = mlt_properties_count( properties );
- for ( i = 0; i < count; i++ )
- {
- const char *opt_name = mlt_properties_get_name( properties, i );
- const AVOption *opt = av_find_opt( obj, opt_name, NULL, flags, flags );
- if ( opt != NULL )
-#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
- av_set_string3( obj, opt_name, mlt_properties_get( properties, opt_name), 0, NULL );
-#elif LIBAVCODEC_VERSION_INT >= ((51<<16)+(59<<8)+0)
- av_set_string2( obj, opt_name, mlt_properties_get( properties, opt_name), 0 );
-#else
- av_set_string( obj, opt_name, mlt_properties_get( properties, opt_name) );
-#endif
- }
-}
-
-/** Set up video handling.
-*/
-
-static void producer_set_up_video( mlt_producer this, mlt_frame frame )
-{
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fetch the video_context
- AVFormatContext *context = mlt_properties_get_data( properties, "video_context", NULL );
-
- // Get the video_index
- int index = mlt_properties_get_int( properties, "video_index" );
-
- // Reopen the file if necessary
- if ( !context && index > -1 )
- {
- mlt_events_block( properties, this );
- producer_open( this, mlt_service_profile( MLT_PRODUCER_SERVICE(this) ),
- mlt_properties_get( properties, "resource" ) );
- context = mlt_properties_get_data( properties, "video_context", NULL );
- mlt_properties_set_data( properties, "dummy_context", NULL, 0, NULL, NULL );
- mlt_events_unblock( properties, this );
-
- // Process properties as AVOptions
- apply_properties( context, properties, AV_OPT_FLAG_DECODING_PARAM );
- }
-
- // Exception handling for video_index
- if ( context && index >= (int) context->nb_streams )
- {
- // Get the last video stream
- for ( index = context->nb_streams - 1; index >= 0 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_VIDEO; --index );
- mlt_properties_set_int( properties, "video_index", index );
- }
- if ( context && index > -1 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_VIDEO )
- {
- // Invalidate the video stream
- index = -1;
- mlt_properties_set_int( properties, "video_index", index );
- }
-
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- if ( context && index > -1 )
- {
- // Get the video stream
- AVStream *stream = context->streams[ index ];
-
- // Get codec context
- AVCodecContext *codec_context = stream->codec;
-
- // Get the codec
- AVCodec *codec = mlt_properties_get_data( properties, "video_codec", NULL );
-
- // Update the video properties if the index changed
- if ( index != mlt_properties_get_int( properties, "_video_index" ) )
- {
- // Reset the video properties if the index changed
- mlt_properties_set_int( properties, "_video_index", index );
- mlt_properties_set_data( properties, "video_codec", NULL, 0, NULL, NULL );
- mlt_properties_set_int( properties, "width", codec_context->width );
- mlt_properties_set_int( properties, "height", codec_context->height );
- // TODO: get the first usable AVPacket and reset the stream position
- mlt_properties_set_double( properties, "aspect_ratio",
- get_aspect_ratio( context->streams[ index ], codec_context, NULL ) );
- codec = NULL;
- }
-
- // Initialise the codec if necessary
- if ( codec == NULL )
- {
- // Initialise multi-threading
- int thread_count = mlt_properties_get_int( properties, "threads" );
- if ( thread_count == 0 && getenv( "MLT_AVFORMAT_THREADS" ) )
- thread_count = atoi( getenv( "MLT_AVFORMAT_THREADS" ) );
- if ( thread_count > 1 )
- {
- avcodec_thread_init( codec_context, thread_count );
- codec_context->thread_count = thread_count;
- }
-
- // Find the codec
- codec = avcodec_find_decoder( codec_context->codec_id );
-
- // If we don't have a codec and we can't initialise it, we can't do much more...
- avformat_lock( );
- if ( codec != NULL && avcodec_open( codec_context, codec ) >= 0 )
- {
- // Now store the codec with its destructor
- mlt_properties_set_data( properties, "video_codec", codec_context, 0, producer_codec_close, NULL );
- }
- else
- {
- // Remember that we can't use this later
- mlt_properties_set_int( properties, "video_index", -1 );
- index = -1;
- }
- avformat_unlock( );
-
- // Process properties as AVOptions
- apply_properties( codec_context, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
- }
-
- // No codec, no show...
- if ( codec && index > -1 )
- {
- double source_fps = 0;
- double force_aspect_ratio = mlt_properties_get_double( properties, "force_aspect_ratio" );
- double aspect_ratio = ( force_aspect_ratio > 0.0 ) ?
- force_aspect_ratio : mlt_properties_get_double( properties, "aspect_ratio" );
-
- // Determine the fps
- source_fps = ( double )codec_context->time_base.den / ( codec_context->time_base.num == 0 ? 1 : codec_context->time_base.num );
-
- // We'll use fps if it's available
- if ( source_fps > 0 )
- mlt_properties_set_double( properties, "source_fps", source_fps );
- else
- mlt_properties_set_double( properties, "source_fps", mlt_producer_get_fps( this ) );
- mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
-
- // Set the width and height
- mlt_properties_set_int( frame_properties, "width", codec_context->width );
- mlt_properties_set_int( frame_properties, "height", codec_context->height );
- mlt_properties_set_int( frame_properties, "real_width", codec_context->width );
- mlt_properties_set_int( frame_properties, "real_height", codec_context->height );
- mlt_properties_set_double( frame_properties, "aspect_ratio", aspect_ratio );
-
- mlt_frame_push_get_image( frame, producer_get_image );
- mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL );
- }
- else
- {
- mlt_properties_set_int( frame_properties, "test_image", 1 );
- }
- }
- else
- {
- mlt_properties_set_int( frame_properties, "test_image", 1 );
- }
-}
-
-/** Get the audio from a frame.
-*/
-
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties from the frame
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the frame number of this frame
- mlt_position position = mlt_properties_get_position( frame_properties, "avformat_position" );
-
- // Get the producer
- mlt_producer this = mlt_properties_get_data( frame_properties, "avformat_producer", NULL );
-
- // Get the producer properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fetch the audio_context
- AVFormatContext *context = mlt_properties_get_data( properties, "audio_context", NULL );
-
- // Get the audio_index
- int index = mlt_properties_get_int( properties, "audio_index" );
-
- // Get the seekable status
- int seekable = mlt_properties_get_int( properties, "seekable" );
-
- // Obtain the expected frame numer
- mlt_position expected = mlt_properties_get_position( properties, "_audio_expected" );
-
- // Obtain the resample context if it exists (not always needed)
- ReSampleContext *resample = mlt_properties_get_data( properties, "audio_resample", NULL );
-
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- // Get the format converter context if it exists
- AVAudioConvert *convert = mlt_properties_get_data( properties, "audio_convert", NULL );
-#endif
-
- // Obtain the audio buffers
- int16_t *audio_buffer = mlt_properties_get_data( properties, "audio_buffer", NULL );
- int16_t *decode_buffer = mlt_properties_get_data( properties, "decode_buffer", NULL );
- int16_t *convert_buffer = mlt_properties_get_data( properties, "convert_buffer", NULL );
-
- // Get amount of audio used
- int audio_used = mlt_properties_get_int( properties, "_audio_used" );
-
- // Calculate the real time code
- double real_timecode = producer_time_of_frame( this, position );
-
- // Get the audio stream
- AVStream *stream = context->streams[ index ];
-
- // Get codec context
- AVCodecContext *codec_context = stream->codec;
-
- // Packet
- AVPacket pkt;
-
- // Number of frames to ignore (for ffwd)
- int ignore = 0;
-
- // Flag for paused (silence)
- int paused = 0;
-
- // Check for resample and create if necessary
- if ( resample == NULL && codec_context->channels <= 2 )
- {
- // Create the resampler
- resample = audio_resample_init( *channels, codec_context->channels, *frequency, codec_context->sample_rate );
-
- // And store it on properties
- mlt_properties_set_data( properties, "audio_resample", resample, 0, ( mlt_destructor )audio_resample_close, NULL );
- }
- else if ( resample == NULL )
- {
- *channels = codec_context->channels;
- *frequency = codec_context->sample_rate;
- }
-
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- // Check for audio format converter and create if necessary
- // TODO: support higher resolutions than 16-bit.
- if ( convert == NULL && codec_context->sample_fmt != SAMPLE_FMT_S16 )
- {
- // Create single channel converter for interleaved with no mixing matrix
- convert = av_audio_convert_alloc( SAMPLE_FMT_S16, 1, codec_context->sample_fmt, 1, NULL, 0 );
- mlt_properties_set_data( properties, "audio_convert", convert, 0, ( mlt_destructor )av_audio_convert_free, NULL );
- }
-#endif
-
- // Check for audio buffer and create if necessary
- if ( audio_buffer == NULL )
- {
- // Allocate the audio buffer
- audio_buffer = mlt_pool_alloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
-
- // And store it on properties for reuse
- mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
- }
-
- // Check for decoder buffer and create if necessary
- if ( decode_buffer == NULL )
- {
- // Allocate the audio buffer
- decode_buffer = av_malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
-
- // And store it on properties for reuse
- mlt_properties_set_data( properties, "decode_buffer", decode_buffer, 0, ( mlt_destructor )av_free, NULL );
- }
-
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- // Check for format converter buffer and create if necessary
- if ( resample && convert && convert_buffer == NULL )
- {
- // Allocate the audio buffer
- convert_buffer = mlt_pool_alloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
-
- // And store it on properties for reuse
- mlt_properties_set_data( properties, "convert_buffer", convert_buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
- }
-#endif
-
- // Seek if necessary
- if ( position != expected )
- {
- if ( position + 1 == expected )
- {
- // We're paused - silence required
- paused = 1;
- }
- else if ( !seekable && position > expected && ( position - expected ) < 250 )
- {
- // Fast forward - seeking is inefficient for small distances - just ignore following frames
- ignore = position - expected;
- }
- else if ( position < expected || position - expected >= 12 )
- {
- int64_t timestamp = ( int64_t )( real_timecode * AV_TIME_BASE + 0.5 );
- if ( context->start_time != AV_NOPTS_VALUE )
- timestamp += context->start_time;
- if ( timestamp < 0 )
- timestamp = 0;
-
- // Set to the real timecode
- if ( av_seek_frame( context, -1, timestamp, AVSEEK_FLAG_BACKWARD ) != 0 )
- paused = 1;
-
- // Clear the usage in the audio buffer
- audio_used = 0;
- }
- }
-
- // Get the audio if required
- if ( !paused )
- {
- int ret = 0;
- int got_audio = 0;
-
- av_init_packet( &pkt );
-
- while( ret >= 0 && !got_audio )
- {
- // Check if the buffer already contains the samples required
- if ( audio_used >= *samples && ignore == 0 )
- {
- got_audio = 1;
- break;
- }
-
- // Read a packet
- ret = av_read_frame( context, &pkt );
-
- int len = pkt.size;
- uint8_t *ptr = pkt.data;
-
- // We only deal with audio from the selected audio_index
- while ( ptr != NULL && ret >= 0 && pkt.stream_index == index && len > 0 )
- {
- int data_size = sizeof( int16_t ) * AVCODEC_MAX_AUDIO_FRAME_SIZE;
-
- // Decode the audio
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(29<<8)+0))
- ret = avcodec_decode_audio2( codec_context, decode_buffer, &data_size, ptr, len );
-#else
- ret = avcodec_decode_audio( codec_context, decode_buffer, &data_size, ptr, len );
-#endif
- if ( ret < 0 )
- {
- ret = 0;
- break;
- }
-
- len -= ret;
- ptr += ret;
-
- if ( data_size > 0 )
- {
- int src_stride[6]= { av_get_bits_per_sample_format( codec_context->sample_fmt ) / 8 };
- int dst_stride[6]= { av_get_bits_per_sample_format( SAMPLE_FMT_S16 ) / 8 };
-
- if ( resample )
- {
- int16_t *source = decode_buffer;
- int16_t *dest = &audio_buffer[ audio_used * *channels ];
- int convert_samples = data_size / src_stride[0];
-
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- if ( convert )
- {
- const void *src_buf[6] = { decode_buffer };
- void *dst_buf[6] = { convert_buffer };
- av_audio_convert( convert, dst_buf, dst_stride, src_buf, src_stride, convert_samples );
- source = convert_buffer;
- }
-#endif
- audio_used += audio_resample( resample, dest, source, convert_samples / codec_context->channels );
- }
- else
- {
-#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
- if ( convert )
- {
- const void *src_buf[6] = { decode_buffer };
- void *dst_buf[6] = { &audio_buffer[ audio_used * *channels ] };
- av_audio_convert( convert, dst_buf, dst_stride, src_buf, src_stride, data_size / src_stride[0] );
- }
- else
-#endif
- {
- memcpy( &audio_buffer[ audio_used * *channels ], decode_buffer, data_size );
- }
- audio_used += data_size / *channels / src_stride[0];
- }
-
- // Handle ignore
- while ( ignore && audio_used > *samples )
- {
- ignore --;
- audio_used -= *samples;
- memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * sizeof( int16_t ) );
- }
- }
-
- // If we're behind, ignore this packet
- if ( pkt.pts >= 0 )
- {
- double current_pts = av_q2d( stream->time_base ) * pkt.pts;
- double source_fps = mlt_properties_get_double( properties, "source_fps" );
- int req_position = ( int )( real_timecode * source_fps + 0.5 );
- int int_position = ( int )( current_pts * source_fps + 0.5 );
-
- if ( context->start_time != AV_NOPTS_VALUE )
- int_position -= ( int )( context->start_time * source_fps / AV_TIME_BASE + 0.5 );
- if ( seekable && !ignore && int_position < req_position )
- ignore = 1;
- }
- }
-
- // We're finished with this packet regardless
- av_free_packet( &pkt );
- }
-
- *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Now handle the audio if we have enough
- if ( audio_used >= *samples )
- {
- memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
- audio_used -= *samples;
- memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
- }
- else
- {
- memset( *buffer, 0, *samples * *channels * sizeof( int16_t ) );
- }
-
- // Store the number of audio samples still available
- mlt_properties_set_int( properties, "_audio_used", audio_used );
- }
- else
- {
- // Get silence and don't touch the context
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- }
-
- // Regardless of speed (other than paused), we expect to get the next frame
- if ( !paused )
- mlt_properties_set_position( properties, "_audio_expected", position + 1 );
-
- return 0;
-}
-
-/** Set up audio handling.
-*/
-
-static void producer_set_up_audio( mlt_producer this, mlt_frame frame )
-{
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fetch the audio_context
- AVFormatContext *context = mlt_properties_get_data( properties, "audio_context", NULL );
-
- // Get the audio_index
- int index = mlt_properties_get_int( properties, "audio_index" );
-
- // Reopen the file if necessary
- if ( !context && index > -1 )
- {
- mlt_events_block( properties, this );
- producer_open( this, mlt_service_profile( MLT_PRODUCER_SERVICE(this) ),
- mlt_properties_get( properties, "resource" ) );
- context = mlt_properties_get_data( properties, "audio_context", NULL );
- mlt_properties_set_data( properties, "dummy_context", NULL, 0, NULL, NULL );
- mlt_events_unblock( properties, this );
- }
-
- // Exception handling for audio_index
- if ( context && index >= (int) context->nb_streams )
- {
- for ( index = context->nb_streams - 1; index >= 0 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_AUDIO; --index );
- mlt_properties_set_int( properties, "audio_index", index );
- }
- if ( context && index > -1 && context->streams[ index ]->codec->codec_type != CODEC_TYPE_AUDIO )
- {
- index = -1;
- mlt_properties_set_int( properties, "audio_index", index );
- }
-
- // Update the audio properties if the index changed
- if ( index > -1 && index != mlt_properties_get_int( properties, "_audio_index" ) )
- {
- mlt_properties_set_int( properties, "_audio_index", index );
- mlt_properties_set_data( properties, "audio_codec", NULL, 0, NULL, NULL );
- }
-
- // Deal with audio context
- if ( context != NULL && index > -1 )
- {
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the audio stream
- AVStream *stream = context->streams[ index ];
-
- // Get codec context
- AVCodecContext *codec_context = stream->codec;
-
- // Get the codec
- AVCodec *codec = mlt_properties_get_data( properties, "audio_codec", NULL );
-
- // Initialise the codec if necessary
- if ( codec == NULL )
- {
- // Find the codec
- codec = avcodec_find_decoder( codec_context->codec_id );
-
- // If we don't have a codec and we can't initialise it, we can't do much more...
- avformat_lock( );
- if ( codec != NULL && avcodec_open( codec_context, codec ) >= 0 )
- {
- // Now store the codec with its destructor
- mlt_properties_set_data( properties, "audio_codec", codec_context, 0, producer_codec_close, NULL );
-
- }
- else
- {
- // Remember that we can't use this later
- mlt_properties_set_int( properties, "audio_index", -1 );
- index = -1;
- }
- avformat_unlock( );
-
- // Process properties as AVOptions
- apply_properties( codec_context, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
- }
-
- // No codec, no show...
- if ( codec && index > -1 )
- {
- mlt_frame_push_audio( frame, producer_get_audio );
- mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL );
- mlt_properties_set_int( frame_properties, "frequency", codec_context->sample_rate );
- mlt_properties_set_int( frame_properties, "channels", codec_context->channels );
- }
- }
-}
-
-/** Our get frame implementation.
-*/
-
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Create an empty frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
-
- // Set the position of this producer
- mlt_properties_set_position( MLT_FRAME_PROPERTIES( *frame ), "avformat_position", mlt_producer_frame( this ) );
-
- // Set up the video
- producer_set_up_video( this, *frame );
-
- // Set up the audio
- producer_set_up_audio( this, *frame );
-
- // Set the aspect_ratio
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( *frame ), "aspect_ratio", mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this ), "aspect_ratio" ) );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( this );
-
- return 0;
-}
+++ /dev/null
-schema_version: 0.1
-type: producer # consumer, filter, producer, or transition
-identifier: avformat
-title: FFmpeg Reader
-version: 0.2.5
-copyright: Copyright (C) 2003-2008 Ushodaya Enterprises Limited
-license: LGPL
-language: en
-url: http://www.ffmpeg.org/
-creator: Charles Yates
-contributor:
- - Dan Dennedy
-tags:
- - Audio # this may produce audio
- - Video # this may produce video
-description: Read an audio and/or video file using FFmpeg
-icon:
- filename: avformat/producer.png # relative to $MLT_DATA/modules/
- content-type: image/png
- content-encoding: base64 # could also be hex or none if inline SVG
- content: |
- iVBORw0KGgoAAAANSUhEUgAAABgAAAAPCAYAAAD+pA/bAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
- WXMAAAsSAAALEgHS3X78AAAAB3RJTUUH1gsBEgMLZIL+swAAAB10RVh0Q29tbWVudABDcmVhdGVk
- IHdpdGggVGhlIEdJTVDvZCVuAAAEgUlEQVQ4y2VUSWwbZRT+5p/xP4v3eIntceLEThOylKgkB070
- UAUOCNFDFYkIVeqBijMHQKiCAwLEDbVIPVQCUalFQggph6pUoWKRWoS6RCGJ04biOG7sOI638TJe
- xjM/FwwRfKf3vve99+kd3uNubNxgVb0Km2W7Tbt06fQLpwv4G8u3k6/88nvJcXYhnJ+dGfsRR/Dl
- 8tqpfKkZJ736d++cf6nU53Nra0utTOarVrMpdCj9XFhJr2C1sQq1pZ6ac8zNAljpi7ezzc+e5Lvx
- je29H8rlyk8DA14GAOl05tT1n6tf39uqBM69GFgAsNjvaezsvKVfuyZkKxXIi4tvknn/PCQi4cA4
- QMQf+aIv3Nvbm0sVTGe9zfDg8eGxUrk83689eFQcyhStQLluYG+/NNfny6VSsLW5Ge3pOjSHAy2e
- /4TwjP84KAfBKRzW99f59G7aAQCVav20SZQAtdlQbfGxteTuNACkd/dsguR8W9NNiKKEVFbjisUi
- BQAtnz8rFAq+LgAWDjN/IpEkk97JzYQjAdkhI2fkwtVG9X0AWN+pwTA5iJSH1qEoaMZC8tFjfv3J
- IckcdiYNk0GUZVRbXKipt5YAoP7wYZDXNKHOGKR4fCs+NbVGBpwDt3zw3VEUBbqo437qvjuXy7kr
- HbtqWQzUJgC8Ar2Dpe1UXpgZC763W+RAOAaR2tAxRTmV3kvsJJPjSrf7umEYqAoC1NnZVCAY3CLD
- 6nBpfnC+4hJc4B08DGqc1xr1l5126RzAIHAWqCjjj1wb8eHQq9uZ6nS9a4PAmaACD8bLWN16itrG
- hoJ8Ptw2TVjRKAZjsWUAIABACHk3RmOQ7BIyegbpg/1oqWGBoAc0U5BFAt20o1CqXSk26YLZM8Aa
- u5AEAwKV4XQNLHpGRq5zpRJ0QuCdmUGpUPgGAAQAoKBPJ5wTyDfzKLMyGMGntRZAmIHxMA/TTnDA
- e3FvM+siXhfMdgXjIQbmUpCvMjTa7fFG5imUdhtNSYIcCCxHx8Y6/2zgUTwNq2Nd8FIvYAHFch1d
- RmHjuhhVfdnjI1LPYVeQaw3gsMZAmYYTk+oT1SdBkiSU6z3U6k30AHR9PrhU9WYoHP7XYHR41Jpw
- TxSDQhAuzgXLtIMQG0RioFwuX3IrwiWPnUByDsKyGPxKB5S3Phj0UkgiRdMQ0FYcqBECFgj8GY7F
- 7vZvg/QDl+S66mg5fg2IATDBC45jkPgOJhODLa8dN4d8BJQKYN06RgfF/eNTibRpWVcdsg2MV1An
- FJrbDfXEiWxEVdf/ZxCPxVvTnmkjqgzB4p0gMGGnPUyMjUANupNusXNHpDxYt4wR1XtrKBq9a3W0
- B047hSg7ofUIxMlJePz+K0d/FjmahLyh146rzyUNw0Jby8LGWvckSbwcjUayx1RpzWZWELR3jZln
- Eh8CwDFVgcLr4HpNVDtMi588ecEbCHx7dKZwNBkODed+W318Zipk3Rx1iTG9GbwYiUQMAAj53Zef
- H2u/Ua16L4ZCgykA8A94vn/W1DdH3dK0wIdXwkNDH+E/+Avfv/E5LPIz8wAAAABJRU5ErkJggg==
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - Audio sync discrepancy with some content.
- - Not all libavformat supported formats are seekable.
- - >
- Seeking is not always accurate. Sometimes it doesn't seek to I-frames so you
- may get junk for a few frames.
- - >
- Fails to play beyond first frame of video of sources with PTS not starting
- at 0 (video4linux).
-
-parameters:
- - identifier: argument # 'argument' is a reserved name for a value supplied to the factory
- title: File # the title can be used as a label for the widget
- type: string
- description: |
- A file name specification or URL in the form:
- [{protocol}|{format}]:{resource}[?{format-parameter}[&{format-parameter}...]]
- For example, video4linux:/dev/video1?width:320&height:240
- Note: on the bash command line, & must be escaped as '\&'.
- Also, note the use of ':' instead of '=' for parameters.
- Use 'f-list' to see a list of supported file formats.
- Use 'vcodec-list' to see a list of supported video decoders.
- Use 'acodec-list' to see a list of supported audio decoders.
- readonly: no
- required: yes
- mutable: no
- widget: fileopen # could provide a button to use a file-open dialog
-
- - identifier: audio_index # the name is the mlt_properties name
- title: Audio Index
- type: integer
- # the description can be used in a tool tip
- description: Choose the index of audio stream to use (-1 is off)
- readonly: no
- mutable: no
- minimum: -1
- # when maximum not specified, the scalar limit is used
- default: 0
- widget: spinner
-
- - identifier: video_index
- title: Video Index
- type: integer
- description: Choose the index of video stream to use (-1 is off)
- readonly: no
- mutable: no
- minimum: -1
- default: 0
- widget: spinner
-
- - identifier: in
- title: In Point
- type: time # time is not implemented, but it will correspond to the mlt_position replacement
- description: Set the start time offset to use within the clip
- readonly: no
- mutable: no
- minimum: 0
- default: 0
- widget: timecode # this is a special form of time value/code entry (e.g. see Kino)
-
- - identifier: out
- title: Out Point
- type: time
- description: Set the ending time offset to use within the clip
- readonly: no
- minimum: 0
- mutable: no
- widget: timecode # as opposed to time, which could be confused for a wallclock-style time widget
-
- - identifier: threads
- title: Decoding Threads
- type: integer
- description: Choose the number of threads to use in the decoder(s)
- readonly: no
- mutable: no
- minimum: 0
- maximum: 4
- default: 1
- widget: spinner
- unit: threads # the unit is a label that appears after the widget
-
- - identifier: force_aspect_ratio
- title: Sample Aspect Ratio
- type: float
- description: Optionally override a (mis)detected aspect ratio
- readonly: no
- mutable: yes
- minimum: 0.001 # just a UI suggestion
- maximum: 9.999 # just a suggestion
- # no default property means it should be blank in the UI and not applied unless provided
-
- - identifier: resource
- title: File
- type: string
- description: file or protocol specification
- readonly: yes
-
- - identifier: source_fps
- title: Frame Rate
- type: float
- scale: 2 # scale is the number of digits to display after the decimal point
- description: the framerate of the resource
- readonly: yes
- unit: frames/second
-
- - identifier: aspect_ratio
- title: Sample Aspect Ratio
- type: float
- description: >
- The sample aspect ratio of the resource.
- This is determined on every frame read.
- readonly: yes
-
- - identifier: length
- title: Duration
- type: time
- description: duration
- readonly: yes
- widget: timecode
-
- - identifier: seekable
- title: Supports Seek
- type: integer
- description: if the resource can seek
- readonly: yes
+++ /dev/null
-#!/bin/sh
-
-# Clean up disables if not in help mode
-[ "$help" != "1" ] && rm -f disable-* producers.dat filters.dat transitions.dat consumers.dat
-
-# Create the make.inc file
-echo SUBDIRS = `find . -maxdepth 1 -type d | grep -v .svn | grep -v "^.$" | sed 's/\.\///'` > make.inc
-
-# Iterate through arguments
-for i in "$@"
-do
- case $i in
- --disable-* ) touch disable-${i#--disable-} ;;
- esac
-done
-
-# Iterate through each of the components
-for i in *
-do
- if [ -d $i -a \( "$help" = "1" -o ! -f disable-$i \) ]
- then
- if [ "$gpl" = "true" -o ! -f $i/gpl ]
- then
- [ -f $i/Makefile -a "$help" = "0" ] && echo "Configuring modules/$i:"
- if [ -x $i/configure ]
- then
- olddir2=`pwd`
- cd $i
- ./configure "$@"
- [ $? != 0 ] && exit 1
- cd $olddir2
- elif [ -f $i/configure ]
- then
- echo " configure script is not set executable!"
- fi
- elif [ "$help" = "0" ]
- then
- touch disable-$i
- fi
- fi
-done
-
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltcore$(LIBSUF)
-
-OBJS = factory.o \
- producer_colour.o \
- producer_consumer.o \
- producer_noise.o \
- producer_ppm.o \
- filter_brightness.o \
- filter_channelcopy.o \
- filter_crop.o \
- filter_data_feed.o \
- filter_data_show.o \
- filter_gamma.o \
- filter_greyscale.o \
- filter_luma.o \
- filter_mirror.o \
- filter_mono.o \
- filter_obscure.o \
- filter_region.o \
- filter_rescale.o \
- filter_resize.o \
- filter_transition.o \
- filter_watermark.o \
- transition_composite.o \
- transition_luma.o \
- transition_mix.o \
- transition_region.o \
- consumer_null.o
-
-ASM_OBJS =
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS) $(ASM_OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(ASM_OBJS) $(LDFLAGS)
-
-composite_line_yuv_mmx.o: composite_line_yuv_mmx.S
- $(CC) -o $@ -c composite_line_yuv_mmx.S
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(ASM_OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
- install -m 644 ../data_fx.properties "$(DESTDIR)$(prefix)/share/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
- .file "composite_line_yuv_mmx"
- .version "01.01"
-
-gcc2_compiled.:
-.data
-
-.text
- .align 16
-
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-.globl composite_line_yuv_mmx
- .type composite_line_yuv_mmx,@function
-composite_line_yuv_mmx:
-#else
-.globl _composite_line_yuv_mmx
-_composite_line_yuv_mmx:
-#endif
-
-/*
- * Arguments
- *
- * dest: 8(%ebp) %esi
- * src: 12(%ebp)
- * width_src: 16(%ebp)
- * alpha: 20(%ebp)
- * weight: 24(%ebp)
- * luma: 28(%ebp)
- * softness: 32(%ebp)
- */
-
-/*
- * Function call entry
- */
- pushl %ebp
- movl %esp,%ebp
- subl $28,%esp
- pushl %edi
- pushl %esi
- pushl %ebx
-
-/* Initialise */
- movl 8(%ebp), %esi # get dest
- movl $0, %edx # j = 0
-
-.loop:
-
- movl $0xffff, %ecx # a = 255
- cmpl $0, 20(%ebp) # if alpha == NULL
- je .noalpha
- movl 20(%ebp), %edi # a = alpha[ j ]
- movb (%edi,%edx), %cl
-.noalpha:
- movl %ecx, -24(%ebp) # save ecx
-
- movl 24(%ebp), %eax # mix = weight
- cmpl $0, 28(%ebp) # if luma == NULL
- je .noluma
- movl 28(%ebp), %edi # mix = ...
- movl %edx, %ebx
- sall $1, %ebx
- movw (%edi,%ebx), %bx # luma[ j*2 ]
- cmpl %ebx, %eax
- jl .luma0
- movl %ebx, %ecx
- addl 32(%ebp), %ecx # + softness
- cmpl %ecx, %eax
- jge .luma1
- /* TODO: linear interpolate between edges */
- subw %bx, %ax
- sall $8, %eax
- subw %bx, %cx
- movl %edx, %ebx
- divw %cx
- movl %ebx, %edx
- jmp .noluma
-.luma0:
- movl $0, %eax
- jmp .noluma
-.luma1:
- movl $0xffff, %eax
-.noluma:
- shrl $8, %eax
-
- movl %edx, %ebx # edx will be destroyed by mulw
- movl -24(%ebp), %ecx # restore ecx
- mull %ecx # mix = mix * a...
- movl %ebx, %edx # restore edx
- shrl $8, %eax # >>8
- andl $0xff, %eax
-
-/* put alpha and (1-alpha) into mm0 */
-/* 0 aa 0 1-a 0 aa 0 1-a */
-
- /* duplicate word */
- movl %eax, %ecx
- shll $16, %ecx
- orl %eax, %ecx
-
- movd %ecx, %mm1
-
- /* (1 << 16) - mix */
- movl $0x000000ff, %ecx
- subl %eax, %ecx
- andl $0xff, %ecx
-
- /* duplicate word */
- movl %ecx, %eax
- shll $16, %eax
- orl %eax, %ecx
-
- movd %ecx, %mm0
-
- /* unpack words into double words */
- punpcklwd %mm1, %mm0
-
-/* put src yuv and dest yuv into mm1 */
-/* 0 UVs 0 UVd 0 Ys 0 Yd */
-
- movl 12(%ebp), %edi # get src
- movb (%edi), %cl
- shll $8, %ecx
- movb 1(%edi), %al
- shll $24, %eax
- orl %eax, %ecx
-
- movb (%esi), %al # get dest
- orl %eax, %ecx
- movb 1(%esi), %al
- shll $16, %eax
- orl %eax, %ecx
-
- movd %ecx, %mm1
- punpcklbw %mm4, %mm1
-
-/* alpha composite */
- pmaddwd %mm1, %mm0
- psrld $8, %mm0
-
-/* store result */
- movd %mm0, %eax
- movb %al, (%esi)
- pextrw $2, %mm0, %eax
- movl $128, %eax
- movb %al, 1(%esi)
-
-/* for..next */
- addl $1, %edx # j++
- cmpl 16(%ebp), %edx # if ( j == width_src )
- jge .out
-
- addl $2, %esi
- addl $2, 12(%ebp)
-
- jmp .loop
-
-.out:
- emms
- leal -40(%ebp),%esp
- popl %ebx
- popl %esi
- popl %edi
- movl %ebp,%esp
- popl %ebp
- ret
-
-
-/********************************************/
-
-.align 8
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-.globl composite_have_mmx
- .type composite_have_mmx,@function
-composite_have_mmx:
-#else
-.globl _composite_have_mmx
-_composite_have_mmx:
-#endif
-
- push %ebx
-
-# Check if bit 21 in flags word is writeable
-
- pushfl
- popl %eax
- movl %eax,%ebx
- xorl $0x00200000, %eax
- pushl %eax
- popfl
- pushfl
- popl %eax
-
- cmpl %eax, %ebx
-
- je .notfound
-
-# OK, we have CPUID
-
- movl $1, %eax
- cpuid
-
- test $0x00800000, %edx
- jz .notfound
-
- movl $1, %eax
- jmp .out2
-
-.notfound:
- movl $0, %eax
-.out2:
- popl %ebx
- ret
+++ /dev/null
-/*
- * consumer_null.c -- a null consumer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// mlt Header files
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-
-// System header files
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.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 void *consumer_thread( void *arg );
-static void consumer_close( mlt_consumer this );
-
-/** Initialise the dv consumer.
-*/
-
-mlt_consumer consumer_null_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Allocate the consumer
- mlt_consumer this = mlt_consumer_new( profile );
-
- // If memory allocated and initialises without error
- if ( this != NULL )
- {
- // Assign close callback
- this->close = consumer_close;
-
- // Set up start/stop/terminated callbacks
- this->start = consumer_start;
- this->stop = consumer_stop;
- this->is_stopped = consumer_is_stopped;
- }
-
- // Return this
- 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 );
- mlt_properties_set_int( properties, "joined", 0 );
-
- // 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, "joined" ) )
- {
- // Get the thread
- pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
-
- // Stop the thread
- mlt_properties_set_int( properties, "running", 0 );
- mlt_properties_set_int( properties, "joined", 1 );
-
- // 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" );
-}
-
-/** The main thread - the argument is simply the consumer.
-*/
-
-static void *consumer_thread( void *arg )
-{
- // Map the argument to the object
- mlt_consumer this = arg;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Convenience functionality
- int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
- int terminated = 0;
-
- // Frame and size
- mlt_frame frame = NULL;
-
- // Loop while running
- while( !terminated && mlt_properties_get_int( properties, "running" ) )
- {
- // Get the frame
- frame = mlt_consumer_rt_frame( this );
-
- // Check for termination
- if ( terminate_on_pause && frame != NULL )
- terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;
-
- // Check that we have a frame to work with
- if ( frame != NULL )
- {
- // Close the frame
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
- mlt_frame_close( frame );
- }
- }
-
- // Indicate that the consumer is stopped
- mlt_properties_set_int( properties, "running", 0 );
- mlt_consumer_stopped( this );
-
- return NULL;
-}
-
-/** Close the consumer.
-*/
-
-static void consumer_close( mlt_consumer this )
-{
- // Stop the consumer
- mlt_consumer_stop( this );
-
- // Close the parent
- mlt_consumer_close( this );
-
- // Free the memory
- free( this );
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-#include <string.h>
-
-extern mlt_consumer consumer_null_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_brightness_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_channelcopy_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_data_feed_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_data_show_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_gamma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_greyscale_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_obscure_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_rescale_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_resize_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_transition_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_watermark_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_colour_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_consumer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_noise_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_ppm_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-#include "transition_composite.h"
-extern mlt_transition transition_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-#include "transition_region.h"
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "null", consumer_null_init );
- MLT_REGISTER( filter_type, "brightness", filter_brightness_init );
- MLT_REGISTER( filter_type, "channelcopy", filter_channelcopy_init );
- MLT_REGISTER( filter_type, "crop", filter_crop_init );
- MLT_REGISTER( filter_type, "data_feed", filter_data_feed_init );
- MLT_REGISTER( filter_type, "data_show", filter_data_show_init );
- MLT_REGISTER( filter_type, "gamma", filter_gamma_init );
- MLT_REGISTER( filter_type, "greyscale", filter_greyscale_init );
- MLT_REGISTER( filter_type, "grayscale", filter_greyscale_init );
- MLT_REGISTER( filter_type, "luma", filter_luma_init );
- MLT_REGISTER( filter_type, "mirror", filter_mirror_init );
- MLT_REGISTER( filter_type, "mono", filter_mono_init );
- MLT_REGISTER( filter_type, "obscure", filter_obscure_init );
- MLT_REGISTER( filter_type, "region", filter_region_init );
- MLT_REGISTER( filter_type, "rescale", filter_rescale_init );
- MLT_REGISTER( filter_type, "resize", filter_resize_init );
- MLT_REGISTER( filter_type, "transition", filter_transition_init );
- MLT_REGISTER( filter_type, "watermark", filter_watermark_init );
- MLT_REGISTER( producer_type, "color", producer_colour_init );
- MLT_REGISTER( producer_type, "colour", producer_colour_init );
- MLT_REGISTER( producer_type, "consumer", producer_consumer_init );
- MLT_REGISTER( producer_type, "noise", producer_noise_init );
- MLT_REGISTER( producer_type, "ppm", producer_ppm_init );
- MLT_REGISTER( transition_type, "composite", transition_composite_init );
- MLT_REGISTER( transition_type, "luma", transition_luma_init );
- MLT_REGISTER( transition_type, "mix", transition_mix_init );
- MLT_REGISTER( transition_type, "region", transition_region_init );
-}
+++ /dev/null
-/*
- * filter_brightness.c -- gamma filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define CLAMP( x, min, max ) (x) < (min) ? (min) : (x) > (max) ? (max) : (x)
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // Get the brightness level
- double level = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "brightness" );
-
- // Only process if level is something other than 1
- if ( level != 1.0 )
- {
- int i = *width * *height + 1;
- uint8_t *p = *image;
- int32_t m = level * ( 1 << 16 );
- int32_t n = 128 * ( ( 1 << 16 ) - m );
-
- while ( --i )
- {
- p[0] = CLAMP( (p[0] * m) >> 16, 16, 235 );
- p[1] = CLAMP( (p[1] * m + n) >> 16, 16, 240 );
- p += 2;
- }
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the starting brightness level
- double level = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "start" ) );
-
- // If there is an end adjust gain to the range
- if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
- mlt_position time = mlt_frame_get_position( frame );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "end" ) );
- level += ( end - level ) * position;
- }
-
- // Push the frame filter
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "brightness", level );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_brightness_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "1" : arg );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_channelcopy.c -- copy one audio channel to another
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#define __USE_ISOC99 1
-#include <math.h>
-
-/** Get the audio.
-*/
-
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the a frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- int i, j;
- int from = mlt_properties_get_int( properties, "channelcopy.from" );
- int to = mlt_properties_get_int( properties, "channelcopy.to" );
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
-
- // Duplicate channels as necessary
- {
- int size = *channels * *samples * 2;
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * *channels ) + ( j == to ? from : j ) ];
- }
- }
- *buffer = new_buffer;
- }
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- mlt_properties frame_props = MLT_FRAME_PROPERTIES( frame );
-
- // Propogate the parameters
- mlt_properties_set_int( frame_props, "channelcopy.to", mlt_properties_get_int( properties, "to" ) );
- mlt_properties_set_int( frame_props, "channelcopy.from", mlt_properties_get_int( properties, "from" ) );
-
- // Override the get_audio method
- mlt_frame_push_audio( frame, filter_get_audio );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_channelcopy_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "to", atoi( arg ) );
- else
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "to", 1 );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_crop.c -- cropping filter
- * Copyright (C) 2009 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_log.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-static void crop( uint8_t *src, uint8_t *dest, int bpp, int width, int height, int left, int right, int top, int bottom )
-{
- int stride = ( width - left - right ) * bpp + 1;
- int y = height - top - bottom + 1;
- uint8_t *s = &src[ ( ( top * width ) + left ) * bpp ];
-
- while ( --y )
- {
- int x = stride;
- while ( --x )
- *dest ++ = *s ++;
- s += ( right + left ) * bpp;
- }
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = 0;
-
- // Get the properties from the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Correct Width/height if necessary
- if ( *width == 0 || *height == 0 )
- {
- *width = mlt_properties_get_int( properties, "normalised_width" );
- *height = mlt_properties_get_int( properties, "normalised_height" );
- }
-
- // Now get the image
- error = mlt_frame_get_image( this, image, format, width, height, writable );
-
- int left = mlt_properties_get_int( properties, "crop.left" );
- int right = mlt_properties_get_int( properties, "crop.right" );
- int top = mlt_properties_get_int( properties, "crop.top" );
- int bottom = mlt_properties_get_int( properties, "crop.bottom" );
- int owidth = *width - left - right;
- int oheight = *height - top - bottom;
-
- // We only know how to process yuv422 at the moment
- if ( ( owidth != *width || oheight != *height ) &&
- error == 0 && *format == mlt_image_yuv422 && *image != NULL && owidth > 0 && oheight > 0 )
- {
- // Provides a manual override for misreported field order
- if ( mlt_properties_get( properties, "meta.top_field_first" ) )
- {
- mlt_properties_set_int( properties, "top_field_first", mlt_properties_get_int( properties, "meta.top_field_first" ) );
- mlt_properties_set_int( properties, "meta.top_field_first", 0 );
- }
-
- if ( top % 2 )
- mlt_properties_set_int( properties, "top_field_first", !mlt_properties_get_int( properties, "top_field_first" ) );
-
- left -= left % 2;
- owidth = *width - left - right;
-
- // Create the output image
- uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
- if ( output )
- {
- // Call the generic resize
- crop( *image, output, 2, *width, *height, left, right, top, bottom );
-
- // Now update the frame
- *image = output;
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
- }
-
- // We should resize the alpha too
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- if ( alpha != NULL )
- {
- uint8_t *newalpha = mlt_pool_alloc( owidth * oheight );
- if ( newalpha )
- {
- crop( alpha, newalpha, 1, *width, *height, left, right, top, bottom );
- mlt_properties_set_data( properties, "alpha", newalpha, owidth * oheight, ( mlt_destructor )mlt_pool_release, NULL );
- this->get_alpha_mask = NULL;
- }
- }
- *width = owidth;
- *height = oheight;
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "active" ) )
- {
- // Push the get_image method on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
- }
- else
- {
- mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
- mlt_properties frame_props = MLT_FRAME_PROPERTIES( frame );
- int left = mlt_properties_get_int( filter_props, "left" );
- int right = mlt_properties_get_int( filter_props, "right" );
- int top = mlt_properties_get_int( filter_props, "top" );
- int bottom = mlt_properties_get_int( filter_props, "bottom" );
- int width = mlt_properties_get_int( frame_props, "real_width" );
- int height = mlt_properties_get_int( frame_props, "real_height" );
-
- mlt_properties_set_int( frame_props, "crop.left", left );
- mlt_properties_set_int( frame_props, "crop.right", right );
- mlt_properties_set_int( frame_props, "crop.top", top );
- mlt_properties_set_int( frame_props, "crop.bottom", bottom );
- mlt_properties_set_int( frame_props, "real_width", width - left - right );
- mlt_properties_set_int( frame_props, "real_height", height - top - bottom );
- }
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
- if ( mlt_filter_init( this, this ) == 0 )
- {
- this->process = filter_process;
- if ( arg )
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "active", atoi( arg ) );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_data_feed.c -- data feed filter
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <framework/mlt.h>
-
-/** This filter should be used in conjuction with the data_show filter.
- The concept of the data_feed is that it can be used to pass titles
- or images to render on the frame, but doesn't actually do it
- itself. data_feed imposes few rules on what's passed on and the
- validity is confirmed in data_show before use.
-*/
-
-/** Data queue destructor.
-*/
-
-static void destroy_data_queue( void *arg )
-{
- if ( arg != NULL )
- {
- // Assign the correct type
- mlt_deque queue = arg;
-
- // Iterate through each item and destroy them
- while ( mlt_deque_peek_front( queue ) != NULL )
- mlt_properties_close( mlt_deque_pop_back( queue ) );
-
- // Close the deque
- mlt_deque_close( queue );
- }
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( this );
-
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the data queue
- mlt_deque data_queue = mlt_properties_get_data( frame_properties, "data_queue", NULL );
-
- // Get the type of the data feed
- char *type = mlt_properties_get( filter_properties, "type" );
-
- // Get the in and out points of this filter
- int in = mlt_filter_get_in( this );
- int out = mlt_filter_get_out( this );
-
- // Create the data queue if it doesn't exist
- if ( data_queue == NULL )
- {
- // Create the queue
- data_queue = mlt_deque_init( );
-
- // Assign it to the frame with the destructor
- mlt_properties_set_data( frame_properties, "data_queue", data_queue, 0, destroy_data_queue, NULL );
- }
-
- // Now create the data feed
- if ( data_queue != NULL && type != NULL && !strcmp( type, "attr_check" ) )
- {
- int i = 0;
- int count = mlt_properties_count( frame_properties );
-
- for ( i = 0; i < count; i ++ )
- {
- char *name = mlt_properties_get_name( frame_properties, i );
-
- // Only deal with meta.attr.name values here - these should have a value of 1 to be considered
- // Additional properties of the form are meta.attr.name.property are passed down on the feed
- if ( !strncmp( name, "meta.attr.", 10 ) && strchr( name + 10, '.' ) == NULL && mlt_properties_get_int( frame_properties, name ) == 1 )
- {
- // Temp var to hold name + '.' for pass method
- char temp[ 132 ];
-
- // Create a new data feed
- mlt_properties feed = mlt_properties_new( );
-
- // Assign it the base properties
- mlt_properties_set( feed, "id", mlt_properties_get( filter_properties, "_unique_id" ) );
- mlt_properties_set( feed, "type", strrchr( name, '.' ) + 1 );
- mlt_properties_set_position( feed, "position", mlt_frame_get_position( frame ) );
-
- // Assign in/out of service we're connected to
- mlt_properties_set_position( feed, "in", mlt_properties_get_position( frame_properties, "in" ) );
- mlt_properties_set_position( feed, "out", mlt_properties_get_position( frame_properties, "out" ) );
-
- // Pass all meta properties
- sprintf( temp, "%s.", name );
- mlt_properties_pass( feed, frame_properties, temp );
-
- // Push it on to the queue
- mlt_deque_push_back( data_queue, feed );
-
- // Make sure this attribute only gets processed once
- mlt_properties_set_int( frame_properties, name, 0 );
- }
- }
- }
- else if ( data_queue != NULL )
- {
- // Create a new data feed
- mlt_properties feed = mlt_properties_new( );
-
- // Assign it the base properties
- mlt_properties_set( feed, "id", mlt_properties_get( filter_properties, "_unique_id" ) );
- mlt_properties_set( feed, "type", type );
- mlt_properties_set_position( feed, "position", mlt_frame_get_position( frame ) );
-
- // Assign in/out of service we're connected to
- mlt_properties_set_position( feed, "in", mlt_properties_get_position( frame_properties, "in" ) );
- mlt_properties_set_position( feed, "out", mlt_properties_get_position( frame_properties, "out" ) );
-
- // Correct in/out to the filter if specified
- if ( in != 0 )
- mlt_properties_set_position( feed, "in", in );
- if ( out != 0 )
- mlt_properties_set_position( feed, "out", out );
-
- // Pass the properties which start with a "feed." prefix
- // Note that 'feed.text' in the filter properties becomes 'text' on the feed
- mlt_properties_pass( feed, filter_properties, "feed." );
-
- // Push it on to the queue
- mlt_deque_push_back( data_queue, feed );
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_data_feed_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the filter
- mlt_filter this = mlt_filter_new( );
-
- // Initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Assign the argument (default to titles)
- mlt_properties_set( properties, "type", arg == NULL ? "titles" : arg );
-
- // Specify the processing method
- this->process = filter_process;
- }
-
- return this;
-}
-
+++ /dev/null
-/*
- * filter_data_show.c -- data feed filter
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Handle the profile.
-*/
-
-static mlt_filter obtain_filter( mlt_filter filter, char *type )
-{
- // Result to return
- mlt_filter result = NULL;
-
- // Miscelaneous variable
- int i = 0;
- int type_len = strlen( type );
-
- // Get the properties of the data show filter
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the profile properties
- mlt_properties profile_properties = mlt_properties_get_data( filter_properties, "profile_properties", NULL );
-
- // Obtain the profile_properties if we haven't already
- if ( profile_properties == NULL )
- {
- char temp[ 512 ];
-
- // Get the profile requested
- char *profile = mlt_properties_get( filter_properties, "resource" );
-
- // If none is specified, pick up the default for this normalisation
- if ( profile == NULL )
- sprintf( temp, "%s/feeds/%s/data_fx.properties", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ) );
- else if ( strchr( profile, '%' ) )
- sprintf( temp, "%s/feeds/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( profile, '%' ) + 1 );
- else
- strcpy( temp, profile );
-
- // Load the specified profile or use the default
- profile_properties = mlt_properties_load( temp );
-
- // Store for later retrieval
- mlt_properties_set_data( filter_properties, "profile_properties", profile_properties, 0, ( mlt_destructor )mlt_properties_close, NULL );
- }
-
- if ( profile_properties != NULL )
- {
- for ( i = 0; i < mlt_properties_count( profile_properties ); i ++ )
- {
- char *name = mlt_properties_get_name( profile_properties, i );
- char *value = mlt_properties_get_value( profile_properties, i );
-
- if ( result == NULL && !strcmp( name, type ) && result == NULL )
- result = mlt_factory_filter( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ), value, NULL );
- else if ( result != NULL && !strncmp( name, type, type_len ) && name[ type_len ] == '.' )
- mlt_properties_set( MLT_FILTER_PROPERTIES( result ), name + type_len + 1, value );
- else if ( result != NULL )
- break;
- }
- }
-
- return result;
-}
-
-/** Retrieve medatata value
-*/
-
-char* metadata_value(mlt_properties properties, char* name)
-{
- if (name == NULL) return NULL;
- char *meta = malloc( strlen(name) + 18 );
- sprintf( meta, "meta.attr.%s.markup", name);
- char *result = mlt_properties_get( properties, meta);
- free(meta);
- return result;
-}
-
-/** Convert frames to Timecode
-*/
-
-char* frame_to_timecode( int frames , int fps)
-{
- if (fps == 0) return strdup("-");
- char *res = malloc(12);
- int seconds = frames / (int) fps;
- frames = frames % ((int) fps);
- int minutes = seconds / 60;
- seconds = seconds % 60;
- int hours = minutes / 60;
- minutes = minutes % 60;
- sprintf(res, "%.2d:%.2d:%.2d:%.2d", hours, minutes, seconds, frames);
- return res;
-}
-
-/** Process the frame for the requested type
-*/
-
-static int process_feed( mlt_properties feed, mlt_filter filter, mlt_frame frame )
-{
- // Error return
- int error = 1;
-
- // Get the properties of the data show filter
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the type requested by the feeding filter
- char *type = mlt_properties_get( feed, "type" );
-
- // Fetch the filter associated to this type
- mlt_filter requested = mlt_properties_get_data( filter_properties, type, NULL );
-
- // If it doesn't exist, then create it now
- if ( requested == NULL )
- {
- // Source filter from profile
- requested = obtain_filter( filter, type );
-
- // Store it on the properties for subsequent retrieval/destruction
- mlt_properties_set_data( filter_properties, type, requested, 0, ( mlt_destructor )mlt_filter_close, NULL );
- }
-
- // If we have one, then process it now...
- if ( requested != NULL )
- {
- int i = 0;
- mlt_properties properties = MLT_FILTER_PROPERTIES( requested );
- static const char *prefix = "properties.";
- int len = strlen( prefix );
-
- // Determine if this is an absolute or relative feed
- int absolute = mlt_properties_get_int( feed, "absolute" );
-
- // Make do with what we have
- int length = !absolute ?
- mlt_properties_get_int( feed, "out" ) - mlt_properties_get_int( feed, "in" ) + 1 :
- mlt_properties_get_int( feed, "out" ) + 1;
-
- // Repeat period
- int period = mlt_properties_get_int( properties, "period" );
- period = period == 0 ? 1 : period;
-
- // Pass properties from feed into requested
- for ( i = 0; i < mlt_properties_count( properties ); i ++ )
- {
- char *name = mlt_properties_get_name( properties, i );
- char *key = mlt_properties_get_value( properties, i );
- if ( !strncmp( name, prefix, len ) )
- {
- if ( !strncmp( name + len, "length[", 7 ) )
- {
- mlt_properties_set_position( properties, key, ( length - period ) / period );
- }
- else
- {
- char *value = mlt_properties_get( feed, name + len );
- if ( value != NULL )
- {
- // check for metadata keywords in metadata markup if user requested so
- if ( mlt_properties_get_int( filter_properties, "dynamic" ) == 1 && !strcmp( name + strlen( name ) - 6, "markup") )
- {
- // Find keywords which should be surrounded by '#', like: #title#
- char* keywords = strtok( value, "#" );
- char result[512] = ""; // XXX: how much is enough?
- int ct = 0;
- int fromStart = ( value[0] == '#' ) ? 1 : 0;
-
- while ( keywords != NULL )
- {
- if ( ct % 2 == fromStart )
- {
- // backslash in front of # suppresses substitution
- if ( keywords[ strlen( keywords ) -1 ] == '\\' )
- {
- // keep characters except backslash
- strncat( result, keywords, strlen( keywords ) -1 );
- strcat( result, "#" );
- ct++;
- }
- else
- {
- strcat( result, keywords );
- }
- }
- else if ( !strcmp( keywords, "timecode" ) )
- {
- // special case: replace #timecode# with current frame timecode
- int pos = mlt_properties_get_int( feed, "position" );
- char *tc = frame_to_timecode( pos, mlt_profile_fps( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) ) );
- strcat( result, tc );
- free( tc );
- }
- else
- {
- // replace keyword with metadata value
- char *metavalue = metadata_value( MLT_FRAME_PROPERTIES( frame ), keywords );
- strcat( result, metavalue ? metavalue : "-" );
- }
- keywords = strtok( NULL, "#" );
- ct++;
- }
- mlt_properties_set( properties, key, (char*) result );
- }
- else mlt_properties_set( properties, key, value );
- }
- }
- }
- }
-
- // Set the original position on the frame
- if ( absolute == 0 )
- mlt_frame_set_position( frame, mlt_properties_get_int( feed, "position" ) - mlt_properties_get_int( feed, "in" ) );
- else
- mlt_frame_set_position( frame, mlt_properties_get_int( feed, "position" ) );
-
- // Process the filter
- mlt_filter_process( requested, frame );
-
- // Should be ok...
- error = 0;
- }
-
- return error;
-}
-
-void process_queue( mlt_deque data_queue, mlt_frame frame, mlt_filter filter )
-{
- if ( data_queue != NULL )
- {
- // Create a new queue for those that we can't handle
- mlt_deque temp_queue = mlt_deque_init( );
-
- // Iterate through each entry on the queue
- while ( mlt_deque_peek_front( data_queue ) != NULL )
- {
- // Get the data feed
- mlt_properties feed = mlt_deque_pop_front( data_queue );
-
- if ( mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "debug" ) != NULL )
- mlt_properties_debug( feed, mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "debug" ), stderr );
-
- // Process the data feed...
- if ( process_feed( feed, filter, frame ) == 0 )
- mlt_properties_close( feed );
- else
- mlt_deque_push_back( temp_queue, feed );
- }
-
- // Now put the unprocessed feeds back on the stack
- while ( mlt_deque_peek_front( temp_queue ) )
- {
- // Get the data feed
- mlt_properties feed = mlt_deque_pop_front( temp_queue );
-
- // Put it back on the data queue
- mlt_deque_push_back( data_queue, feed );
- }
-
- // Close the temporary queue
- mlt_deque_close( temp_queue );
- }
-}
-
-/** Get the image.
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Pop the service
- mlt_filter filter = mlt_frame_pop_service( frame );
-
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Track specific
- process_queue( mlt_properties_get_data( frame_properties, "data_queue", NULL ), frame, filter );
-
- // Global
- process_queue( mlt_properties_get_data( frame_properties, "global_queue", NULL ), frame, filter );
-
- // Need to get the image
- return mlt_frame_get_image( frame, image, format, width, height, 1 );
-}
-
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the filter
- mlt_frame_push_service( frame, this );
-
- // Register the get image method
- mlt_frame_push_get_image( frame, filter_get_image );
-
- // Return the frame
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_data_show_init( mlt_profile profile, mlt_service_type type, const char *id, void *arg )
-{
- // Create the filter
- mlt_filter this = mlt_filter_new( );
-
- // Initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Assign the argument (default to titles)
- mlt_properties_set( properties, "resource", arg == NULL ? NULL : arg );
-
- // Specify the processing method
- this->process = filter_process;
- }
-
- return this;
-}
-
+++ /dev/null
-/*
- * filter_gamma.c -- gamma filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // Get the gamma value
- double gamma = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "gamma" );
-
- if ( gamma != 1.0 )
- {
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
-
- // Calculate the look up table
- double exp = 1 / gamma;
- uint8_t lookup[ 256 ];
- int i;
-
- for( i = 0; i < 256; i ++ )
- lookup[ i ] = ( uint8_t )( pow( ( double )i / 255.0, exp ) * 255 );
-
- while ( p != q )
- {
- *p = lookup[ *p ];
- p += 2;
- }
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- double gamma = mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "gamma" );
- gamma = gamma <= 0 ? 1 : gamma;
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "gamma", gamma );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_gamma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "gamma", arg == NULL ? "1" : arg );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_greyscale.c -- greyscale filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
- while ( p ++ != q )
- *p ++ = 128;
- }
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_greyscale_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- this->process = filter_process;
- return this;
-}
-
+++ /dev/null
-/*
- * filter_luma.c -- luma filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_transition.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = 0;
- mlt_filter filter = mlt_frame_pop_service( this );
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
- mlt_transition luma = mlt_properties_get_data( properties, "luma", NULL );
- mlt_frame b_frame = mlt_properties_get_data( properties, "frame", NULL );
- mlt_properties b_frame_props = b_frame ? MLT_FRAME_PROPERTIES( b_frame ) : NULL;
- int out = mlt_properties_get_int( properties, "period" );
-
- if ( out == 0 )
- out = 24;
-
- if ( b_frame == NULL || mlt_properties_get_int( b_frame_props, "width" ) != *width || mlt_properties_get_int( b_frame_props, "height" ) != *height )
- {
- b_frame = mlt_frame_init( MLT_FILTER_SERVICE( filter ) );
- mlt_properties_set_data( properties, "frame", b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
-
- if ( luma == NULL )
- {
- char *resource = mlt_properties_get( properties, "resource" );
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
- luma = mlt_factory_transition( profile, "luma", resource );
- if ( luma != NULL )
- {
- mlt_properties luma_properties = MLT_TRANSITION_PROPERTIES( luma );
- mlt_properties_set_int( luma_properties, "in", 0 );
- mlt_properties_set_int( luma_properties, "out", out );
- mlt_properties_set_int( luma_properties, "reverse", 1 );
- mlt_properties_set_data( properties, "luma", luma, 0, ( mlt_destructor )mlt_transition_close, NULL );
- }
-
- // Prime the filter with the first image to prevent a transition from the white
- // of a test card.
- error = mlt_frame_get_image( this, image, format, width, height, 1 );
- if ( error == 0 )
- {
- mlt_properties a_props = MLT_FRAME_PROPERTIES( this );
- int size = 0;
- uint8_t *src = mlt_properties_get_data( a_props, "image", &size );
- uint8_t *dst = mlt_pool_alloc( size );
-
- if ( dst != NULL )
- {
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
- memcpy( dst, src, size );
- mlt_properties_set_data( b_props, "image", dst, size, mlt_pool_release, NULL );
- mlt_properties_set_int( b_props, "width", *width );
- mlt_properties_set_int( b_props, "height", *height );
- mlt_properties_set_int( b_props, "format", *format );
- }
- }
- }
-
- if ( luma != NULL &&
- ( mlt_properties_get( properties, "blur" ) != NULL ||
- (int)mlt_frame_get_position( this ) % ( out + 1 ) != out ) )
- {
- mlt_properties luma_properties = MLT_TRANSITION_PROPERTIES( luma );
- mlt_properties_pass( luma_properties, properties, "luma." );
- mlt_transition_process( luma, this, b_frame );
- }
-
- error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 )
- {
- mlt_properties a_props = MLT_FRAME_PROPERTIES( this );
- int size = 0;
- uint8_t *src = mlt_properties_get_data( a_props, "image", &size );
- uint8_t *dst = mlt_pool_alloc( size );
-
- if ( dst != NULL )
- {
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
- memcpy( dst, src, size );
- mlt_properties_set_data( b_props, "image", dst, size, mlt_pool_release, NULL );
- mlt_properties_set_int( b_props, "width", *width );
- mlt_properties_set_int( b_props, "height", *height );
- mlt_properties_set_int( b_props, "format", *format );
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the filter on to the stack
- mlt_frame_push_service( frame, this );
-
- // Push the get_image on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set( properties, "resource", arg );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_mirror.c -- mirror filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Pop the mirror filter from the stack
- mlt_filter this = mlt_frame_pop_service( frame );
-
- // Get the mirror type
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Get the properties
- char *mirror = mlt_properties_get( properties, "mirror" );
-
- // Determine if reverse is required
- int reverse = mlt_properties_get_int( properties, "reverse" );
-
- // Get the image
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- // Get the alpha
- uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
-
- // If we have an image of the right colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // We'll KISS here
- int hh = *height / 2;
-
- if ( !strcmp( mirror, "horizontal" ) )
- {
- uint8_t *p = NULL;
- uint8_t *q = NULL;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- int i;
- int uneven_w = ( *width % 2 ) * 2;
- for ( i = 0; i < *height; i ++ )
- {
- p = ( uint8_t * )*image + i * *width * 2;
- q = p + *width * 2;
- a = alpha + i * *width;
- b = a + *width - 1;
- if ( !reverse )
- {
- while ( p < q )
- {
- *p ++ = *( q - 2 );
- *p ++ = *( q - 3 - uneven_w );
- *p ++ = *( q - 4 );
- *p ++ = *( q - 1 - uneven_w );
- q -= 4;
- *a ++ = *b --;
- *a ++ = *b --;
- }
- }
- else
- {
- while ( p < q )
- {
- *( q - 2 ) = *p ++;
- *( q - 3 - uneven_w ) = *p ++;
- *( q - 4 ) = *p ++;
- *( q - 1 - uneven_w ) = *p ++;
- q -= 4;
- *b -- = *a ++;
- *b -- = *a ++;
- }
- }
- }
- }
- else if ( !strcmp( mirror, "vertical" ) )
- {
- uint16_t *end = ( uint16_t *)*image + *width * *height;
- uint16_t *p = NULL;
- uint16_t *q = NULL;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- int i;
- int j;
- for ( i = 0; i < hh; i ++ )
- {
- p = ( uint16_t * )*image + i * *width;
- q = end - ( i + 1 ) * *width;
- j = *width;
- a = alpha + i * *width;
- b = alpha + ( *height - i - 1 ) * *width;
- if ( !reverse )
- {
- while ( j -- )
- {
- *p ++ = *q ++;
- *a ++ = *b ++;
- }
- }
- else
- {
- while ( j -- )
- {
- *q ++ = *p ++;
- *b ++ = *a ++;
- }
- }
- }
- }
- else if ( !strcmp( mirror, "diagonal" ) )
- {
- uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
- uint8_t *p = NULL;
- uint8_t *q = NULL;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- int i;
- int j;
- int uneven_w = ( *width % 2 ) * 2;
- for ( i = 0; i < *height; i ++ )
- {
- p = ( uint8_t * )*image + i * *width * 2;
- q = end - i * *width * 2;
- j = ( ( *width * ( *height - i ) ) / *height ) / 2;
- a = alpha + i * *width;
- b = alpha + ( *height - i - 1 ) * *width;
- if ( !reverse )
- {
- while ( j -- )
- {
- *p ++ = *( q - 2 );
- *p ++ = *( q - 3 - uneven_w );
- *p ++ = *( q - 4 );
- *p ++ = *( q - 1 - uneven_w );
- q -= 4;
- *a ++ = *b --;
- *a ++ = *b --;
- }
- }
- else
- {
- while ( j -- )
- {
- *( q - 2 ) = *p ++;
- *( q - 3 - uneven_w ) = *p ++;
- *( q - 4 ) = *p ++;
- *( q - 1 - uneven_w ) = *p ++;
- q -= 4;
- *b -- = *a ++;
- *b -- = *a ++;
- }
- }
- }
- }
- else if ( !strcmp( mirror, "xdiagonal" ) )
- {
- uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
- uint8_t *p = NULL;
- uint8_t *q = NULL;
- int i;
- int j;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- int uneven_w = ( *width % 2 ) * 2;
- for ( i = 0; i < *height; i ++ )
- {
- p = ( uint8_t * )*image + ( i + 1 ) * *width * 2;
- q = end - ( i + 1 ) * *width * 2;
- j = ( ( *width * ( *height - i ) ) / *height ) / 2;
- a = alpha + ( i + 1 ) * *width - 1;
- b = alpha + ( *height - i - 1 ) * *width;
- if ( !reverse )
- {
- while ( j -- )
- {
- *q ++ = *( p - 2 );
- *q ++ = *( p - 3 - uneven_w );
- *q ++ = *( p - 4 );
- *q ++ = *( p - 1 - uneven_w );
- p -= 4;
- *b ++ = *a --;
- *b ++ = *a --;
- }
- }
- else
- {
- while ( j -- )
- {
- *( p - 2 ) = *q ++;
- *( p - 3 - uneven_w ) = *q ++;
- *( p - 4 ) = *q ++;
- *( p - 1 - uneven_w ) = *q ++;
- p -= 4;
- *a -- = *b ++;
- *a -- = *b ++;
- }
- }
- }
- }
- else if ( !strcmp( mirror, "flip" ) )
- {
- uint8_t t[ 4 ];
- uint8_t *p = NULL;
- uint8_t *q = NULL;
- int i;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- uint8_t c;
- int uneven_w = ( *width % 2 ) * 2;
- for ( i = 0; i < *height; i ++ )
- {
- p = ( uint8_t * )*image + i * *width * 2;
- q = p + *width * 2;
- a = alpha + i * *width;
- b = a + *width - 1;
- while ( p < q )
- {
- t[ 0 ] = p[ 0 ];
- t[ 1 ] = p[ 1 + uneven_w ];
- t[ 2 ] = p[ 2 ];
- t[ 3 ] = p[ 3 + uneven_w ];
- *p ++ = *( q - 2 );
- *p ++ = *( q - 3 - uneven_w );
- *p ++ = *( q - 4 );
- *p ++ = *( q - 1 - uneven_w );
- *( -- q ) = t[ 3 ];
- *( -- q ) = t[ 0 ];
- *( -- q ) = t[ 1 ];
- *( -- q ) = t[ 2 ];
- c = *a;
- *a ++ = *b;
- *b -- = c;
- c = *a;
- *a ++ = *b;
- *b -- = c;
- }
- }
- }
- else if ( !strcmp( mirror, "flop" ) )
- {
- uint16_t *end = ( uint16_t *)*image + *width * *height;
- uint16_t *p = NULL;
- uint16_t *q = NULL;
- uint16_t t;
- uint8_t *a = NULL;
- uint8_t *b = NULL;
- uint8_t c;
- int i;
- int j;
- for ( i = 0; i < hh; i ++ )
- {
- p = ( uint16_t * )*image + i * *width;
- q = end - ( i + 1 ) * *width;
- a = alpha + i * *width;
- b = alpha + ( *height - i - 1 ) * *width;
- j = *width;
- while ( j -- )
- {
- t = *p;
- *p ++ = *q;
- *q ++ = t;
- c = *a;
- *a ++ = *b;
- *b ++ = c;
- }
- }
- }
- }
-
- // Return the error
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the service on to the stack
- mlt_frame_push_service( frame, this );
-
- // Push the filter method on to the stack
- mlt_frame_push_service( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Construct a new filter
- mlt_filter this = mlt_filter_new( );
-
- // If we have a filter, initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Set the default mirror type
- mlt_properties_set_or_default( properties, "mirror", arg, "horizontal" );
-
- // Assign the process method
- this->process = filter_process;
- }
-
- // Return the filter
- return this;
-}
-
+++ /dev/null
-/*
- * filter_mono.c -- mix all channels to a mono signal across n channels
- * Copyright (C) 2003-2006 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/** Get the audio.
-*/
-
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the a frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- int channels_out = mlt_properties_get_int( properties, "mono.channels" );
- int i, j, size;
- int16_t *new_buffer;
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
-
- size = *samples * channels_out * sizeof( int16_t );
- new_buffer = mlt_pool_alloc( size );
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Mix
- for ( i = 0; i < *samples; i++ )
- {
- int16_t mixdown = 0;
- for ( j = 0; j < *channels; j++ )
- mixdown += (*buffer)[ ( i * *channels ) + j ] / *channels;
- for ( j = 0; j < channels_out; j++ )
- new_buffer[ ( i * channels_out ) + j ] = mixdown;
- }
-
- // Apply results
- *buffer = new_buffer;
- *channels = channels_out;
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- mlt_properties frame_props = MLT_FRAME_PROPERTIES( frame );
-
- // Propogate the parameters
- mlt_properties_set_int( frame_props, "mono.channels", mlt_properties_get_int( properties, "channels" ) );
-
- // Override the get_audio method
- mlt_frame_push_audio( frame, filter_get_audio );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", atoi( arg ) );
- else
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_obscure.c -- obscure filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/** Geometry struct.
-*/
-
-struct geometry_s
-{
- int nw;
- int nh;
- float x;
- float y;
- float w;
- float h;
- int mask_w;
- int mask_h;
-};
-
-/** Parse a value from a geometry string.
-*/
-
-static inline float parse_value( char **ptr, int normalisation, char delim, float defaults )
-{
- float value = defaults;
-
- if ( *ptr != NULL && **ptr != '\0' )
- {
- char *end = NULL;
- value = strtod( *ptr, &end );
- if ( end != NULL )
- {
- if ( *end == '%' )
- value = ( value / 100.0 ) * normalisation;
- while ( *end == delim || *end == '%' )
- end ++;
- }
- *ptr = end;
- }
-
- return value;
-}
-
-/** Parse a geometry property string.
-*/
-
-static void geometry_parse( struct geometry_s *geometry, struct geometry_s *defaults, char *property, int nw, int nh )
-{
- // Assign normalised width and height
- geometry->nw = nw;
- geometry->nh = nh;
-
- // Assign from defaults if available
- if ( defaults != NULL )
- {
- geometry->x = defaults->x;
- geometry->y = defaults->y;
- geometry->w = defaults->w;
- geometry->h = defaults->h;
- geometry->mask_w = defaults->mask_w;
- geometry->mask_h = defaults->mask_h;
- }
- else
- {
- geometry->x = 0;
- geometry->y = 0;
- geometry->w = nw;
- geometry->h = nh;
- geometry->mask_w = 20;
- geometry->mask_h = 20;
- }
-
- // Parse the geomtry string
- if ( property != NULL )
- {
- char *ptr = property;
- geometry->x = parse_value( &ptr, nw, ',', geometry->x );
- geometry->y = parse_value( &ptr, nh, ':', geometry->y );
- geometry->w = parse_value( &ptr, nw, 'x', geometry->w );
- geometry->h = parse_value( &ptr, nh, ':', geometry->h );
- geometry->mask_w = parse_value( &ptr, nw, 'x', geometry->mask_w );
- geometry->mask_h = parse_value( &ptr, nh, ' ', geometry->mask_h );
- }
-}
-
-/** A Timism but not as clean ;-).
-*/
-
-static float lerp( float value, float lower, float upper )
-{
- if ( value < lower )
- return lower;
- else if ( value > upper )
- return upper;
- return value;
-}
-
-/** Calculate real geometry.
-*/
-
-static void geometry_calculate( struct geometry_s *output, struct geometry_s *in, struct geometry_s *out, float position, int ow, int oh )
-{
- // Calculate this frames geometry
- output->x = lerp( ( in->x + ( out->x - in->x ) * position ) / ( float )out->nw * ow, 0, ow );
- output->y = lerp( ( in->y + ( out->y - in->y ) * position ) / ( float )out->nh * oh, 0, oh );
- output->w = lerp( ( in->w + ( out->w - in->w ) * position ) / ( float )out->nw * ow, 0, ow - output->x );
- output->h = lerp( ( in->h + ( out->h - in->h ) * position ) / ( float )out->nh * oh, 0, oh - output->y );
- output->mask_w = in->mask_w + ( out->mask_w - in->mask_w ) * position;
- output->mask_h = in->mask_h + ( out->mask_h - in->mask_h ) * position;
-}
-
-/** Calculate the position for this frame.
-*/
-
-static float position_calculate( mlt_filter this, mlt_frame frame )
-{
- // Get the in and out position
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
-
- // Get the position of the frame
- mlt_position position = mlt_frame_get_position( frame );
-
- // Now do the calcs
- return ( float )( position - in ) / ( float )( out - in + 1 );
-}
-
-/** The averaging function...
-*/
-
-static inline void obscure_average( uint8_t *start, int width, int height, int stride )
-{
- register int y;
- register int x;
- register int Y = ( *start + *( start + 2 ) ) / 2;
- register int U = *( start + 1 );
- register int V = *( start + 3 );
- register uint8_t *p;
- register int components = width >> 1;
-
- y = height;
- while( y -- )
- {
- p = start;
- x = components;
- while( x -- )
- {
- Y = ( Y + *p ++ ) >> 1;
- U = ( U + *p ++ ) >> 1;
- Y = ( Y + *p ++ ) >> 1;
- V = ( V + *p ++ ) >> 1;
- }
- start += stride;
- }
-
- start -= height * stride;
- y = height;
- while( y -- )
- {
- p = start;
- x = components;
- while( x -- )
- {
- *p ++ = Y;
- *p ++ = U;
- *p ++ = Y;
- *p ++ = V;
- }
- start += stride;
- }
-}
-
-
-/** The obscurer rendering function...
-*/
-
-static void obscure_render( uint8_t *image, int width, int height, struct geometry_s result )
-{
- int area_x = result.x;
- int area_y = result.y;
- int area_w = result.w;
- int area_h = result.h;
-
- int mw = result.mask_w;
- int mh = result.mask_h;
- int w;
- int h;
- int aw;
- int ah;
-
- uint8_t *p = image + area_y * width * 2 + area_x * 2;
-
- for ( w = 0; w < area_w; w += mw )
- {
- for ( h = 0; h < area_h; h += mh )
- {
- aw = w + mw > area_w ? mw - ( w + mw - area_w ) : mw;
- ah = h + mh > area_h ? mh - ( h + mh - area_h ) : mh;
- if ( aw > 1 && ah > 1 )
- obscure_average( p + h * ( width << 1 ) + ( w << 1 ), aw, ah, width << 1 );
- }
- }
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Pop the top of stack now
- mlt_filter this = mlt_frame_pop_service( frame );
-
- // Get the image from the frame
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- // Get the image from the frame
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- if ( this != NULL )
- {
- // Get the filter properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Obtain the normalised width and height from the frame
- int normalised_width = mlt_properties_get_int( frame_properties, "normalised_width" );
- int normalised_height = mlt_properties_get_int( frame_properties, "normalised_height" );
-
- // Structures for geometry
- struct geometry_s result;
- struct geometry_s start;
- struct geometry_s end;
-
- // Retrieve the position
- float position = mlt_properties_get_double(frame_properties, "filter_position");
-
- // Now parse the geometries
- geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ), normalised_width, normalised_height );
- geometry_parse( &end, &start, mlt_properties_get( properties, "end" ), normalised_width, normalised_height );
-
- // Do the calculation
- geometry_calculate( &result, &start, &end, position, *width, *height );
-
- // Now actually render it
- obscure_render( *image, *width, *height, result );
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push this on to the service stack
- mlt_frame_push_service( frame, this );
-
- // Calculate the position for the filter effect
- float position = position_calculate( this, frame );
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "filter_position", position );
-
- // Push the get image call
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_obscure_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- this->process = filter_process;
- mlt_properties_set( properties, "start", arg != NULL ? arg : "0%,0%:100%x100%" );
- mlt_properties_set( properties, "end", "" );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_region.c -- region filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "transition_region.h"
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the properties of the filter
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Get the region transition
- mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL );
-
- // Create the transition if not available
- if ( transition == NULL )
- {
- // Create the transition
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- transition = mlt_factory_transition( profile, "region", NULL );
-
- // Register with the filter
- mlt_properties_set_data( properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL );
-
- // Pass a reference to this filter down
- mlt_properties_set_data( MLT_TRANSITION_PROPERTIES( transition ), "_region_filter", this, 0, NULL, NULL );
- }
-
- // Pass all properties down
- mlt_properties_pass( MLT_TRANSITION_PROPERTIES( transition ), properties, "" );
-
- // Process the frame
- return mlt_transition_process( transition, frame, NULL );
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create a new filter
- mlt_filter this = mlt_filter_new( );
-
- // Further initialisation
- if ( this != NULL )
- {
- // Get the properties from the filter
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Assign the filter process method
- this->process = filter_process;
-
- // Resource defines the shape of the region
- mlt_properties_set( properties, "resource", arg == NULL ? "rectangle" : arg );
-
- // Ensure that attached filters are handled privately
- mlt_properties_set_int( properties, "_filter_private", 1 );
- }
-
- // Return the filter
- return this;
-}
-
+++ /dev/null
-/*
- * filter_rescale.c -- scale the producer video frame size to match the consumer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-typedef int ( *image_scaler )( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight );
-
-static void scale_alpha( mlt_frame this, int iwidth, int iheight, int owidth, int oheight );
-
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight )
-{
- // Get the properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the rescaling interpolsation
- char *interps = mlt_properties_get( properties, "rescale.interp" );
-
- // Carry out the rescaling
- if ( iformat == mlt_image_yuv422 && oformat == mlt_image_yuv422 )
- {
- // Scale the frame
- mlt_frame_rescale_yuv422( this, owidth, oheight );
-
- // Return the output
- *image = mlt_properties_get_data( properties, "image", NULL );
-
- // Scale the alpha channel only if exists and not correct size
- int alpha_size = 0;
- mlt_properties_get_data( properties, "alpha", &alpha_size );
- if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) )
- scale_alpha( this, iwidth, iheight, owidth, oheight );
- }
- else if ( iformat == mlt_image_rgb24 || iformat == mlt_image_rgb24a )
- {
- int bpp = (iformat == mlt_image_rgb24a ? 4 : 3 );
-
- // Create the yuv image
- uint8_t *output = mlt_pool_alloc( iwidth * ( iheight + 1 ) * 2 );
-
- if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
- {
- // Extract YUV422 and alpha
- if ( bpp == 4 )
- {
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( iwidth * ( iheight + 1 ) );
-
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( *image, iwidth, iheight, iwidth * 4, output, alpha );
-
- mlt_properties_set_data( properties, "alpha", alpha, iwidth * ( iheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
-
- scale_alpha( this, iwidth, iheight, owidth, oheight );
- }
- else
- {
- // No alpha to extract
- mlt_convert_rgb24_to_yuv422( *image, iwidth, iheight, iwidth * 3, output );
- }
-
- mlt_properties_set_data( properties, "image", output, iwidth * ( iheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Scale the frame
- output = mlt_frame_rescale_yuv422( this, owidth, oheight );
-
- }
- else
- {
- // Extract YUV422 and alpha
- if ( bpp == 4 )
- {
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) );
-
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( *image, owidth, oheight, owidth * 4, output, alpha );
-
- mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
-
- scale_alpha( this, iwidth, iheight, owidth, oheight );
- }
- else
- {
- // No alpha to extract
- mlt_convert_rgb24_to_yuv422( *image, owidth, oheight, owidth * 3, output );
- }
- }
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- *image = output;
- }
-
- return 0;
-}
-
-static void scale_alpha( mlt_frame this, int iwidth, int iheight, int owidth, int oheight )
-{
- // Scale the alpha
- uint8_t *output = NULL;
- uint8_t *input = mlt_frame_get_alpha_mask( this );
-
- if ( input != NULL )
- {
- uint8_t *out_line;
- int x, y;
- int ox = ( iwidth << 10 ) / owidth;
- int oy = ( iheight << 10 ) / oheight;
-
- output = mlt_pool_alloc( owidth * oheight );
- out_line = output;
-
- // Loop for the entirety of our output height.
- for ( y = 0; y < oheight; y ++ )
- for ( x = 0; x < owidth; x ++ )
- *out_line ++ = *( input + ( ( 512 + ( y * oy * iwidth ) + x * ox ) >> 10 ) );
-
- // Set it back on the frame
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", output, owidth * oheight, mlt_pool_release, NULL );
- }
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the frame properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the filter from the stack
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the image scaler method
- image_scaler scaler_method = mlt_properties_get_data( filter_properties, "method", NULL );
-
- // Correct Width/height if necessary
- if ( *width == 0 || *height == 0 )
- {
- *width = mlt_properties_get_int( properties, "normalised_width" );
- *height = mlt_properties_get_int( properties, "normalised_height" );
- }
-
- // There can be problems with small images - avoid them (by hacking - gah)
- if ( *width >= 6 && *height >= 6 )
- {
- int iwidth = *width;
- int iheight = *height;
- int owidth = *width;
- int oheight = *height;
- char *interps = mlt_properties_get( properties, "rescale.interp" );
- int wanted_format = *format;
-
- // Default from the scaler if not specifed on the frame
- if ( interps == NULL )
- {
- interps = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "interpolation" );
- mlt_properties_set( properties, "rescale.interp", interps );
- }
-
- // If real_width/height exist, we want that as minimum information
- if ( mlt_properties_get_int( properties, "real_width" ) )
- {
- iwidth = mlt_properties_get_int( properties, "real_width" );
- iheight = mlt_properties_get_int( properties, "real_height" );
- }
-
- // Let the producer know what we are actually requested to obtain
- if ( *format == mlt_image_yuv422 && strcmp( interps, "none" ) )
- {
- mlt_properties_set_int( properties, "rescale_width", *width );
- mlt_properties_set_int( properties, "rescale_height", *height );
- }
- else
- {
- // When no scaling is requested, revert the requested dimensions if possible
- mlt_properties_set_int( properties, "rescale_width", iwidth );
- mlt_properties_set_int( properties, "rescale_height", iheight );
- }
-
- // Deinterlace if height is changing to prevent fields mixing on interpolation
- // One exception: non-interpolated, integral scaling
- if ( iheight != oheight && ( strcmp( interps, "nearest" ) || ( iheight % oheight != 0 ) ) )
- mlt_properties_set_int( properties, "consumer_deinterlace", 1 );
-
- // Get the image as requested
- mlt_frame_get_image( this, image, format, &iwidth, &iheight, writable );
-
- // Get rescale interpretation again, in case the producer wishes to override scaling
- interps = mlt_properties_get( properties, "rescale.interp" );
-
- if ( *image != NULL && ( *format != mlt_image_yuv422 || ( iwidth != owidth || iheight != oheight ) ) )
- {
- // If the colour space is correct and scaling is off, do nothing
- if ( *format == mlt_image_yuv422 && !strcmp( interps, "none" ) )
- {
- *width = iwidth;
- *height = iheight;
- }
- else if ( *format == mlt_image_yuv422 )
- {
- // Call the local scaler
- scaler_method( this, image, *format, mlt_image_yuv422, iwidth, iheight, owidth, oheight );
- *width = owidth;
- *height = oheight;
- }
- else if ( *format == mlt_image_rgb24 && wanted_format == mlt_image_rgb24 )
- {
- // Call the local scaler
- scaler_method( this, image, *format, mlt_image_rgb24, iwidth, iheight, owidth, oheight );
-
- // Return the output
- *width = owidth;
- *height = oheight;
- }
- else if ( *format == mlt_image_rgb24 || *format == mlt_image_rgb24a )
- {
- // Call the local scaler
- scaler_method( this, image, *format, mlt_image_yuv422, iwidth, iheight, owidth, oheight );
-
- // Return the output
- *format = mlt_image_yuv422;
- *width = owidth;
- *height = oheight;
- }
- else
- {
- *width = iwidth;
- *height = iheight;
- }
- }
- else
- {
- *width = iwidth;
- *height = iheight;
- }
- }
- else
- {
- // Store the requested width/height
- int iwidth = *width;
- int iheight = *height;
-
- // Get the image as requested
- mlt_frame_get_image( this, image, format, &iwidth, &iheight, writable );
-
- // Too small - for now just assign as though we got what we wanted
- *width = iwidth;
- *height = iheight;
- }
-
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the filter
- mlt_frame_push_service( frame, this );
-
- // Push the get image method
- mlt_frame_push_service( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_rescale_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create a new scaler
- mlt_filter this = mlt_filter_new( );
-
- // If successful, then initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Set the process method
- this->process = filter_process;
-
- // Set the inerpolation
- mlt_properties_set( properties, "interpolation", arg == NULL ? "bilinear" : arg );
-
- // Set the method
- mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
- }
-
- return this;
-}
-
+++ /dev/null
-/*
- * filter_resize.c -- resizing filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/** Swapbytes inline.
-*/
-
-static inline void swap_bytes( uint8_t *upper, uint8_t *lower )
-{
- uint8_t t = *lower;
- *lower = *upper;
- *upper = t;
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = 0;
-
- // Get the properties from the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Pop the top of stack now
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Retrieve the aspect ratio
- double aspect_ratio = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( this ) );
-
- // Correct Width/height if necessary
- if ( *width == 0 || *height == 0 )
- {
- *width = mlt_properties_get_int( properties, "normalised_width" );
- *height = mlt_properties_get_int( properties, "normalised_height" );
- }
-
- // Assign requested width/height from our subordinate
- int owidth = *width;
- int oheight = *height;
-
- // Check for the special case - no aspect ratio means no problem :-)
- if ( aspect_ratio == 0.0 )
- aspect_ratio = mlt_properties_get_double( properties, "consumer_aspect_ratio" );
-
- // Reset the aspect ratio
- mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
-
- // Hmmm...
- char *rescale = mlt_properties_get( properties, "rescale.interp" );
- if ( rescale != NULL && !strcmp( rescale, "none" ) )
- return mlt_frame_get_image( this, image, format, width, height, writable );
-
- if ( mlt_properties_get_int( properties, "distort" ) == 0 )
- {
- // Normalise the input and out display aspect
- int normalised_width = mlt_properties_get_int( properties, "normalised_width" );
- int normalised_height = mlt_properties_get_int( properties, "normalised_height" );
- int real_width = mlt_properties_get_int( properties, "real_width" );
- int real_height = mlt_properties_get_int( properties, "real_height" );
- if ( real_width == 0 )
- real_width = mlt_properties_get_int( properties, "width" );
- if ( real_height == 0 )
- real_height = mlt_properties_get_int( properties, "height" );
- double input_ar = aspect_ratio * real_width / real_height;
- double output_ar = mlt_properties_get_double( properties, "consumer_aspect_ratio" ) * owidth / oheight;
-
-// fprintf( stderr, "real %dx%d normalised %dx%d output %dx%d sar %f in-dar %f out-dar %f\n",
-// real_width, real_height, normalised_width, normalised_height, owidth, oheight, aspect_ratio, input_ar, output_ar);
-
- // Optimised for the input_ar > output_ar case (e.g. widescreen on standard)
- int scaled_width = rint( ( input_ar * normalised_width ) / output_ar );
- int scaled_height = normalised_height;
-
- // Now ensure that our images fit in the output frame
- if ( scaled_width > normalised_width )
- {
- scaled_width = normalised_width;
- scaled_height = rint( ( output_ar * normalised_height ) / input_ar );
- }
-
- // Now calculate the actual image size that we want
- owidth = rint( scaled_width * owidth / normalised_width );
- oheight = rint( scaled_height * oheight / normalised_height );
-
- // Tell frame we have conformed the aspect to the consumer
- mlt_frame_set_aspect_ratio( this, mlt_properties_get_double( properties, "consumer_aspect_ratio" ) );
- }
-
- mlt_properties_set_int( properties, "distort", 0 );
-
- // Now pass on the calculations down the line
- mlt_properties_set_int( properties, "resize_width", *width );
- mlt_properties_set_int( properties, "resize_height", *height );
-
- // Now get the image
- error = mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
-
- // We only know how to process yuv422 at the moment
- if ( error == 0 && *format == mlt_image_yuv422 && *image != NULL )
- {
- // Get the requested scale operation
- char *op = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "scale" );
-
- // Provides a manual override for misreported field order
- if ( mlt_properties_get( properties, "meta.top_field_first" ) )
- mlt_properties_set_int( properties, "top_field_first", mlt_properties_get_int( properties, "meta.top_field_first" ) );
-
- // Correct field order if needed
- if ( mlt_properties_get_int( properties, "top_field_first" ) == 1 )
- {
- // Get the input image, width and height
- int size;
- uint8_t *image = mlt_properties_get_data( properties, "image", &size );
- uint8_t *ptr = image + owidth * 2;
- memmove( ptr, image, size - owidth * 2 );
-
- // Set the normalised field order
- mlt_properties_set_int( properties, "top_field_first", 0 );
- mlt_properties_set_int( properties, "meta.top_field_first", 0 );
- }
-
- if ( !strcmp( op, "affine" ) )
- {
- *image = mlt_frame_rescale_yuv422( this, *width, *height );
- }
- else if ( strcmp( op, "none" ) != 0 )
- {
- *image = mlt_frame_resize_yuv422( this, *width, *height );
- }
- else
- {
- *width = owidth;
- *height = oheight;
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Store the aspect ratio reported by the source
- mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( frame ), mlt_frame_get_aspect_ratio( frame ) );
-
- // Push this on to the service stack
- mlt_frame_push_service( frame, this );
-
- // Push the get_image method on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_resize_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
- if ( mlt_filter_init( this, this ) == 0 )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "scale", arg == NULL ? "off" : arg );
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_transition.c -- Convert any transition into a filter
- * Copyright (C) 2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_transition.h>
-
-/** Get the image via the transition.
- NB: Not all transitions will accept a and b frames being the same...
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_transition transition = mlt_frame_pop_service( this );
- if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "image_count" ) >= 1 )
- mlt_transition_process( transition, this, this );
- return mlt_frame_get_image( this, image, format, width, height, writable );
-}
-
-/** Get the audio via the transition.
- NB: Not all transitions will accept a and b frames being the same...
-*/
-
-static int filter_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Obtain the transition instance
- mlt_transition transition = mlt_frame_pop_audio( this );
- mlt_transition_process( transition, this, this );
- return mlt_frame_get_audio( this, buffer, format, frequency, channels, samples );
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Obtain the transition instance
- mlt_transition transition = mlt_properties_get_data( MLT_FILTER_PROPERTIES( this ), "instance", NULL );
-
- // If we haven't created the instance, do it now
- if ( transition == NULL )
- {
- char *name = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "transition" );
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- transition = mlt_factory_transition( profile, name, NULL );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "instance", transition, 0, ( mlt_destructor )mlt_transition_close, NULL );
- }
-
- // We may still not have a transition...
- if ( transition != NULL )
- {
- // Get the transition type
- int type = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type" );
-
- // Set the basic info
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "in", mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "in" ) );
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "out", mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "out" ) );
-
- // Refresh with current user values
- mlt_properties_pass( MLT_TRANSITION_PROPERTIES( transition ), MLT_FILTER_PROPERTIES( this ), "transition." );
-
- if ( type & 1 && !mlt_frame_is_test_card( frame ) && !( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "hide" ) & 1 ) )
- {
- mlt_frame_push_service( frame, transition );
- mlt_frame_push_get_image( frame, filter_get_image );
- }
- if ( type & 2 && !mlt_frame_is_test_audio( frame ) && !( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "hide" ) & 2 ) )
- {
- mlt_frame_push_audio( frame, transition );
- mlt_frame_push_audio( frame, filter_get_audio );
- }
-
- if ( type == 0 )
- mlt_properties_debug( MLT_TRANSITION_PROPERTIES( transition ), "unknown transition type", stderr );
- }
- else
- {
- mlt_properties_debug( MLT_FILTER_PROPERTIES( this ), "no transition", stderr );
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_transition_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "transition", arg );
- this->process = filter_process;
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_watermark.c -- watermark filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_transition.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Error we will return
- int error = 0;
-
- // Get the watermark filter object
- mlt_filter this = mlt_frame_pop_service( frame );
-
- // Get the properties of the filter
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Get the producer from the filter
- mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // Get the composite from the filter
- mlt_transition composite = mlt_properties_get_data( properties, "composite", NULL );
-
- // Get the resource to use
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Get the old resource
- char *old_resource = mlt_properties_get( properties, "_old_resource" );
-
- // Create a composite if we don't have one
- if ( composite == NULL )
- {
- // Create composite via the factory
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- composite = mlt_factory_transition( profile, "composite", NULL );
-
- // Register the composite for reuse/destruction
- if ( composite != NULL )
- mlt_properties_set_data( properties, "composite", composite, 0, ( mlt_destructor )mlt_transition_close, NULL );
- }
-
- // If we have one
- if ( composite != NULL )
- {
- // Get the properties
- mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite );
-
- // Pass all the composite. properties on the filter down
- mlt_properties_pass( composite_properties, properties, "composite." );
-
- if ( mlt_properties_get( properties, "composite.out" ) == NULL )
- mlt_properties_set_int( composite_properties, "out", mlt_properties_get_int( properties, "_out" ) );
-
- // Force a refresh
- mlt_properties_set_int( composite_properties, "refresh", 1 );
- }
-
- // Create a producer if don't have one
- if ( producer == NULL || ( old_resource != NULL && strcmp( resource, old_resource ) ) )
- {
- // Get the factory producer service
- char *factory = mlt_properties_get( properties, "factory" );
-
- // Create the producer
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- producer = mlt_factory_producer( profile, factory, resource );
-
- // If we have one
- if ( producer != NULL )
- {
- // Register the producer for reuse/destruction
- mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
-
- // Ensure that we loop
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "loop" );
-
- // Set the old resource
- mlt_properties_set( properties, "_old_resource", resource );
- }
- }
-
- if ( producer != NULL )
- {
- // Get the producer properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Now pass all producer. properties on the filter down
- mlt_properties_pass( producer_properties, properties, "producer." );
- }
-
- // Only continue if we have both producer and composite
- if ( composite != NULL && producer != NULL )
- {
- // Get the service of the producer
- mlt_service service = MLT_PRODUCER_SERVICE( producer );
-
- // We will get the 'b frame' from the producer
- mlt_frame b_frame = NULL;
-
- // Get the unique id of the filter (used to reacquire the producer position)
- char *name = mlt_properties_get( properties, "_unique_id" );
-
- // Get the original producer position
- mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name );
-
- // Make sure the producer is in the correct position
- mlt_producer_seek( producer, position );
-
- // Resetting position to appease the composite transition
- mlt_frame_set_position( frame, position );
-
- // Get the b frame and process with composite if successful
- if ( mlt_service_get_frame( service, &b_frame, 0 ) == 0 )
- {
- // Get the a and b frame properties
- mlt_properties a_props = MLT_FRAME_PROPERTIES( frame );
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // Set the b frame to be in the same position and have same consumer requirements
- mlt_frame_set_position( b_frame, position );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- mlt_properties_set_int( b_props, "consumer_deinterlace", mlt_properties_get_int( a_props, "consumer_deinterlace" ) || mlt_properties_get_int( properties, "deinterlace" ) );
- mlt_properties_set_double( b_props, "output_ratio", mlt_properties_get_double( a_props, "output_ratio" ) );
-
- // Check for the special case - no aspect ratio means no problem :-)
- if ( mlt_frame_get_aspect_ratio( b_frame ) == 0 )
- mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- if ( mlt_frame_get_aspect_ratio( frame ) == 0 )
- mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
-
- mlt_properties_set_int( b_props, "normalised_width", mlt_properties_get_int( a_props, "normalised_width" ) );
- mlt_properties_set_int( b_props, "normalised_height", mlt_properties_get_int( a_props, "normalised_height" ) );
-
- if ( mlt_properties_get_int( properties, "distort" ) )
- {
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( composite ), "distort", 1 );
- mlt_properties_set_int( a_props, "distort", 1 );
- mlt_properties_set_int( b_props, "distort", 1 );
- }
-
- if ( mlt_properties_get_int( properties, "reverse" ) == 0 )
- {
- // Apply all filters that are attached to this filter to the b frame
- mlt_service_apply_filters( MLT_FILTER_SERVICE( this ), b_frame, 0 );
-
- // Process the frame
- mlt_transition_process( composite, frame, b_frame );
-
- // Get the image
- error = mlt_frame_get_image( frame, image, format, width, height, 1 );
- }
- else
- {
- char temp[ 132 ];
- int count = 0;
- uint8_t *alpha = NULL;
- const char *rescale = mlt_properties_get( a_props, "rescale.interp" );
- if ( rescale == NULL || !strcmp( rescale, "none" ) )
- rescale = "hyper";
- mlt_transition_process( composite, b_frame, frame );
- mlt_properties_set_int( a_props, "consumer_deinterlace", 1 );
- mlt_properties_set_int( b_props, "consumer_deinterlace", 1 );
- mlt_properties_set( a_props, "rescale.interp", rescale );
- mlt_properties_set( b_props, "rescale.interp", rescale );
- mlt_service_apply_filters( MLT_FILTER_SERVICE( this ), b_frame, 0 );
- error = mlt_frame_get_image( b_frame, image, format, width, height, 1 );
- alpha = mlt_frame_get_alpha_mask( b_frame );
- mlt_properties_set_data( a_props, "image", *image, *width * *height * 2, NULL, NULL );
- mlt_properties_set_data( a_props, "alpha", alpha, *width * *height, NULL, NULL );
- mlt_properties_set_int( a_props, "width", *width );
- mlt_properties_set_int( a_props, "height", *height );
- mlt_properties_set_int( a_props, "progressive", 1 );
- mlt_properties_inc_ref( b_props );
- strcpy( temp, "_b_frame" );
- while( mlt_properties_get_data( a_props, temp, NULL ) != NULL )
- sprintf( temp, "_b_frame%d", count ++ );
- mlt_properties_set_data( a_props, temp, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
- }
-
- // Close the b frame
- mlt_frame_close( b_frame );
- }
- else
- {
- // Get the image from the frame without running fx
- error = mlt_frame_get_image( frame, image, format, width, height, 1 );
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get a unique name to store the frame position
- char *name = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "_unique_id" );
-
- // Assign the frame out point to the filter (just in case we need it later)
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "_out", mlt_properties_get_int( properties, "out" ) );
-
- // Assign the current position to the name
- mlt_properties_set_position( properties, name, mlt_frame_get_position( frame ) - mlt_filter_get_in( this ) );
-
- // Push the filter on to the stack
- mlt_frame_push_service( frame, this );
-
- // Push the get_image on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_watermark_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- this->process = filter_process;
- mlt_properties_set( properties, "factory", "fezzik" );
- if ( arg != NULL )
- mlt_properties_set( properties, "resource", arg );
- // Ensure that attached filters are handled privately
- mlt_properties_set_int( properties, "_filter_private", 1 );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * producer_colour.c -- raster image loader based upon gdk-pixbuf
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_pool.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-typedef struct
-{
- uint8_t r, g, b, a;
-} rgba_color;
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_colour_init( mlt_profile profile, mlt_service_type type, const char *id, char *colour )
-{
- mlt_producer producer = calloc( 1, sizeof( struct mlt_producer_s ) );
- if ( producer != NULL && mlt_producer_init( producer, NULL ) == 0 )
- {
- // Get the properties interface
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Callback registration
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- // Set the default properties
- mlt_properties_set( properties, "resource", colour == NULL ? "0x000000ff" : colour );
- mlt_properties_set( properties, "_resource", "" );
- mlt_properties_set_double( properties, "aspect_ratio", 0 );
-
- return producer;
- }
- free( producer );
- return NULL;
-}
-
-rgba_color parse_color( char *color, unsigned int color_int )
-{
- rgba_color result = { 0xff, 0xff, 0xff, 0xff };
-
- if ( !strcmp( color, "red" ) )
- {
- result.r = 0xff;
- result.g = 0x00;
- result.b = 0x00;
- }
- else if ( !strcmp( color, "green" ) )
- {
- result.r = 0x00;
- result.g = 0xff;
- result.b = 0x00;
- }
- else if ( !strcmp( color, "blue" ) )
- {
- result.r = 0x00;
- result.g = 0x00;
- result.b = 0xff;
- }
- else if ( strcmp( color, "white" ) )
- {
- result.r = ( color_int >> 24 ) & 0xff;
- result.g = ( color_int >> 16 ) & 0xff;
- result.b = ( color_int >> 8 ) & 0xff;
- result.a = ( color_int ) & 0xff;
- }
-
- return result;
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // May need to know the size of the image to clone it
- int size = 0;
-
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer for this frame
- mlt_producer producer = mlt_properties_get_data( properties, "producer_colour", NULL );
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Get the current and previous colour strings
- char *now = mlt_properties_get( producer_props, "resource" );
- char *then = mlt_properties_get( producer_props, "_resource" );
-
- // Get the current image and dimensions cached in the producer
- uint8_t *image = mlt_properties_get_data( producer_props, "image", &size );
- int current_width = mlt_properties_get_int( producer_props, "_width" );
- int current_height = mlt_properties_get_int( producer_props, "_height" );
-
- // Parse the colour
- if ( now && strchr( now, '/' ) )
- {
- now = strrchr( now, '/' ) + 1;
- mlt_properties_set( producer_props, "resource", now );
- }
- rgba_color color = parse_color( now, mlt_properties_get_int( producer_props, "resource" ) );
-
- // See if we need to regenerate
- if ( strcmp( now, then ) || *width != current_width || *height != current_height )
- {
- // Color the image
- uint8_t y, u, v;
- int i = *height;
- int j = 0;
- int uneven = *width % 2;
- int count = ( *width - uneven ) / 2;
- uint8_t *p = NULL;
-
- // Allocate the image
- size = *width * *height * 2;
- image = mlt_pool_alloc( size );
-
- // Update the producer
- mlt_properties_set_data( producer_props, "image", image, size, mlt_pool_release, NULL );
- mlt_properties_set_int( producer_props, "_width", *width );
- mlt_properties_set_int( producer_props, "_height", *height );
- mlt_properties_set( producer_props, "_resource", now );
-
- RGB2YUV( color.r, color.g, color.b, y, u, v );
-
- p = image;
-
- while ( i -- )
- {
- j = count;
- while ( j -- )
- {
- *p ++ = y;
- *p ++ = u;
- *p ++ = y;
- *p ++ = v;
- }
- if ( uneven )
- {
- *p ++ = y;
- *p ++ = u;
- }
- }
- }
-
- // Update the frame
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
-
- // Clone if necessary (deemed always necessary)
- if ( 1 )
- {
- // Create the alpha channel
- uint8_t *alpha = mlt_pool_alloc( size >> 1 );
-
- // Clone our image
- uint8_t *copy = mlt_pool_alloc( size );
- memcpy( copy, image, size );
-
- // We're going to pass the copy on
- image = copy;
-
- // Initialise the alpha
- if ( alpha )
- memset( alpha, color.a, size >> 1 );
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", copy, size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha, size >> 1, mlt_pool_release, NULL );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
- }
-
- // Pass on the image
- *buffer = image;
- *format = mlt_image_yuv422;
-
- return 0;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- if ( *frame != NULL )
- {
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Set the producer on the frame properties
- mlt_properties_set_data( properties, "producer_colour", producer, 0, NULL, NULL );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
-
- // colour is an alias for resource
- if ( mlt_properties_get( producer_props, "colour" ) != NULL )
- mlt_properties_set( producer_props, "resource", mlt_properties_get( producer_props, "colour" ) );
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer producer )
-{
- producer->close = NULL;
- mlt_producer_close( producer );
- free( producer );
-}
+++ /dev/null
-/*
- * producer_consumer.c -- produce as a consumer of an encapsulated producer
- * Copyright (C) 2008 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-struct context_s {
- mlt_producer this;
- mlt_producer producer;
- mlt_consumer consumer;
- mlt_profile profile;
- int is_close_profile;
-};
-typedef struct context_s *context;
-
-
-static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- context cx = mlt_frame_pop_service( frame );
- mlt_frame nested_frame = mlt_frame_pop_service( frame );
-
- *width = cx->profile->width;
- *height = cx->profile->height;
-
- int result = mlt_frame_get_image( nested_frame, image, format, width, height, writable );
-
- // Allocate the image
- int size = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 : *format == mlt_image_rgb24a ? 4 : ( 3 / 2 ) );
- uint8_t *new_image = mlt_pool_alloc( size );
-
- // Update the frame
- mlt_properties properties = mlt_frame_properties( frame );
- mlt_properties_set_data( properties, "image", new_image, size, mlt_pool_release, NULL );
- memcpy( new_image, *image, size );
- mlt_frame_close( nested_frame );
- *image = new_image;
-
-// mlt_properties_debug( properties, "frame", stderr );
-// mlt_properties_debug( mlt_frame_properties( nested_frame ), "nested_frame", stderr );
-
- return result;
-}
-
-static int get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- mlt_frame nested_frame = mlt_frame_pop_audio( frame );
- int result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples );
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "audio", new_buffer, size, mlt_pool_release, NULL );
- memcpy( new_buffer, *buffer, size );
- *buffer = new_buffer;
- mlt_frame_close( nested_frame );
- return result;
-}
-
-static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES(this);
- context cx = mlt_properties_get_data( properties, "context", NULL );
-
- if ( !cx )
- {
- // Allocate and initialize our context
- cx = mlt_pool_alloc( sizeof( struct context_s ) );
- mlt_properties_set_data( properties, "context", cx, 0, mlt_pool_release, NULL );
- cx->this = this;
- char *profile_name = mlt_properties_get( properties, "profile" );
- mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( this ) );
-
- if ( profile_name )
- {
- cx->profile = mlt_profile_init( profile_name );
- cx->is_close_profile = 1;
- }
- else
- {
- cx->profile = profile;
- cx->is_close_profile = 0;
- }
-
- // For now, we must conform the nested network's frame rate to the parent network's
- // framerate.
- cx->profile->frame_rate_num = profile->frame_rate_num;
- cx->profile->frame_rate_den = profile->frame_rate_den;
-
- // We will encapsulate a consumer
- cx->consumer = mlt_consumer_new( cx->profile );
- // Do not use _pass_list on real_time so that it defaults to 0 in the absence of
- // an explicit real_time property.
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( cx->consumer ), "real_time",
- mlt_properties_get_int( properties, "real_time" ) );
- mlt_properties_pass_list( MLT_CONSUMER_PROPERTIES( cx->consumer ), properties,
- "buffer, prefill" );
-
- // Encapsulate a real producer for the resource
- cx->producer = mlt_factory_producer( cx->profile, mlt_environment( "MLT_PRODUCER" ),
- mlt_properties_get( properties, "resource" ) );
- mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( cx->producer ),
- "out, length" );
-
- // Since we control the seeking, prevent it from seeking on its own
- mlt_producer_set_speed( cx->producer, 0 );
-
- // Connect it all together
- mlt_consumer_connect( cx->consumer, MLT_PRODUCER_SERVICE( cx->producer ) );
- mlt_consumer_start( cx->consumer );
- }
-
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
- if ( frame )
- {
- // Our "in" needs to be the same, keep it so
- mlt_properties_pass_list( MLT_PRODUCER_PROPERTIES( cx->producer ), properties, "in, out" );
-
- // Seek the producer to the correct place
- // Calculate our positions
- double actual_position = mlt_producer_get_speed( this ) * (double)mlt_producer_position( this );
- mlt_position need_first = floor( actual_position );
- mlt_producer_seek( cx->producer, need_first );
-
- // Get the nested frame
- mlt_frame nested_frame = mlt_consumer_rt_frame( cx->consumer );
-
- // Stack the producer and our methods on the nested frame
- mlt_frame_push_service( *frame, nested_frame );
- mlt_frame_push_service( *frame, cx );
- mlt_frame_push_get_image( *frame, get_image );
- mlt_frame_push_audio( *frame, nested_frame );
- mlt_frame_push_audio( *frame, get_audio );
-
- // Give the returned frame temporal identity
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
-
- // Put additional references on the frame so both get_image and get_audio
- // methods can close it.
- mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( nested_frame ) );
-
- // Inform the normalizers about our video properties
- mlt_properties frame_props = MLT_FRAME_PROPERTIES( *frame );
- mlt_properties_set_double( frame_props, "aspect_ratio", mlt_profile_sar( cx->profile ) );
- mlt_properties_set_int( frame_props, "width", cx->profile->width );
- mlt_properties_set_int( frame_props, "height", cx->profile->height );
- mlt_properties_set_int( frame_props, "real_width", cx->profile->width );
- mlt_properties_set_int( frame_props, "real_height", cx->profile->height );
- mlt_properties_set_int( frame_props, "progressive", cx->profile->progressive );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( this );
-
- return 0;
-}
-
-static void producer_close( mlt_producer this )
-{
- context cx = mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( this ), "context", NULL );
-
- // Shut down all the encapsulated services
- if ( cx )
- {
- mlt_consumer_stop( cx->consumer );
- mlt_consumer_close( cx->consumer );
- mlt_producer_close( cx->producer );
- if ( cx->is_close_profile )
- mlt_profile_close( cx->profile );
- }
-
- this->close = NULL;
- mlt_producer_close( this );
- free( this );
-}
-
-mlt_producer producer_consumer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_producer this = mlt_producer_new( );
-
- // Encapsulate the real producer
- mlt_producer real_producer = mlt_factory_producer( profile, mlt_environment( "MLT_PRODUCER" ), arg );
-
- if ( this && real_producer )
- {
- // Override some producer methods
- this->close = ( mlt_destructor )producer_close;
- this->get_frame = get_frame;
-
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- mlt_properties_set( properties, "resource", arg );
- mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( real_producer ), "out, length" );
-
- // Done with the producer - will re-open later when we have the profile property
- mlt_producer_close( real_producer );
- }
- else
- {
- if ( this )
- mlt_producer_close( this );
- if ( real_producer )
- mlt_producer_close( real_producer );
-
- this = NULL;
- }
- return this;
-}
+++ /dev/null
-/*
- * producer_noise.c -- noise generating producer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_pool.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/** Random number generator
-*/
-
-static unsigned int seed_x = 521288629;
-static unsigned int seed_y = 362436069;
-
-static inline unsigned int fast_rand( )
-{
- static unsigned int a = 18000, b = 30903;
- seed_x = a * ( seed_x & 65535 ) + ( seed_x >> 16 );
- seed_y = b * ( seed_y & 65535 ) + ( seed_y >> 16 );
- return ( ( seed_x << 16 ) + ( seed_y & 65535 ) );
-}
-
-// Foward declarations
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer this );
-
-/** Initialise.
-*/
-
-mlt_producer producer_noise_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create a new producer object
- mlt_producer this = mlt_producer_new( );
-
- // Initialise the producer
- if ( this != NULL )
- {
- // Callback registration
- this->get_frame = producer_get_frame;
- this->close = ( mlt_destructor )producer_close;
- }
-
- return this;
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Calculate the size of the image
- int size = *width * *height * 2;
-
- // Set the format being returned
- *format = mlt_image_yuv422;
-
- // Allocate the image
- *buffer = mlt_pool_alloc( size );
-
- // Update the frame
- mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
-
- // Before we write to the image, make sure we have one
- if ( *buffer != NULL )
- {
- // Calculate the end of the buffer
- uint8_t *p = *buffer + *width * *height * 2;
-
- // Value to hold a random number
- uint32_t value;
-
- // Generate random noise
- while ( p != *buffer )
- {
- value = fast_rand( ) & 0xff;
- *( -- p ) = 128;
- *( -- p ) = value < 16 ? 16 : value > 240 ? 240 : value;
- }
- }
-
- return 0;
-}
-
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the frame properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- int size = 0;
-
- // Correct the returns if necessary
- *samples = *samples <= 0 ? 1920 : *samples;
- *channels = *channels <= 0 ? 2 : *channels;
- *frequency = *frequency <= 0 ? 48000 : *frequency;
-
- // Calculate the size of the buffer
- size = *samples * *channels * sizeof( int16_t );
-
- // Allocate the buffer
- *buffer = mlt_pool_alloc( size );
-
- // Make sure we got one and fill it
- if ( *buffer != NULL )
- {
- int16_t *p = *buffer + size / 2;
- while ( p != *buffer )
- *( -- p ) = fast_rand( ) & 0x0f00;
- }
-
- // Set the buffer for destruction
- mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- return 0;
-}
-
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-
- // Check that we created a frame and initialise it
- if ( *frame != NULL )
- {
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Aspect ratio is whatever it needs to be
- mlt_properties_set_double( properties, "aspect_ratio", 0 );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", 1 );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
-
- // Specify the audio
- mlt_frame_push_audio( *frame, producer_get_audio );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( this );
-
- return 0;
-}
-
-static void producer_close( mlt_producer this )
-{
- this->close = NULL;
- mlt_producer_close( this );
- free( this );
-}
-
+++ /dev/null
-/*
- * producer_ppm.c -- simple ppm test case
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-typedef struct producer_ppm_s *producer_ppm;
-
-struct producer_ppm_s
-{
- struct mlt_producer_s parent;
- char *command;
- FILE *video;
- FILE *audio;
- uint64_t expected;
-};
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_ppm_init( mlt_profile profile, mlt_service_type type, const char *id, char *command )
-{
- producer_ppm this = calloc( sizeof( struct producer_ppm_s ), 1 );
- if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- mlt_producer producer = &this->parent;
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- if ( command != NULL )
- {
- mlt_properties_set( properties, "resource", command );
- this->command = strdup( command );
- }
- else
- {
- mlt_properties_set( properties, "resource", "ppm test" );
- }
-
- return producer;
- }
- free( this );
- return NULL;
-}
-
-static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- if ( mlt_properties_get_int( properties, "has_image" ) )
- {
- // Get the RGB image
- uint8_t *rgb = mlt_properties_get_data( properties, "image", NULL );
-
- // Get width and height
- *width = mlt_properties_get_int( properties, "width" );
- *height = mlt_properties_get_int( properties, "height" );
-
- // Convert to requested format
- if ( *format == mlt_image_yuv422 )
- {
- uint8_t *image = mlt_pool_alloc( *width * ( *height + 1 ) * 2 );
- mlt_convert_rgb24_to_yuv422( rgb, *width, *height, *width * 3, image );
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- *buffer = image;
- }
- else if ( *format == mlt_image_rgb24 )
- {
- *buffer = rgb;
- }
- }
- else
- {
- mlt_frame_get_image( this, buffer, format, width, height, writable );
- }
-
- return 0;
-}
-
-FILE *producer_ppm_run_video( producer_ppm this )
-{
- if ( this->video == NULL )
- {
- if ( this->command == NULL )
- {
- this->video = popen( "image2raw -k -r 25 -ppm /usr/share/pixmaps/*.png", "r" );
- }
- else
- {
- char command[ 1024 ];
- float fps = mlt_producer_get_fps( &this->parent );
- float position = mlt_producer_position( &this->parent );
- sprintf( command, "ffmpeg -i \"%s\" -ss %f -f imagepipe -r %f -img ppm - 2>/dev/null", this->command, position, fps );
- this->video = popen( command, "r" );
- }
- }
- return this->video;
-}
-
-FILE *producer_ppm_run_audio( producer_ppm this )
-{
- if ( this->audio == NULL )
- {
- if ( this->command != NULL )
- {
- char command[ 1024 ];
- float position = mlt_producer_position( &this->parent );
- sprintf( command, "ffmpeg -i \"%s\" -ss %f -f s16le -ar 48000 -ac 2 - 2>/dev/null", this->command, position );
- this->audio = popen( command, "r" );
- }
- }
- return this->audio;
-}
-
-static void producer_ppm_position( producer_ppm this, uint64_t requested )
-{
- if ( requested != this->expected )
- {
- if ( this->video != NULL )
- pclose( this->video );
- this->video = NULL;
- if ( this->audio != NULL )
- pclose( this->audio );
- this->audio = NULL;
- }
-
- // This is the next frame we expect
- this->expected = mlt_producer_frame( &this->parent ) + 1;
-
- // Open the pipe
- this->video = producer_ppm_run_video( this );
-
- // Open the audio pipe
- this->audio = producer_ppm_run_audio( this );
-
-}
-
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- FILE *pipe = mlt_properties_get_data( properties, "audio.pipe", NULL );
-
- *frequency = 48000;
- *channels = 2;
- *samples = 1920;
-
- // Size
- int size = *samples * *channels * 2;
-
- // Allocate an image
- *buffer = malloc( size );
-
- // Read it
- if ( pipe != NULL )
- fread( *buffer, size, 1, pipe );
- else
- memset( *buffer, 0, size );
-
- // Pass the data on the frame properties
- mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
-
- return 0;
-}
-
-static int read_ppm_header( FILE *video, int *width, int *height )
-{
- int count = 0;
- {
- char temp[ 132 ];
- fgets( temp, 132, video );
- fgets( temp, 132, video );
- count += sscanf( temp, "%d %d", width, height );
- fgets( temp, 132, video );
- }
- return count;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- producer_ppm this = producer->child;
- int width;
- int height;
-
- // Construct a test frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- // Are we at the position expected?
- producer_ppm_position( this, mlt_producer_frame( producer ) );
-
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- FILE *video = this->video;
- FILE *audio = this->audio;
-
- // Read the video
- if ( video != NULL && read_ppm_header( video, &width, &height ) == 2 )
- {
- // Allocate an image
- uint8_t *image = mlt_pool_alloc( width * ( height + 1 ) * 3 );
-
- // Read it
- fread( image, width * height * 3, 1, video );
-
- // Pass the data on the frame properties
- mlt_properties_set_data( properties, "image", image, width * ( height + 1 ) * 3, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", width );
- mlt_properties_set_int( properties, "height", height );
- mlt_properties_set_int( properties, "has_image", 1 );
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", 1 );
-
- // Push the image callback
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
- else
- {
- // Push the image callback
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Set the audio pipe
- mlt_properties_set_data( properties, "audio.pipe", audio, 0, NULL, NULL );
-
- // Hmm - register audio callback
- mlt_frame_push_audio( *frame, producer_get_audio );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- producer_ppm this = parent->child;
- if ( this->video )
- pclose( this->video );
- if ( this->audio )
- pclose( this->audio );
- free( this->command );
- parent->close = NULL;
- mlt_producer_close( parent );
- free( this );
-}
+++ /dev/null
-/*
- * transition_composite.c -- compose one image over another using alpha channel
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "transition_composite.h"
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-
-typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int softness );
-
-/** Geometry struct.
-*/
-
-struct geometry_s
-{
- struct mlt_geometry_item_s item;
- int nw; // normalised width
- int nh; // normalised height
- int sw; // scaled width, not including consumer scale based upon w/nw
- int sh; // scaled height, not including consumer scale based upon h/nh
- int halign; // horizontal alignment: 0=left, 1=center, 2=right
- int valign; // vertical alignment: 0=top, 1=middle, 2=bottom
- int x_src;
- int y_src;
-};
-
-/** Parse the alignment properties into the geometry.
-*/
-
-static int alignment_parse( char* align )
-{
- int ret = 0;
-
- if ( align == NULL );
- else if ( isdigit( align[ 0 ] ) )
- ret = atoi( align );
- else if ( align[ 0 ] == 'c' || align[ 0 ] == 'm' )
- ret = 1;
- else if ( align[ 0 ] == 'r' || align[ 0 ] == 'b' )
- ret = 2;
-
- return ret;
-}
-
-/** Calculate real geometry.
-*/
-
-static void geometry_calculate( mlt_transition this, struct geometry_s *output, double position )
-{
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- mlt_geometry geometry = mlt_properties_get_data( properties, "geometries", NULL );
- int mirror_off = mlt_properties_get_int( properties, "mirror_off" );
- int repeat_off = mlt_properties_get_int( properties, "repeat_off" );
- int length = mlt_geometry_get_length( geometry );
-
- // Allow wrapping
- if ( !repeat_off && position >= length && length != 0 )
- {
- int section = position / length;
- position -= section * length;
- if ( !mirror_off && section % 2 == 1 )
- position = length - position;
- }
-
- // Fetch the key for the position
- mlt_geometry_fetch( geometry, &output->item, position );
-}
-
-static mlt_geometry transition_parse_keys( mlt_transition this, int normalised_width, int normalised_height )
-{
- // Loop variable for property interrogation
- int i = 0;
-
- // Get the properties of the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Create an empty geometries object
- mlt_geometry geometry = mlt_geometry_init( );
-
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
- int length = out - in + 1;
- double cycle = mlt_properties_get_double( properties, "cycle" );
-
- // Get the new style geometry string
- char *property = mlt_properties_get( properties, "geometry" );
-
- // Allow a geometry repeat cycle
- if ( cycle >= 1 )
- length = cycle;
- else if ( cycle > 0 )
- length *= cycle;
-
- // Parse the geometry if we have one
- mlt_geometry_parse( geometry, property, length, normalised_width, normalised_height );
-
- // Check if we're using the old style geometry
- if ( property == NULL )
- {
- // DEPRECATED: Multiple keys for geometry information is inefficient and too rigid for
- // practical use - while deprecated, it has been slightly extended too - keys can now
- // be specified out of order, and can be blanked or NULL to simulate removal
-
- // Structure to use for parsing and inserting
- struct mlt_geometry_item_s item;
-
- // Parse the start property
- item.frame = 0;
- if ( mlt_geometry_parse_item( geometry, &item, mlt_properties_get( properties, "start" ) ) == 0 )
- mlt_geometry_insert( geometry, &item );
-
- // Parse the keys in between
- for ( i = 0; i < mlt_properties_count( properties ); i ++ )
- {
- // Get the name of the property
- char *name = mlt_properties_get_name( properties, i );
-
- // Check that it's valid
- if ( !strncmp( name, "key[", 4 ) )
- {
- // Get the value of the property
- char *value = mlt_properties_get_value( properties, i );
-
- // Determine the frame number
- item.frame = atoi( name + 4 );
-
- // Parse and add to the list
- if ( mlt_geometry_parse_item( geometry, &item, value ) == 0 )
- mlt_geometry_insert( geometry, &item );
- else
- fprintf( stderr, "Invalid Key - skipping %s = %s\n", name, value );
- }
- }
-
- // Parse the end
- item.frame = -1;
- if ( mlt_geometry_parse_item( geometry, &item, mlt_properties_get( properties, "end" ) ) == 0 )
- mlt_geometry_insert( geometry, &item );
- }
-
- return geometry;
-}
-
-/** Adjust position according to scaled size and alignment properties.
-*/
-
-static void alignment_calculate( struct geometry_s *geometry )
-{
- geometry->item.x += ( geometry->item.w - geometry->sw ) * geometry->halign / 2;
- geometry->item.y += ( geometry->item.h - geometry->sh ) * geometry->valign / 2;
-}
-
-/** Calculate the position for this frame.
-*/
-
-static int position_calculate( mlt_transition this, mlt_position position )
-{
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
-
- // Now do the calcs
- return position - in;
-}
-
-/** Calculate the field delta for this frame - position between two frames.
-*/
-
-static inline double delta_calculate( mlt_transition this, mlt_frame frame, mlt_position position )
-{
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
- double length = out - in + 1;
-
- // Now do the calcs
- double x = ( double )( position - in ) / length;
- double y = ( double )( position + 1 - in ) / length;
-
- return length * ( y - x ) / 2.0;
-}
-
-static int get_value( mlt_properties properties, const char *preferred, const char *fallback )
-{
- int value = mlt_properties_get_int( properties, preferred );
- if ( value == 0 )
- value = mlt_properties_get_int( properties, fallback );
- return value;
-}
-
-/** A linear threshold determination function.
-*/
-
-static inline int32_t linearstep( int32_t edge1, int32_t edge2, int32_t a )
-{
- if ( a < edge1 )
- return 0;
-
- if ( a >= edge2 )
- return 0x10000;
-
- return ( ( a - edge1 ) << 16 ) / ( edge2 - edge1 );
-}
-
-/** A smoother, non-linear threshold determination function.
-*/
-
-static inline int32_t smoothstep( int32_t edge1, int32_t edge2, uint32_t a )
-{
- if ( a < edge1 )
- return 0;
-
- if ( a >= edge2 )
- return 0x10000;
-
- a = ( ( a - edge1 ) << 16 ) / ( edge2 - edge1 );
-
- return ( ( ( a * a ) >> 16 ) * ( ( 3 << 16 ) - ( 2 * a ) ) ) >> 16;
-}
-
-/** Load the luma map from PGM stream.
-*/
-
-static void luma_read_pgm( FILE *f, uint16_t **map, int *width, int *height )
-{
- uint8_t *data = NULL;
- while (1)
- {
- char line[128];
- char comment[128];
- int i = 2;
- int maxval;
- int bpp;
- uint16_t *p;
-
- line[127] = '\0';
-
- // get the magic code
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- if ( line[0] != 'P' || line[1] != '5' )
- break;
-
- // skip white space and see if a new line must be fetched
- for ( i = 2; i < 127 && line[i] != '\0' && isspace( line[i] ); i++ );
- if ( ( line[i] == '\0' || line[i] == '#' ) && fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // get the dimensions
- if ( line[0] == 'P' )
- i = sscanf( line, "P5 %d %d %d", width, height, &maxval );
- else
- i = sscanf( line, "%d %d %d", width, height, &maxval );
-
- // get the height value, if not yet
- if ( i < 2 )
- {
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- i = sscanf( line, "%d", height );
- if ( i == 0 )
- break;
- else
- i = 2;
- }
-
- // get the maximum gray value, if not yet
- if ( i < 3 )
- {
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- i = sscanf( line, "%d", &maxval );
- if ( i == 0 )
- break;
- }
-
- // determine if this is one or two bytes per pixel
- bpp = maxval > 255 ? 2 : 1;
-
- // allocate temporary storage for the raw data
- data = mlt_pool_alloc( *width * *height * bpp );
- if ( data == NULL )
- break;
-
- // read the raw data
- if ( fread( data, *width * *height * bpp, 1, f ) != 1 )
- break;
-
- // allocate the luma bitmap
- *map = p = (uint16_t*)mlt_pool_alloc( *width * *height * sizeof( uint16_t ) );
- if ( *map == NULL )
- break;
-
- // proces the raw data into the luma bitmap
- for ( i = 0; i < *width * *height * bpp; i += bpp )
- {
- if ( bpp == 1 )
- *p++ = data[ i ] << 8;
- else
- *p++ = ( data[ i ] << 8 ) + data[ i + 1 ];
- }
-
- break;
- }
-
- if ( data != NULL )
- mlt_pool_release( data );
-}
-
-/** Generate a luma map from any YUV image.
-*/
-
-static void luma_read_yuv422( uint8_t *image, uint16_t **map, int width, int height )
-{
- int i;
-
- // allocate the luma bitmap
- uint16_t *p = *map = ( uint16_t* )mlt_pool_alloc( width * height * sizeof( uint16_t ) );
- if ( *map == NULL )
- return;
-
- // proces the image data into the luma bitmap
- for ( i = 0; i < width * height * 2; i += 2 )
- *p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219
-}
-
-static inline int calculate_mix( uint16_t *luma, int j, int soft, int weight, int alpha )
-{
- return ( ( ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + soft, weight + soft ) ) * alpha ) >> 8;
-}
-
-static inline uint8_t sample_mix( uint8_t dest, uint8_t src, int mix )
-{
- return ( src * mix + dest * ( ( 1 << 16 ) - mix ) ) >> 16;
-}
-
-/** Composite a source line over a destination line
-*/
-
-static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
-{
- register int j;
- register int mix;
-
- for ( j = 0; j < width; j ++ )
- {
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ );
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *alpha_a = ( mix >> 8 ) | *alpha_a;
- alpha_a ++;
- }
-}
-
-static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
-{
- register int j;
- register int mix;
-
- for ( j = 0; j < width; j ++ )
- {
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ | *alpha_a );
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *alpha_a ++ = mix >> 8;
- }
-}
-
-static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
-{
- register int j;
- register int mix;
-
- for ( j = 0; j < width; j ++ )
- {
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ & *alpha_a );
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *alpha_a ++ = mix >> 8;
- }
-}
-
-static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
-{
- register int j;
- register int mix;
-
- for ( j = 0; j < width; j ++ )
- {
- mix = calculate_mix( luma, j, soft, weight, *alpha_b ++ ^ *alpha_a );
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *dest = sample_mix( *dest, *src++, mix );
- dest++;
- *alpha_a ++ = mix >> 8;
- }
-}
-
-/** Composite function.
-*/
-
-static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *alpha_b, uint8_t *alpha_a, struct geometry_s geometry, int field, uint16_t *p_luma, int32_t softness, composite_line_fn line_fn )
-{
- int ret = 0;
- int i;
- int x_src = -geometry.x_src, y_src = -geometry.y_src;
- int uneven_x_src = ( x_src % 2 );
- int32_t weight = ( ( 1 << 16 ) - 1 ) * ( geometry.item.mix / 100 );
- int step = ( field > -1 ) ? 2 : 1;
- int bpp = 2;
- int stride_src = geometry.sw * bpp;
- int stride_dest = width_dest * bpp;
-
- // Adjust to consumer scale
- int x = rint( geometry.item.x * width_dest / geometry.nw );
- int y = rint( geometry.item.y * height_dest / geometry.nh );
- int uneven_x = ( x % 2 );
-
- // optimization points - no work to do
- if ( width_src <= 0 || height_src <= 0 || y_src >= height_src || x_src >= width_src )
- return ret;
-
- if ( ( x < 0 && -x >= width_src ) || ( y < 0 && -y >= height_src ) )
- return ret;
-
- // cropping affects the source width
- if ( x_src > 0 )
- {
- width_src -= x_src;
- // and it implies cropping
- if ( width_src > geometry.item.w )
- width_src = geometry.item.w;
- }
-
- // cropping affects the source height
- if ( y_src > 0 )
- {
- height_src -= y_src;
- // and it implies cropping
- if ( height_src > geometry.item.h )
- height_src = geometry.item.h;
- }
-
- // crop overlay off the left edge of frame
- if ( x < 0 )
- {
- x_src = -x;
- width_src -= x_src;
- x = 0;
- }
-
- // crop overlay beyond right edge of frame
- if ( x + width_src > width_dest )
- width_src = width_dest - x;
-
- // crop overlay off the top edge of the frame
- if ( y < 0 )
- {
- y_src = -y;
- height_src -= y_src;
- y = 0;
- }
-
- // crop overlay below bottom edge of frame
- if ( y + height_src > height_dest )
- height_src = height_dest - y;
-
- // offset pointer into overlay buffer based on cropping
- p_src += x_src * bpp + y_src * stride_src;
-
- // offset pointer into frame buffer based upon positive coordinates only!
- p_dest += ( x < 0 ? 0 : x ) * bpp + ( y < 0 ? 0 : y ) * stride_dest;
-
- // offset pointer into alpha channel based upon cropping
- alpha_b += x_src + y_src * stride_src / bpp;
- alpha_a += x + y * stride_dest / bpp;
-
- // offset pointer into luma channel based upon cropping
- if ( p_luma )
- p_luma += x_src + y_src * stride_src / bpp;
-
- // Assuming lower field first
- // Special care is taken to make sure the b_frame is aligned to the correct field.
- // field 0 = lower field and y should be odd (y is 0-based).
- // field 1 = upper field and y should be even.
- if ( ( field > -1 ) && ( y % 2 == field ) )
- {
- if ( ( field == 1 && y < height_dest - 1 ) || ( field == 0 && y == 0 ) )
- p_dest += stride_dest;
- else
- p_dest -= stride_dest;
- }
-
- // On the second field, use the other lines from b_frame
- if ( field == 1 )
- {
- p_src += stride_src;
- alpha_b += stride_src / bpp;
- alpha_a += stride_dest / bpp;
- height_src--;
- }
-
- stride_src *= step;
- stride_dest *= step;
- int alpha_b_stride = stride_src / bpp;
- int alpha_a_stride = stride_dest / bpp;
-
- // Align chroma of source and destination
- if ( uneven_x != uneven_x_src )
- {
- p_src += 2;
- width_src -= 2;
- alpha_b += 1;
- }
-
- // now do the compositing only to cropped extents
- for ( i = 0; i < height_src; i += step )
- {
- line_fn( p_dest, p_src, width_src, alpha_b, alpha_a, weight, p_luma, softness );
-
- p_src += stride_src;
- p_dest += stride_dest;
- alpha_b += alpha_b_stride;
- alpha_a += alpha_a_stride;
- if ( p_luma )
- p_luma += alpha_b_stride;
- }
-
- return ret;
-}
-
-
-/** Scale 16bit greyscale luma map using nearest neighbor.
-*/
-
-static inline void
-scale_luma ( uint16_t *dest_buf, int dest_width, int dest_height, const uint16_t *src_buf, int src_width, int src_height, int invert )
-{
- register int i, j;
- register int x_step = ( src_width << 16 ) / dest_width;
- register int y_step = ( src_height << 16 ) / dest_height;
- register int x, y = 0;
-
- for ( i = 0; i < dest_height; i++ )
- {
- const uint16_t *src = src_buf + ( y >> 16 ) * src_width;
- x = 0;
-
- for ( j = 0; j < dest_width; j++ )
- {
- *dest_buf++ = src[ x >> 16 ] ^ invert;
- x += x_step;
- }
- y += y_step;
- }
-}
-
-static uint16_t* get_luma( mlt_transition this, mlt_properties properties, int width, int height )
-{
- // The cached luma map information
- int luma_width = mlt_properties_get_int( properties, "_luma.width" );
- int luma_height = mlt_properties_get_int( properties, "_luma.height" );
- uint16_t *luma_bitmap = mlt_properties_get_data( properties, "_luma.bitmap", NULL );
- int invert = mlt_properties_get_int( properties, "luma_invert" );
-
- // If the filename property changed, reload the map
- char *resource = mlt_properties_get( properties, "luma" );
-
- char temp[ 512 ];
-
- if ( luma_width == 0 || luma_height == 0 )
- {
- luma_width = width;
- luma_height = height;
- }
-
- if ( resource && resource[0] && strchr( resource, '%' ) )
- {
- // TODO: Clean up quick and dirty compressed/existence check
- FILE *test;
- sprintf( temp, "%s/lumas/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( resource, '%' ) + 1 );
- test = fopen( temp, "r" );
- if ( test == NULL )
- strcat( temp, ".png" );
- else
- fclose( test );
- resource = temp;
- }
-
- if ( resource && resource[0] )
- {
- char *old_luma = mlt_properties_get( properties, "_luma" );
- int old_invert = mlt_properties_get_int( properties, "_luma_invert" );
-
- if ( invert != old_invert || ( old_luma && old_luma[0] && strcmp( resource, old_luma ) ) )
- {
- mlt_properties_set_data( properties, "_luma.orig_bitmap", NULL, 0, NULL, NULL );
- luma_bitmap = NULL;
- }
- }
- else {
- char *old_luma = mlt_properties_get( properties, "_luma" );
- if ( old_luma && old_luma[0] )
- {
- mlt_properties_set_data( properties, "_luma.orig_bitmap", NULL, 0, NULL, NULL );
- luma_bitmap = NULL;
- mlt_properties_set( properties, "_luma", NULL);
- }
- }
-
- if ( resource && resource[0] && ( luma_bitmap == NULL || luma_width != width || luma_height != height ) )
- {
- uint16_t *orig_bitmap = mlt_properties_get_data( properties, "_luma.orig_bitmap", NULL );
- luma_width = mlt_properties_get_int( properties, "_luma.orig_width" );
- luma_height = mlt_properties_get_int( properties, "_luma.orig_height" );
-
- // Load the original luma once
- if ( orig_bitmap == NULL )
- {
- char *extension = strrchr( resource, '.' );
-
- // See if it is a PGM
- if ( extension != NULL && strcmp( extension, ".pgm" ) == 0 )
- {
- // Open PGM
- FILE *f = fopen( resource, "r" );
- if ( f != NULL )
- {
- // Load from PGM
- luma_read_pgm( f, &orig_bitmap, &luma_width, &luma_height );
- fclose( f );
-
- // Remember the original size for subsequent scaling
- mlt_properties_set_data( properties, "_luma.orig_bitmap", orig_bitmap, luma_width * luma_height * 2, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "_luma.orig_width", luma_width );
- mlt_properties_set_int( properties, "_luma.orig_height", luma_height );
- }
- }
- else
- {
- // Get the factory producer service
- char *factory = mlt_properties_get( properties, "factory" );
-
- // Create the producer
- mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
- mlt_producer producer = mlt_factory_producer( profile, factory, resource );
-
- // If we have one
- if ( producer != NULL )
- {
- // Get the producer properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Ensure that we loop
- mlt_properties_set( producer_properties, "eof", "loop" );
-
- // Now pass all producer. properties on the transition down
- mlt_properties_pass( producer_properties, properties, "luma." );
-
- // We will get the alpha frame from the producer
- mlt_frame luma_frame = NULL;
-
- // Get the luma frame
- if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &luma_frame, 0 ) == 0 )
- {
- uint8_t *luma_image;
- mlt_image_format luma_format = mlt_image_yuv422;
-
- // Get image from the luma producer
- mlt_properties_set( MLT_FRAME_PROPERTIES( luma_frame ), "rescale.interp", "none" );
- mlt_frame_get_image( luma_frame, &luma_image, &luma_format, &luma_width, &luma_height, 0 );
-
- // Generate the luma map
- if ( luma_image != NULL && luma_format == mlt_image_yuv422 )
- luma_read_yuv422( luma_image, &orig_bitmap, luma_width, luma_height );
-
- // Remember the original size for subsequent scaling
- mlt_properties_set_data( properties, "_luma.orig_bitmap", orig_bitmap, luma_width * luma_height * 2, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "_luma.orig_width", luma_width );
- mlt_properties_set_int( properties, "_luma.orig_height", luma_height );
-
- // Cleanup the luma frame
- mlt_frame_close( luma_frame );
- }
-
- // Cleanup the luma producer
- mlt_producer_close( producer );
- }
- }
- }
- // Scale luma map
- luma_bitmap = mlt_pool_alloc( width * height * sizeof( uint16_t ) );
- scale_luma( luma_bitmap, width, height, orig_bitmap, luma_width, luma_height, invert * ( ( 1 << 16 ) - 1 ) );
-
- // Remember the scaled luma size to prevent unnecessary scaling
- mlt_properties_set_int( properties, "_luma.width", width );
- mlt_properties_set_int( properties, "_luma.height", height );
- mlt_properties_set_data( properties, "_luma.bitmap", luma_bitmap, width * height * 2, mlt_pool_release, NULL );
- mlt_properties_set( properties, "_luma", resource );
- mlt_properties_set_int( properties, "_luma_invert", invert );
- }
- return luma_bitmap;
-}
-
-/** Get the properly sized image from b_frame.
-*/
-
-static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **image, int *width, int *height, struct geometry_s *geometry )
-{
- int ret = 0;
- mlt_image_format format = mlt_image_yuv422;
-
- // Get the properties objects
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- uint8_t resize_alpha = mlt_properties_get_int( b_props, "resize_alpha" );
-
- // Do not scale if we are cropping - the compositing rectangle can crop the b image
- // TODO: Use the animatable w and h of the crop geometry to scale independently of crop rectangle
- if ( mlt_properties_get( properties, "crop" ) )
- {
- int real_width = get_value( b_props, "real_width", "width" );
- int real_height = get_value( b_props, "real_height", "height" );
- double input_ar = mlt_properties_get_double( b_props, "aspect_ratio" );
- double consumer_ar = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
- double background_ar = mlt_properties_get_double( b_props, "output_ratio" );
- double output_ar = background_ar != 0.0 ? background_ar : consumer_ar;
- int scaled_width = rint( ( input_ar == 0.0 ? output_ar : input_ar ) / output_ar * real_width );
- int scaled_height = real_height;
- geometry->sw = scaled_width;
- geometry->sh = scaled_height;
- }
- // Normalise aspect ratios and scale preserving aspect ratio
- else if ( mlt_properties_get_int( properties, "aligned" ) && mlt_properties_get_int( properties, "distort" ) == 0 && mlt_properties_get_int( b_props, "distort" ) == 0 && geometry->item.distort == 0 )
- {
- // Adjust b_frame pixel aspect
- int normalised_width = geometry->item.w;
- int normalised_height = geometry->item.h;
- int real_width = get_value( b_props, "real_width", "width" );
- int real_height = get_value( b_props, "real_height", "height" );
- double input_ar = mlt_properties_get_double( b_props, "aspect_ratio" );
- double consumer_ar = mlt_properties_get_double( b_props, "consumer_aspect_ratio" );
- double background_ar = mlt_properties_get_double( b_props, "output_ratio" );
- double output_ar = background_ar != 0.0 ? background_ar : consumer_ar;
- int scaled_width = rint( ( input_ar == 0.0 ? output_ar : input_ar ) / output_ar * real_width );
- int scaled_height = real_height;
-// fprintf(stderr, "%s: scaled %dx%d norm %dx%d real %dx%d output_ar %f => %f\n", __FILE__,
-// scaled_width, scaled_height, normalised_width, normalised_height, real_width, real_height,
-// background_ar, output_ar);
-
- // Now ensure that our images fit in the normalised frame
- if ( scaled_width > normalised_width )
- {
- scaled_height = rint( scaled_height * normalised_width / scaled_width );
- scaled_width = normalised_width;
- }
- if ( scaled_height > normalised_height )
- {
- scaled_width = rint( scaled_width * normalised_height / scaled_height );
- scaled_height = normalised_height;
- }
-
- // Honour the fill request - this will scale the image to fill width or height while maintaining a/r
- // ????: Shouln't this be the default behaviour?
- if ( mlt_properties_get_int( properties, "fill" ) && scaled_width > 0 && scaled_height > 0 )
- {
- if ( scaled_height < normalised_height && scaled_width * normalised_height / scaled_height <= normalised_width )
- {
- scaled_width = rint( scaled_width * normalised_height / scaled_height );
- scaled_height = normalised_height;
- }
- else if ( scaled_width < normalised_width && scaled_height * normalised_width / scaled_width < normalised_height )
- {
- scaled_height = rint( scaled_height * normalised_width / scaled_width );
- scaled_width = normalised_width;
- }
- }
-
- // Save the new scaled dimensions
- geometry->sw = scaled_width;
- geometry->sh = scaled_height;
- }
- else
- {
- geometry->sw = geometry->item.w;
- geometry->sh = geometry->item.h;
- }
-
- // We want to ensure that we bypass resize now...
- if ( resize_alpha == 0 )
- mlt_properties_set_int( b_props, "distort", mlt_properties_get_int( properties, "distort" ) );
-
- // If we're not aligned, we want a non-transparent background
- if ( mlt_properties_get_int( properties, "aligned" ) == 0 )
- mlt_properties_set_int( b_props, "resize_alpha", 255 );
-
- // Take into consideration alignment for optimisation (titles are a special case)
- if ( !mlt_properties_get_int( properties, "titles" ) &&
- mlt_properties_get( properties, "crop" ) == NULL )
- alignment_calculate( geometry );
-
- // Adjust to consumer scale
- *width = rint( geometry->sw * *width / geometry->nw );
- *height = rint( geometry->sh * *height / geometry->nh );
-// fprintf(stderr, "%s: scaled %dx%d norm %dx%d resize %dx%d\n", __FILE__,
-// geometry->sw, geometry->sh, geometry->nw, geometry->nh, *width, *height);
-
- ret = mlt_frame_get_image( b_frame, image, &format, width, height, 1 );
-
- // Set the frame back
- mlt_properties_set_int( b_props, "resize_alpha", resize_alpha );
-
- return ret && image != NULL;
-}
-
-static void crop_calculate( mlt_transition this, mlt_properties properties, struct geometry_s *result, double position )
-{
- // Initialize panning info
- result->x_src = 0;
- result->y_src = 0;
- if ( mlt_properties_get( properties, "crop" ) )
- {
- mlt_geometry crop = mlt_properties_get_data( properties, "crop_geometry", NULL );
- if ( !crop )
- {
- crop = mlt_geometry_init();
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
- int length = out - in + 1;
- double cycle = mlt_properties_get_double( properties, "cycle" );
-
- // Allow a geometry repeat cycle
- if ( cycle >= 1 )
- length = cycle;
- else if ( cycle > 0 )
- length *= cycle;
- mlt_geometry_parse( crop, mlt_properties_get( properties, "crop" ), length, result->sw, result->sh );
- mlt_properties_set_data( properties, "crop_geometry", crop, 0, (mlt_destructor)mlt_geometry_close, NULL );
- }
-
- // Repeat processing
- int length = mlt_geometry_get_length( crop );
- int mirror_off = mlt_properties_get_int( properties, "mirror_off" );
- int repeat_off = mlt_properties_get_int( properties, "repeat_off" );
- if ( !repeat_off && position >= length && length != 0 )
- {
- int section = position / length;
- position -= section * length;
- if ( !mirror_off && section % 2 == 1 )
- position = length - position;
- }
-
- // Compute the pan
- struct mlt_geometry_item_s crop_item;
- mlt_geometry_fetch( crop, &crop_item, position );
- result->x_src = rint( crop_item.x );
- result->y_src = rint( crop_item.y );
- }
-}
-
-static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s *result, mlt_frame a_frame, double position )
-{
- // Get the properties from the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Get the properties from the frame
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
-
- // Structures for geometry
- mlt_geometry start = mlt_properties_get_data( properties, "geometries", NULL );
-
- // Obtain the normalised width and height from the a_frame
- int normalised_width = mlt_properties_get_int( a_props, "normalised_width" );
- int normalised_height = mlt_properties_get_int( a_props, "normalised_height" );
-
- char *name = mlt_properties_get( properties, "_unique_id" );
- char key[ 256 ];
-
- sprintf( key, "%s.in", name );
- if ( mlt_properties_get( a_props, key ) )
- {
- sscanf( mlt_properties_get( a_props, key ), "%f,%f,%f,%f,%f,%d,%d", &result->item.x, &result->item.y, &result->item.w, &result->item.h, &result->item.mix, &result->nw, &result->nh );
- }
- else
- {
- // Now parse the geometries
- if ( start == NULL )
- {
- // Parse the transitions properties
- start = transition_parse_keys( this, normalised_width, normalised_height );
-
- // Assign to properties to ensure we get destroyed
- mlt_properties_set_data( properties, "geometries", start, 0, ( mlt_destructor )mlt_geometry_close, NULL );
- }
- else
- {
- int length = mlt_transition_get_out( this ) - mlt_transition_get_in( this ) + 1;
- double cycle = mlt_properties_get_double( properties, "cycle" );
- if ( cycle > 1 )
- length = cycle;
- else if ( cycle > 0 )
- length *= cycle;
- mlt_geometry_refresh( start, mlt_properties_get( properties, "geometry" ), length, normalised_width, normalised_height );
- }
-
- // Do the calculation
- geometry_calculate( this, result, position );
-
- // Assign normalised info
- result->nw = normalised_width;
- result->nh = normalised_height;
- }
-
- // Now parse the alignment
- result->halign = alignment_parse( mlt_properties_get( properties, "halign" ) );
- result->valign = alignment_parse( mlt_properties_get( properties, "valign" ) );
-
- crop_calculate( this, properties, result, position );
-
- return start;
-}
-
-mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_position frame_position )
-{
- // Create a frame to return
- mlt_frame b_frame = mlt_frame_init( MLT_TRANSITION_SERVICE( this ) );
-
- // Get the properties of the a frame
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
-
- // Get the properties of the b frame
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // Get the position
- int position = position_calculate( this, frame_position );
-
- // Get the unique id of the transition
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" );
- char key[ 256 ];
-
- // Destination image
- uint8_t *dest = NULL;
-
- // Get the image and dimensions
- uint8_t *image = mlt_properties_get_data( a_props, "image", NULL );
- int width = mlt_properties_get_int( a_props, "width" );
- int height = mlt_properties_get_int( a_props, "height" );
- int format = mlt_properties_get_int( a_props, "format" );
-
- // Pointers for copy operation
- uint8_t *p;
-
- // Coordinates
- int w = 0;
- int h = 0;
- int x = 0;
- int y = 0;
-
- int ss = 0;
- int ds = 0;
-
- // Will need to know region to copy
- struct geometry_s result;
-
- // Calculate the region now
- composite_calculate( this, &result, a_frame, position );
-
- // Need to scale down to actual dimensions
- x = rint( result.item.x * width / result.nw );
- y = rint( result.item.y * height / result.nh );
- w = rint( result.item.w * width / result.nw );
- h = rint( result.item.h * height / result.nh );
-
- if ( x % 2 )
- {
- x --;
- w ++;
- }
-
- // Store the key
- sprintf( key, "%s.in=%d,%d,%d,%d,%f,%d,%d", name, x, y, w, h, result.item.mix, width, height );
- mlt_properties_parse( a_props, key );
- sprintf( key, "%s.out=%d,%d,%d,%d,%f,%d,%d", name, x, y, w, h, result.item.mix, width, height );
- mlt_properties_parse( a_props, key );
-
- ds = w * 2;
- ss = width * 2;
-
- // Now we need to create a new destination image
- dest = mlt_pool_alloc( w * h * 2 );
-
- // Assign to the new frame
- mlt_properties_set_data( b_props, "image", dest, w * h * 2, mlt_pool_release, NULL );
- mlt_properties_set_int( b_props, "width", w );
- mlt_properties_set_int( b_props, "height", h );
- mlt_properties_set_int( b_props, "format", format );
-
- if ( y < 0 )
- {
- dest += ( ds * -y );
- h += y;
- y = 0;
- }
-
- if ( y + h > height )
- h -= ( y + h - height );
-
- if ( x < 0 )
- {
- dest += -x * 2;
- w += x;
- x = 0;
- }
-
- if ( w > 0 && h > 0 )
- {
- // Copy the region of the image
- p = image + y * ss + x * 2;
-
- while ( h -- )
- {
- memcpy( dest, p, w * 2 );
- dest += ds;
- p += ss;
- }
- }
-
- // Assign this position to the b frame
- mlt_frame_set_position( b_frame, frame_position );
- mlt_properties_set_int( b_props, "distort", 1 );
-
- // Return the frame
- return b_frame;
-}
-
-/** Get the image.
-*/
-
-static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the b frame from the stack
- mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
-
- // Get the transition from the a frame
- mlt_transition this = mlt_frame_pop_service( a_frame );
-
- // Get in and out
- double position = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( a_frame ) );
- int out = mlt_frame_pop_service_int( a_frame );
- int in = mlt_frame_pop_service_int( a_frame );
-
- // Get the properties from the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // TODO: clean up always_active behaviour
- if ( mlt_properties_get_int( properties, "always_active" ) )
- {
- mlt_events_block( properties, properties );
- mlt_properties_set_int( properties, "in", in );
- mlt_properties_set_int( properties, "out", out );
- mlt_events_unblock( properties, properties );
- }
-
- // This compositer is yuv422 only
- *format = mlt_image_yuv422;
-
- if ( b_frame != NULL )
- {
- // Get the properties of the a frame
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
-
- // Get the properties of the b frame
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // Structures for geometry
- struct geometry_s result;
-
- // Calculate the position
- double delta = delta_calculate( this, a_frame, position );
-
- // Get the image from the b frame
- uint8_t *image_b = NULL;
- int width_b = *width;
- int height_b = *height;
-
- // Vars for alphas
- uint8_t *alpha_a = NULL;
- uint8_t *alpha_b = NULL;
-
- // Composites always need scaling... defaulting to lowest
- const char *rescale = mlt_properties_get( a_props, "rescale.interp" );
- if ( rescale == NULL || !strcmp( rescale, "none" ) )
- rescale = "nearest";
- mlt_properties_set( a_props, "rescale.interp", rescale );
- mlt_properties_set( b_props, "rescale.interp", rescale );
-
- // Do the calculation
- // NB: Locks needed here since the properties are being modified
- mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
- composite_calculate( this, &result, a_frame, position );
- mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
-
- // Since we are the consumer of the b_frame, we must pass along these
- // consumer properties from the a_frame
- mlt_properties_set_int( b_props, "consumer_deinterlace", mlt_properties_get_int( a_props, "consumer_deinterlace" ) || mlt_properties_get_int( properties, "deinterlace" ) );
- mlt_properties_set( b_props, "consumer_deinterlace_method", mlt_properties_get( a_props, "consumer_deinterlace_method" ) );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
-
- // TODO: Dangerous/temporary optimisation - if nothing to do, then do nothing
- if ( mlt_properties_get_int( properties, "no_alpha" ) &&
- result.item.x == 0 && result.item.y == 0 && result.item.w == *width && result.item.h == *height && result.item.mix == 100 )
- {
- mlt_frame_get_image( b_frame, image, format, width, height, 1 );
- if ( !mlt_frame_is_test_card( a_frame ) )
- mlt_frame_replace_image( a_frame, *image, *format, *width, *height );
- return 0;
- }
-
- if ( a_frame == b_frame )
- {
- double aspect_ratio = mlt_frame_get_aspect_ratio( b_frame );
- get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result );
- alpha_b = mlt_frame_get_alpha_mask( b_frame );
- mlt_properties_set_double( a_props, "aspect_ratio", aspect_ratio );
- }
-
- // Get the image from the a frame
- mlt_frame_get_image( a_frame, image, format, width, height, 1 );
- alpha_a = mlt_frame_get_alpha_mask( a_frame );
-
- // Optimisation - no compositing required
- if ( result.item.mix == 0 || ( result.item.w == 0 && result.item.h == 0 ) )
- return 0;
-
- // Need to keep the width/height of the a_frame on the b_frame for titling
- if ( mlt_properties_get( a_props, "dest_width" ) == NULL )
- {
- mlt_properties_set_int( a_props, "dest_width", *width );
- mlt_properties_set_int( a_props, "dest_height", *height );
- mlt_properties_set_int( b_props, "dest_width", *width );
- mlt_properties_set_int( b_props, "dest_height", *height );
- }
- else
- {
- mlt_properties_set_int( b_props, "dest_width", mlt_properties_get_int( a_props, "dest_width" ) );
- mlt_properties_set_int( b_props, "dest_height", mlt_properties_get_int( a_props, "dest_height" ) );
- }
-
- // Special case for titling...
- if ( mlt_properties_get_int( properties, "titles" ) )
- {
- if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL )
- mlt_properties_set( b_props, "rescale.interp", "hyper" );
- width_b = mlt_properties_get_int( a_props, "dest_width" );
- height_b = mlt_properties_get_int( a_props, "dest_height" );
- }
-
- if ( *image != image_b && ( image_b != NULL || get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ) == 0 ) )
- {
- uint8_t *dest = *image;
- uint8_t *src = image_b;
- int progressive =
- mlt_properties_get_int( a_props, "consumer_deinterlace" ) ||
- mlt_properties_get_int( properties, "progressive" );
- int field;
-
- int32_t luma_softness = mlt_properties_get_double( properties, "softness" ) * ( 1 << 16 );
- uint16_t *luma_bitmap = get_luma( this, properties, width_b, height_b );
- char *operator = mlt_properties_get( properties, "operator" );
-
- alpha_b = alpha_b == NULL ? mlt_frame_get_alpha_mask( b_frame ) : alpha_b;
-
- composite_line_fn line_fn = composite_line_yuv;
-
- // Replacement and override
- if ( operator != NULL )
- {
- if ( !strcmp( operator, "or" ) )
- line_fn = composite_line_yuv_or;
- if ( !strcmp( operator, "and" ) )
- line_fn = composite_line_yuv_and;
- if ( !strcmp( operator, "xor" ) )
- line_fn = composite_line_yuv_xor;
- }
-
- // Allow the user to completely obliterate the alpha channels from both frames
- if ( mlt_properties_get( properties, "alpha_a" ) )
- memset( alpha_a, mlt_properties_get_int( properties, "alpha_a" ), *width * *height );
-
- if ( mlt_properties_get( properties, "alpha_b" ) )
- memset( alpha_b, mlt_properties_get_int( properties, "alpha_b" ), width_b * height_b );
-
- for ( field = 0; field < ( progressive ? 1 : 2 ); field++ )
- {
- // Assume lower field (0) first
- double field_position = position + field * delta;
-
- // Do the calculation if we need to
- // NB: Locks needed here since the properties are being modified
- mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
- composite_calculate( this, &result, a_frame, field_position );
- mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
-
- if ( mlt_properties_get_int( properties, "titles" ) )
- {
- result.item.w = rint( *width * ( result.item.w / result.nw ) );
- result.nw = result.item.w;
- result.item.h = rint( *height * ( result.item.h / result.nh ) );
- result.nh = *height;
- result.sw = width_b;
- result.sh = height_b;
- }
-
- // Enforce cropping
- if ( mlt_properties_get( properties, "crop" ) )
- {
- if ( result.x_src == 0 )
- width_b = width_b > result.item.w ? result.item.w : width_b;
- if ( result.y_src == 0 )
- height_b = height_b > result.item.h ? result.item.h : height_b;
- }
- else
- {
- // Otherwise, align
- alignment_calculate( &result );
- }
-
- // Composite the b_frame on the a_frame
- composite_yuv( dest, *width, *height, src, width_b, height_b, alpha_b, alpha_a, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
- }
- }
- }
- else
- {
- mlt_frame_get_image( a_frame, image, format, width, height, 1 );
- }
-
- return 0;
-}
-
-/** Composition transition processing.
-*/
-
-static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
-{
- // UGH - this is a TODO - find a more reliable means of obtaining in/out for the always_active case
- if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "always_active" ) == 0 )
- {
- mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "in" ) );
- mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "out" ) );
- mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( a_frame ), position_calculate( this, mlt_frame_get_position( a_frame ) ) );
- }
- else
- {
- mlt_properties props = mlt_properties_get_data( MLT_FRAME_PROPERTIES( b_frame ), "_producer", NULL );
- mlt_frame_push_service_int( a_frame, mlt_properties_get_int( props, "in" ) );
- mlt_frame_push_service_int( a_frame, mlt_properties_get_int( props, "out" ) );
- mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( a_frame ), mlt_properties_get_int( props, "_frame" ) - mlt_properties_get_int( props, "in" ) );
- }
-
- mlt_frame_push_service( a_frame, this );
- mlt_frame_push_frame( a_frame, b_frame );
- mlt_frame_push_get_image( a_frame, transition_get_image );
- return a_frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_transition transition_composite_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_transition this = calloc( sizeof( struct mlt_transition_s ), 1 );
- if ( this != NULL && mlt_transition_init( this, NULL ) == 0 )
- {
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- this->process = composite_process;
-
- // Default starting motion and zoom
- mlt_properties_set( properties, "start", arg != NULL ? arg : "0,0:100%x100%" );
-
- // Default factory
- mlt_properties_set( properties, "factory", "fezzik" );
-
- // Use alignment (and hence alpha of b frame)
- mlt_properties_set_int( properties, "aligned", 1 );
-
- // Inform apps and framework that this is a video only transition
- mlt_properties_set_int( properties, "_transition_type", 1 );
- }
- return this;
-}
+++ /dev/null
-/*
- * transition_composite.h -- compose one image over another using alpha channel
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _TRANSITION_COMPOSITE_H_
-#define _TRANSITION_COMPOSITE_H_
-
-#include <framework/mlt_transition.h>
-
-extern mlt_transition transition_composite_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-// Courtesy functionality - allows regionalised filtering
-extern mlt_frame composite_copy_region( mlt_transition, mlt_frame, mlt_position );
-
-#endif
+++ /dev/null
-/*
- * transition_luma.c -- a generic dissolve/wipe processor
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * Adapted from Kino Plugin Timfx, which is
- * Copyright (C) 2002 Timothy M. Shead <tshead@k-3d.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-
-/** Calculate the position for this frame.
-*/
-
-static float position_calculate( mlt_transition this, mlt_frame frame )
-{
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
-
- // Get the position of the frame
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" );
- mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name );
-
- // Now do the calcs
- return ( float )( position - in ) / ( float )( out - in + 1 );
-}
-
-/** Calculate the field delta for this frame - position between two frames.
-*/
-
-static float delta_calculate( mlt_transition this, mlt_frame frame )
-{
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
-
- // Get the position of the frame
- mlt_position position = mlt_frame_get_position( frame );
-
- // Now do the calcs
- float x = ( float )( position - in ) / ( float )( out - in + 1 );
- float y = ( float )( position + 1 - in ) / ( float )( out - in + 1 );
-
- return ( y - x ) / 2.0;
-}
-
-static inline int dissolve_yuv( mlt_frame this, mlt_frame that, float weight, int width, int height )
-{
- int ret = 0;
- int width_src = width, height_src = height;
- mlt_image_format format = mlt_image_yuv422;
- uint8_t *p_src, *p_dest;
- uint8_t *p, *q;
- uint8_t *limit;
- uint8_t *alpha_src;
- uint8_t *alpha_dst;
-
- int32_t weigh = weight * ( 1 << 16 );
- int32_t weigh_complement = ( 1 - weight ) * ( 1 << 16 );
-
- if ( mlt_properties_get( &this->parent, "distort" ) )
- mlt_properties_set( &that->parent, "distort", mlt_properties_get( &this->parent, "distort" ) );
- mlt_properties_set_int( &that->parent, "consumer_deinterlace", mlt_properties_get_int( &this->parent, "consumer_deinterlace" ) );
- mlt_frame_get_image( this, &p_dest, &format, &width, &height, 1 );
- alpha_dst = mlt_frame_get_alpha_mask( this );
- mlt_frame_get_image( that, &p_src, &format, &width_src, &height_src, 0 );
- alpha_src = mlt_frame_get_alpha_mask( that );
-
- // Pick the lesser of two evils ;-)
- width_src = width_src > width ? width : width_src;
- height_src = height_src > height ? height : height_src;
-
- p = p_dest;
- q = alpha_dst;
- limit = p_dest + height_src * width_src * 2;
-
- while ( p < limit )
- {
- *p_dest++ = ( *p_src++ * weigh + *p++ * weigh_complement ) >> 16;
- *p_dest++ = ( *p_src++ * weigh + *p++ * weigh_complement ) >> 16;
- *alpha_dst++ = ( *alpha_src++ * weigh + *q++ * weigh_complement ) >> 16;
- }
-
- return ret;
-}
-
-// image processing functions
-
-static inline int32_t smoothstep( int32_t edge1, int32_t edge2, uint32_t a )
-{
- if ( a < edge1 )
- return 0;
-
- if ( a >= edge2 )
- return 0x10000;
-
- a = ( ( a - edge1 ) << 16 ) / ( edge2 - edge1 );
-
- return ( ( ( a * a ) >> 16 ) * ( ( 3 << 16 ) - ( 2 * a ) ) ) >> 16;
-}
-
-/** powerful stuff
-
- \param field_order -1 = progressive, 0 = lower field first, 1 = top field first
-*/
-static void luma_composite( mlt_frame a_frame, mlt_frame b_frame, int luma_width, int luma_height,
- uint16_t *luma_bitmap, float pos, float frame_delta, float softness, int field_order,
- int *width, int *height )
-{
- int width_src = *width, height_src = *height;
- int width_dest = *width, height_dest = *height;
- mlt_image_format format_src = mlt_image_yuv422, format_dest = mlt_image_yuv422;
- uint8_t *p_src, *p_dest;
- int i, j;
- int stride_src;
- int stride_dest;
- uint16_t weight = 0;
-
- format_src = mlt_image_yuv422;
- format_dest = mlt_image_yuv422;
-
- if ( mlt_properties_get( &a_frame->parent, "distort" ) )
- mlt_properties_set( &b_frame->parent, "distort", mlt_properties_get( &a_frame->parent, "distort" ) );
- mlt_properties_set_int( &b_frame->parent, "consumer_deinterlace", mlt_properties_get_int( &a_frame->parent, "consumer_deinterlace" ) );
- mlt_frame_get_image( a_frame, &p_dest, &format_dest, &width_dest, &height_dest, 1 );
- mlt_frame_get_image( b_frame, &p_src, &format_src, &width_src, &height_src, 0 );
-
- if ( *width == 0 || *height == 0 )
- return;
-
- // Pick the lesser of two evils ;-)
- width_src = width_src > width_dest ? width_dest : width_src;
- height_src = height_src > height_dest ? height_dest : height_src;
-
- stride_src = width_src * 2;
- stride_dest = width_dest * 2;
-
- // Offset the position based on which field we're looking at ...
- int32_t field_pos[ 2 ];
- field_pos[ 0 ] = ( pos + ( ( field_order == 0 ? 1 : 0 ) * frame_delta * 0.5 ) ) * ( 1 << 16 ) * ( 1.0 + softness );
- field_pos[ 1 ] = ( pos + ( ( field_order == 0 ? 0 : 1 ) * frame_delta * 0.5 ) ) * ( 1 << 16 ) * ( 1.0 + softness );
-
- register uint8_t *p;
- register uint8_t *q;
- register uint8_t *o;
- uint16_t *l;
-
- uint32_t value;
-
- int32_t x_diff = ( luma_width << 16 ) / *width;
- int32_t y_diff = ( luma_height << 16 ) / *height;
- int32_t x_offset = 0;
- int32_t y_offset = 0;
- uint8_t *p_row;
- uint8_t *q_row;
-
- int32_t i_softness = softness * ( 1 << 16 );
-
- int field_count = field_order < 0 ? 1 : 2;
- int field_stride_src = field_count * stride_src;
- int field_stride_dest = field_count * stride_dest;
- int field = 0;
-
- // composite using luma map
- while ( field < field_count )
- {
- p_row = p_src + field * stride_src;
- q_row = p_dest + field * stride_dest;
- y_offset = field << 16;
- i = field;
-
- while ( i < height_src )
- {
- p = p_row;
- q = q_row;
- o = q;
- l = luma_bitmap + ( y_offset >> 16 ) * ( luma_width * field_count );
- x_offset = 0;
- j = width_src;
-
- while( j -- )
- {
- weight = l[ x_offset >> 16 ];
- value = smoothstep( weight, i_softness + weight, field_pos[ field ] );
- *o ++ = ( *p ++ * value + *q++ * ( ( 1 << 16 ) - value ) ) >> 16;
- *o ++ = ( *p ++ * value + *q++ * ( ( 1 << 16 ) - value ) ) >> 16;
- x_offset += x_diff;
- }
-
- y_offset += y_diff;
- i += field_count;
- p_row += field_stride_src;
- q_row += field_stride_dest;
- }
-
- field ++;
- }
-}
-
-/** Load the luma map from PGM stream.
-*/
-
-static void luma_read_pgm( FILE *f, uint16_t **map, int *width, int *height )
-{
- uint8_t *data = NULL;
- while (1)
- {
- char line[128];
- char comment[128];
- int i = 2;
- int maxval;
- int bpp;
- uint16_t *p;
-
- line[127] = '\0';
-
- // get the magic code
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- if ( line[0] != 'P' || line[1] != '5' )
- break;
-
- // skip white space and see if a new line must be fetched
- for ( i = 2; i < 127 && line[i] != '\0' && isspace( line[i] ); i++ );
- if ( ( line[i] == '\0' || line[i] == '#' ) && fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // get the dimensions
- if ( line[0] == 'P' )
- i = sscanf( line, "P5 %d %d %d", width, height, &maxval );
- else
- i = sscanf( line, "%d %d %d", width, height, &maxval );
-
- // get the height value, if not yet
- if ( i < 2 )
- {
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- i = sscanf( line, "%d", height );
- if ( i == 0 )
- break;
- else
- i = 2;
- }
-
- // get the maximum gray value, if not yet
- if ( i < 3 )
- {
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- // skip comments
- while ( sscanf( line, " #%s", comment ) > 0 )
- if ( fgets( line, 127, f ) == NULL )
- break;
-
- i = sscanf( line, "%d", &maxval );
- if ( i == 0 )
- break;
- }
-
- // determine if this is one or two bytes per pixel
- bpp = maxval > 255 ? 2 : 1;
-
- // allocate temporary storage for the raw data
- data = mlt_pool_alloc( *width * *height * bpp );
- if ( data == NULL )
- break;
-
- // read the raw data
- if ( fread( data, *width * *height * bpp, 1, f ) != 1 )
- break;
-
- // allocate the luma bitmap
- *map = p = (uint16_t*)mlt_pool_alloc( *width * *height * sizeof( uint16_t ) );
- if ( *map == NULL )
- break;
-
- // proces the raw data into the luma bitmap
- for ( i = 0; i < *width * *height * bpp; i += bpp )
- {
- if ( bpp == 1 )
- *p++ = data[ i ] << 8;
- else
- *p++ = ( data[ i ] << 8 ) + data[ i+1 ];
- }
-
- break;
- }
-
- if ( data != NULL )
- mlt_pool_release( data );
-}
-
-/** Generate a luma map from an RGB image.
-*/
-
-static void luma_read_yuv422( uint8_t *image, uint16_t **map, int width, int height )
-{
- int i;
- int size = width * height * 2;
-
- // allocate the luma bitmap
- uint16_t *p = *map = ( uint16_t* )mlt_pool_alloc( width * height * sizeof( uint16_t ) );
- if ( *map == NULL )
- return;
-
- // proces the image data into the luma bitmap
- for ( i = 0; i < size; i += 2 )
- *p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219
-}
-
-/** Generate a luma map from a YUV image.
-*/
-static void luma_read_rgb24( uint8_t *image, uint16_t **map, int width, int height )
-{
-}
-
-/** Get the image.
-*/
-
-static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the b frame from the stack
- mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
-
- // Get the transition object
- mlt_transition transition = mlt_frame_pop_service( a_frame );
-
- // Get the properties of the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
-
- // Get the properties of the a frame
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
-
- // Get the properties of the b frame
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // This compositer is yuv422 only
- *format = mlt_image_yuv422;
-
- // The cached luma map information
- int luma_width = mlt_properties_get_int( properties, "width" );
- int luma_height = mlt_properties_get_int( properties, "height" );
- uint16_t *luma_bitmap = mlt_properties_get_data( properties, "bitmap", NULL );
- char *current_resource = mlt_properties_get( properties, "_resource" );
-
- // If the filename property changed, reload the map
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Correct width/height if not specified
- if ( luma_width == 0 || luma_height == 0 )
- {
- luma_width = mlt_properties_get_int( a_props, "width" );
- luma_height = mlt_properties_get_int( a_props, "height" );
- }
-
- if ( resource != current_resource )
- {
- char temp[ 512 ];
- char *extension = strrchr( resource, '.' );
-
- if ( strchr( resource, '%' ) )
- {
- FILE *test;
- sprintf( temp, "%s/lumas/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( resource, '%' ) + 1 );
- test = fopen( temp, "r" );
- if ( test == NULL )
- strcat( temp, ".png" );
- else
- fclose( test );
- resource = temp;
- extension = strrchr( resource, '.' );
- }
-
- // See if it is a PGM
- if ( extension != NULL && strcmp( extension, ".pgm" ) == 0 )
- {
- // Open PGM
- FILE *f = fopen( resource, "r" );
- if ( f != NULL )
- {
- // Load from PGM
- luma_read_pgm( f, &luma_bitmap, &luma_width, &luma_height );
- fclose( f );
-
- // Set the transition properties
- mlt_properties_set_int( properties, "width", luma_width );
- mlt_properties_set_int( properties, "height", luma_height );
- mlt_properties_set( properties, "_resource", resource );
- mlt_properties_set_data( properties, "bitmap", luma_bitmap, luma_width * luma_height * 2, mlt_pool_release, NULL );
- }
- }
- else if (!*resource)
- {
- luma_bitmap = NULL;
- mlt_properties_set( properties, "_resource", NULL );
- mlt_properties_set_data( properties, "bitmap", luma_bitmap, 0, mlt_pool_release, NULL );
- }
- else
- {
- // Get the factory producer service
- char *factory = mlt_properties_get( properties, "factory" );
-
- // Create the producer
- mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) );
- mlt_producer producer = mlt_factory_producer( profile, factory, resource );
-
- // If we have one
- if ( producer != NULL )
- {
- // Get the producer properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Ensure that we loop
- mlt_properties_set( producer_properties, "eof", "loop" );
-
- // Now pass all producer. properties on the transition down
- mlt_properties_pass( producer_properties, properties, "producer." );
-
- // We will get the alpha frame from the producer
- mlt_frame luma_frame = NULL;
-
- // Get the luma frame
- if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &luma_frame, 0 ) == 0 )
- {
- uint8_t *luma_image = NULL;
- mlt_image_format luma_format = mlt_image_yuv422;
-
- // Get image from the luma producer
- mlt_properties_set( MLT_FRAME_PROPERTIES( luma_frame ), "rescale.interp", "nearest" );
- mlt_frame_get_image( luma_frame, &luma_image, &luma_format, &luma_width, &luma_height, 0 );
-
- // Generate the luma map
- if ( luma_image != NULL && luma_format == mlt_image_yuv422 )
- luma_read_yuv422( luma_image, &luma_bitmap, luma_width, luma_height );
-
- else if ( luma_image != NULL && luma_format == mlt_image_rgb24 )
- luma_read_rgb24( luma_image, &luma_bitmap, luma_width, luma_height );
-
- // Set the transition properties
- mlt_properties_set_int( properties, "width", luma_width );
- mlt_properties_set_int( properties, "height", luma_height );
- mlt_properties_set( properties, "_resource", resource);
- mlt_properties_set_data( properties, "bitmap", luma_bitmap, luma_width * luma_height * 2, mlt_pool_release, NULL );
-
- // Cleanup the luma frame
- mlt_frame_close( luma_frame );
- }
-
- // Cleanup the luma producer
- mlt_producer_close( producer );
- }
- }
- }
-
- // Arbitrary composite defaults
- float mix = position_calculate( transition, a_frame );
- float frame_delta = delta_calculate( transition, a_frame );
-
- float luma_softness = mlt_properties_get_double( properties, "softness" );
- int progressive =
- mlt_properties_get_int( a_props, "consumer_deinterlace" ) ||
- mlt_properties_get_int( properties, "progressive" ) ||
- mlt_properties_get_int( b_props, "luma.progressive" );
- int top_field_first = mlt_properties_get_int( b_props, "top_field_first" );
- int reverse = mlt_properties_get_int( properties, "reverse" );
- int invert = mlt_properties_get_int( properties, "invert" );
-
- if ( mlt_properties_get( a_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) )
- mlt_properties_set( a_props, "rescale.interp", "nearest" );
-
- // Since we are the consumer of the b_frame, we must pass along this
- // consumer property from the a_frame
- if ( mlt_properties_get_double( a_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
-
- // Honour the reverse here
- if ( mix >= 1.0 )
- mix -= floor( mix );
-
- mix = reverse || invert ? 1 - mix : mix;
- frame_delta *= reverse || invert ? -1.0 : 1.0;
-
- // Ensure we get scaling on the b_frame
- if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( b_props, "rescale.interp" ), "none" ) )
- mlt_properties_set( b_props, "rescale.interp", "nearest" );
-
- if ( mlt_properties_get( properties, "fixed" ) )
- mix = mlt_properties_get_double( properties, "fixed" );
-
- if ( luma_width > 0 && luma_height > 0 && luma_bitmap != NULL )
- // Composite the frames using a luma map
- luma_composite( !invert ? a_frame : b_frame, !invert ? b_frame : a_frame, luma_width, luma_height, luma_bitmap, mix, frame_delta,
- luma_softness, progressive ? -1 : top_field_first, width, height );
- else
- // Dissolve the frames using the time offset for mix value
- dissolve_yuv( a_frame, b_frame, mix, *width, *height );
-
- // Extract the a_frame image info
- *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" );
- *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" );
- *image = mlt_properties_get_data( !invert ? a_props : b_props, "image", NULL );
-
- return 0;
-}
-
-
-/** Luma transition processing.
-*/
-
-static mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
-{
- // Get a unique name to store the frame position
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
-
- // Assign the current position to the name
- mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) );
-
- // Push the transition on to the frame
- mlt_frame_push_service( a_frame, transition );
-
- // Push the b_frame on to the stack
- mlt_frame_push_frame( a_frame, b_frame );
-
- // Push the transition method
- mlt_frame_push_get_image( a_frame, transition_get_image );
-
- return a_frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_transition transition_luma_init( mlt_profile profile, mlt_service_type type, const char *id, char *lumafile )
-{
- mlt_transition transition = mlt_transition_new( );
- if ( transition != NULL )
- {
- // Set the methods
- transition->process = transition_process;
-
- // Default factory
- mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "factory", "fezzik" );
-
- // Set the main property
- mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "resource", lumafile );
-
- // Inform apps and framework that this is a video only transition
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 );
-
- return transition;
- }
- return NULL;
-}
+++ /dev/null
-/*
- * transition_mix.c -- mix two audio streams
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_transition.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-
-/** Get the audio.
-*/
-
-static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the b frame from the stack
- mlt_frame b_frame = mlt_frame_pop_audio( frame );
-
- // Get the effect
- mlt_transition effect = mlt_frame_pop_audio( frame );
-
- // Get the properties of the b frame
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( effect ), "combine" ) == 0 )
- {
- double mix_start = 0.5, mix_end = 0.5;
- if ( mlt_properties_get( b_props, "audio.previous_mix" ) != NULL )
- mix_start = mlt_properties_get_double( b_props, "audio.previous_mix" );
- if ( mlt_properties_get( b_props, "audio.mix" ) != NULL )
- mix_end = mlt_properties_get_double( b_props, "audio.mix" );
- if ( mlt_properties_get_int( b_props, "audio.reverse" ) )
- {
- mix_start = 1 - mix_start;
- mix_end = 1 - mix_end;
- }
-
- mlt_frame_mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples );
- }
- else
- {
- mlt_frame_combine_audio( frame, b_frame, buffer, format, frequency, channels, samples );
- }
-
- return 0;
-}
-
-
-/** Mix transition processing.
-*/
-
-static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
-{
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // Only if mix is specified, otherwise a producer may set the mix
- if ( mlt_properties_get( properties, "start" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_properties props = mlt_properties_get_data( MLT_FRAME_PROPERTIES( b_frame ), "_producer", NULL );
- int always_active = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "always_active" );
- mlt_position in = !always_active ? mlt_transition_get_in( this ) : mlt_properties_get_int( props, "in" );
- mlt_position out = !always_active ? mlt_transition_get_out( this ) : mlt_properties_get_int( props, "out" );
- int length = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( this ), "length" );
- mlt_position time = !always_active ? mlt_frame_get_position( b_frame ) : mlt_properties_get_int( props, "_frame" );
- double mix = ( double )( time - in ) / ( double )( out - in + 1 );
-
- // TODO: Check the logic here - shouldn't we be computing current and next mixing levels in all cases?
- if ( length == 0 )
- {
- // If there is an end mix level adjust mix to the range
- if ( mlt_properties_get( properties, "end" ) != NULL )
- {
- double start = mlt_properties_get_double( properties, "start" );
- double end = mlt_properties_get_double( properties, "end" );
- mix = start + ( end - start ) * mix;
- }
- // A negative means total crossfade (uses position)
- else if ( mlt_properties_get_double( properties, "start" ) >= 0 )
- {
- // Otherwise, start/constructor is a constant mix level
- mix = mlt_properties_get_double( properties, "start" );
- }
-
- // Finally, set the mix property on the frame
- mlt_properties_set_double( b_props, "audio.mix", mix );
-
- // Initialise transition previous mix value to prevent an inadvertant jump from 0
- mlt_position last_position = mlt_properties_get_position( properties, "_last_position" );
- mlt_position current_position = mlt_frame_get_position( b_frame );
- if ( mlt_properties_get( properties, "_previous_mix" ) == NULL
- || current_position != last_position + 1 )
- mlt_properties_set_double( properties, "_previous_mix", mix );
-
- // Tell b frame what the previous mix level was
- mlt_properties_set_double( b_props, "audio.previous_mix", mlt_properties_get_double( properties, "_previous_mix" ) );
-
- // Save the current mix level for the next iteration
- mlt_properties_set_double( properties, "_previous_mix", mlt_properties_get_double( b_props, "audio.mix" ) );
-
- mlt_properties_set_double( b_props, "audio.reverse", mlt_properties_get_double( properties, "reverse" ) );
- }
- else
- {
- double level = mlt_properties_get_double( properties, "start" );
- double mix_start = level;
- double mix_end = mix_start;
- double mix_increment = 1.0 / length;
- if ( time - in < length )
- {
- mix_start = mix_start * ( ( double )( time - in ) / length );
- mix_end = mix_start + mix_increment;
- }
- else if ( time > out - length )
- {
- mix_end = mix_start * ( ( double )( out - time - in ) / length );
- mix_start = mix_end - mix_increment;
- }
-
- mix_start = mix_start < 0 ? 0 : mix_start > level ? level : mix_start;
- mix_end = mix_end < 0 ? 0 : mix_end > level ? level : mix_end;
- mlt_properties_set_double( b_props, "audio.previous_mix", mix_start );
- mlt_properties_set_double( b_props, "audio.mix", mix_end );
- }
- }
-
- // Override the get_audio method
- mlt_frame_push_audio( a_frame, this );
- mlt_frame_push_audio( a_frame, b_frame );
- mlt_frame_push_audio( a_frame, transition_get_audio );
-
- return a_frame;
-}
-
-/** Constructor for the transition.
-*/
-
-mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_transition this = calloc( sizeof( struct mlt_transition_s ), 1 );
- if ( this != NULL && mlt_transition_init( this, NULL ) == 0 )
- {
- this->process = transition_process;
- if ( arg != NULL )
- mlt_properties_set_double( MLT_TRANSITION_PROPERTIES( this ), "start", atof( arg ) );
- // Inform apps and framework that this is an audio only transition
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( this ), "_transition_type", 2 );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * transition_region.c -- region transition
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "transition_region.h"
-#include "transition_composite.h"
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static int create_instance( mlt_transition this, char *name, char *value, int count )
-{
- // Return from this function
- int error = 0;
-
- // Duplicate the value
- char *type = strdup( value );
-
- // Pointer to filter argument
- char *arg = type == NULL ? NULL : strchr( type, ':' );
-
- // New filter being created
- mlt_filter filter = NULL;
-
- // Cleanup type and arg
- if ( arg != NULL )
- *arg ++ = '\0';
-
- // Create the filter
- mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
- filter = mlt_factory_filter( profile, type, arg );
-
- // If we have a filter, then initialise and store it
- if ( filter != NULL )
- {
- // Properties of this
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // String to hold the property name
- char id[ 256 ];
-
- // String to hold the passdown key
- char key[ 256 ];
-
- // Construct id
- sprintf( id, "_filter_%d", count );
-
- // Counstruct key
- sprintf( key, "%s.", name );
-
- // Just in case, let's assume that the filter here has a composite
- //mlt_properties_set( MLT_FILTER_PROPERTIES( filter ), "composite.geometry", "0%,0%:100%x100%" );
- //mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "composite.fill", 1 );
-
- // Pass all the key properties on the filter down
- mlt_properties_pass( MLT_FILTER_PROPERTIES( filter ), properties, key );
-
- // Ensure that filter is assigned
- mlt_properties_set_data( properties, id, filter, 0, ( mlt_destructor )mlt_filter_close, NULL );
- }
- else
- {
- // Indicate that an error has occurred
- error = 1;
- }
-
- // Cleanup
- free( type );
-
- // Return error condition
- return error;
-}
-
-static uint8_t *filter_get_alpha_mask( mlt_frame this )
-{
- uint8_t *alpha = NULL;
-
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the shape frame
- mlt_frame shape_frame = mlt_properties_get_data( properties, "shape_frame", NULL );
-
- // Get the width and height of the image
- int region_width = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "width" );
- int region_height = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "height" );
- uint8_t *image = NULL;
- mlt_image_format format = mlt_image_yuv422;
-
- // Get the shape image to trigger alpha creation
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( shape_frame ), "distort", 1 );
- mlt_frame_get_image( shape_frame, &image, &format, ®ion_width, ®ion_height, 0 );
-
- alpha = mlt_frame_get_alpha_mask( shape_frame );
-
- // Generate from the Y component of the image if no alpha available
- if ( alpha == NULL )
- {
- int size = region_width * region_height;
- uint8_t *p = mlt_pool_alloc( size );
- alpha = p;
- while ( size -- )
- {
- *p ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 );
- image ++;
- }
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", alpha, region_width * region_height, mlt_pool_release, NULL );
- }
- else
- {
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "alpha", alpha, region_width * region_height, NULL, NULL );
- }
-
- this->get_alpha_mask = NULL;
-
- return alpha;
-}
-
-/** Do it :-).
-*/
-
-static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Error we will return
- int error = 0;
-
- // We will get the 'b frame' from the frame stack
- mlt_frame b_frame = mlt_frame_pop_frame( frame );
-
- // Get the watermark transition object
- mlt_transition this = mlt_frame_pop_service( frame );
-
- // Get the properties of the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Get the composite from the transition
- mlt_transition composite = mlt_properties_get_data( properties, "composite", NULL );
-
- // Look for the first filter
- mlt_filter filter = mlt_properties_get_data( properties, "_filter_0", NULL );
-
- // Get the unique id of the filter (used to reacquire the producer position)
- char *name = mlt_properties_get( properties, "_unique_id" );
-
- // Get the original producer position
- mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name );
-
- // Create a composite if we don't have one
- if ( composite == NULL )
- {
- // Create composite via the factory
- mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
- composite = mlt_factory_transition( profile, "composite", NULL );
-
- // If we have one
- if ( composite != NULL )
- {
- // Get the properties
- mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite );
-
- // We want to ensure that we don't get a wobble...
- //mlt_properties_set_int( composite_properties, "distort", 1 );
- mlt_properties_set_int( composite_properties, "progressive", 1 );
-
- // Pass all the composite. properties on the transition down
- mlt_properties_pass( composite_properties, properties, "composite." );
-
- // Register the composite for reuse/destruction
- mlt_properties_set_data( properties, "composite", composite, 0, ( mlt_destructor )mlt_transition_close, NULL );
- }
- }
- else
- {
- // Pass all current properties down
- mlt_properties composite_properties = MLT_TRANSITION_PROPERTIES( composite );
- mlt_properties_pass( composite_properties, properties, "composite." );
- }
-
- // Create filters
- if ( filter == NULL )
- {
- // Loop Variable
- int i = 0;
-
- // Number of filters created
- int count = 0;
-
- // Loop for all properties
- for ( i = 0; i < mlt_properties_count( properties ); i ++ )
- {
- // Get the name of this property
- char *name = mlt_properties_get_name( properties, i );
-
- // If the name does not contain a . and matches filter
- if ( strchr( name, '.' ) == NULL && !strncmp( name, "filter", 6 ) )
- {
- // Get the filter constructor
- char *value = mlt_properties_get_value( properties, i );
-
- // Create an instance
- if ( create_instance( this, name, value, count ) == 0 )
- count ++;
- }
- }
-
- // Look for the first filter again
- filter = mlt_properties_get_data( properties, "_filter_0", NULL );
- }
- else
- {
- // Pass all properties down
- mlt_filter temp = NULL;
-
- // Loop Variable
- int i = 0;
-
- // Number of filters found
- int count = 0;
-
- // Loop for all properties
- for ( i = 0; i < mlt_properties_count( properties ); i ++ )
- {
- // Get the name of this property
- char *name = mlt_properties_get_name( properties, i );
-
- // If the name does not contain a . and matches filter
- if ( strchr( name, '.' ) == NULL && !strncmp( name, "filter", 6 ) )
- {
- // Strings to hold the id and pass down key
- char id[ 256 ];
- char key[ 256 ];
-
- // Construct id and key
- sprintf( id, "_filter_%d", count );
- sprintf( key, "%s.", name );
-
- // Get the filter
- temp = mlt_properties_get_data( properties, id, NULL );
-
- if ( temp != NULL )
- {
- mlt_properties_pass( MLT_FILTER_PROPERTIES( temp ), properties, key );
- count ++;
- }
- }
- }
- }
-
- // Get the image
- error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- // Only continue if we have both filter and composite
- if ( composite != NULL )
- {
- // Get the resource of this filter (could be a shape [rectangle/circle] or an alpha provider of choice
- const char *resource = mlt_properties_get( properties, "resource" );
-
- // Get the old resource in case it's changed
- char *old_resource = mlt_properties_get( properties, "_old_resource" );
-
- // String to hold the filter to query on
- char id[ 256 ];
-
- // Index to hold the count
- int i = 0;
-
- // We will get the 'b frame' from the composite only if it's NULL
- if ( b_frame == NULL )
- {
- // Copy the region
- b_frame = composite_copy_region( composite, frame, position );
-
- // Ensure a destructor
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
-
- // Set the position of the b_frame
- mlt_frame_set_position( b_frame, position );
-
- // Make sure the filter is in the correct position
- while ( filter != NULL )
- {
- // Stack this filter
- if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "off" ) == 0 )
- mlt_filter_process( filter, b_frame );
-
- // Generate the key for the next
- sprintf( id, "_filter_%d", ++ i );
-
- // Get the next filter
- filter = mlt_properties_get_data( properties, id, NULL );
- }
-
- // Allow filters to be attached to a region filter
- filter = mlt_properties_get_data( properties, "_region_filter", NULL );
- if ( filter != NULL )
- mlt_service_apply_filters( MLT_FILTER_SERVICE( filter ), b_frame, 0 );
-
- // Hmm - this is probably going to go wrong....
- mlt_frame_set_position( frame, position );
-
- // Get the b frame and process with composite if successful
- mlt_transition_process( composite, frame, b_frame );
-
- // If we have a shape producer copy the alpha mask from the shape frame to the b_frame
- if ( strcmp( resource, "rectangle" ) != 0 )
- {
- // Get the producer from the transition
- mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // If We have no producer then create one
- if ( producer == NULL || ( old_resource != NULL && strcmp( resource, old_resource ) ) )
- {
- // Get the factory producer service
- char *factory = mlt_properties_get( properties, "factory" );
-
- // Store the old resource
- mlt_properties_set( properties, "_old_resource", resource );
-
- // Special case circle resource
- if ( strcmp( resource, "circle" ) == 0 )
- resource = "pixbuf:<svg width='100' height='100'><circle cx='50' cy='50' r='50' fill='black'/></svg>";
-
- // Create the producer
- mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
- producer = mlt_factory_producer( profile, factory, resource );
-
- // If we have one
- if ( producer != NULL )
- {
- // Get the producer properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Ensure that we loop
- mlt_properties_set( producer_properties, "eof", "loop" );
-
- // Now pass all producer. properties on the transition down
- mlt_properties_pass( producer_properties, properties, "producer." );
-
- // Register the producer for reuse/destruction
- mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
- }
- }
-
- // Now use the shape producer
- if ( producer != NULL )
- {
- // We will get the alpha frame from the producer
- mlt_frame shape_frame = NULL;
-
- // Make sure the producer is in the correct position
- mlt_producer_seek( producer, position );
-
- // Get the shape frame
- if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &shape_frame, 0 ) == 0 )
- {
- // Ensure that the shape frame will be closed
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( b_frame ), "shape_frame", shape_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
-
- // Specify the callback for evaluation
- b_frame->get_alpha_mask = filter_get_alpha_mask;
- }
- }
- }
-
- // Get the image
- error = mlt_frame_get_image( frame, image, format, width, height, 0 );
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( a_frame );
-
- // Get a unique name to store the frame position
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" );
-
- // Assign the current position to the name
- mlt_properties_set_position( properties, name, mlt_frame_get_position( a_frame ) );
-
- // Push the transition on to the frame
- mlt_frame_push_service( a_frame, this );
-
- // Push the b_frame on to the stack
- mlt_frame_push_frame( a_frame, b_frame );
-
- // Push the transition method
- mlt_frame_push_get_image( a_frame, transition_get_image );
-
- // Return the frame
- return a_frame;
-}
-
-/** Constructor for the transition.
-*/
-
-mlt_transition transition_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create a new transition
- mlt_transition this = mlt_transition_new( );
-
- // Further initialisation
- if ( this != NULL )
- {
- // Get the properties from the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Assign the transition process method
- this->process = transition_process;
-
- // Default factory
- mlt_properties_set( properties, "factory", "fezzik" );
-
- // Resource defines the shape of the region
- mlt_properties_set( properties, "resource", arg == NULL ? "rectangle" : arg );
-
- // Inform apps and framework that this is a video only transition
- mlt_properties_set_int( properties, "_transition_type", 1 );
- }
-
- // Return the transition
- return this;
-}
-
+++ /dev/null
-/*
- * transition_region.h -- region transition
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _TRANSITION_REGION_H_
-#define _TRANSITION_REGION_H_
-
-#include <framework/mlt_transition.h>
-
-extern mlt_transition transition_region_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-#endif
+++ /dev/null
-# This properties file describes the fx available to the data_send and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-#
-# The titles filter definition
-#
-
-titles=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,70%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-
-#
-# The top titles filter definition
-#
-
-top-titles=region
-.description=Top Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,5%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.halign=centre
-.filter[1].composite.titles=1
-
-#
-# OK - Silly example...
-#
-
-tickertape=region
-.description=Tickertape
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0%,93%:100%x7%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=100%,0%:300%x100%:100;-1=-300%,0%:300%x100%:100
-.filter[1].producer.font=San 32
-.filter[1].composite.titles=1
-
-#
-# ETV Location
-#
-
-location=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,80:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=-100%,0%:100%x100%:100;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:0;24=0%,0%:100%x100%:0;49=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=center
-
-courtesy=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,115:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=-100%,0%:100%x100%:0;12=-100%,0%:100%x100%:0;37=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=ETV Exclusive
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:0;37=0%,0%:100%x100%:0;61=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=right
-
-exclusive=region
-.description=Exclusive
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,115:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=ETV Exclusive
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=right
-
-file_shot=region
-.description=Titles
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=590,160:80x25
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=File Shot
-.filter[1].producer.font=San 18
-.filter[1].composite.geometry=0%,0%:100%x100%:15;25=0%,0%:100%x100%:100
-.filter[1].composite.titles=0
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-special=region
-.description=Titles
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=465,375:255x35
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=100%,0%:100%x100%:0;49=100%,0%:100%x100%:0;74=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Special
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=100%,0%:100%x100%:0;49=100%,0%:100%x100%:0;74=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-ticker=region
-.description=Tickertape
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0,500:722x75
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Ticker - provided for reference
-.filter[1].composite.geometry=0%,0%:100%x100%:100
-.filter[1].composite.titles=0
-.filter[1].producer.font=San 24
-.filter[1].composite.halign=centre
-.filter[1].composite.titles=1
-.filter[1].composite.valign=centre
-
-super=region
-.description=Transcription
-.properties.0=filter[1].producer.markup
-.properties.1=filter[2].producer.markup
-.properties.align=filter[1].composite.valign
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.properties.length[2]=filter[2].composite.out
-.period=2
-.composite.geometry=0,410:720x90
-.filter[0]=watermark
-.filter[0].resource=colour:0xbbbbbb00
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[0].composite.luma=%luma18.pgm
-.filter[0].composite.out=25
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=
-.filter[1].producer.font=San 32
-.filter[1].producer.fgcolour=0x6c0101ff
-.filter[1].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=top
-.filter[2]=watermark
-.filter[2].resource=pango:
-.filter[2].producer.markup=
-.filter[2].producer.font=San 32
-.filter[2].producer.fgcolour=0x6c0101ff
-.filter[2].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[2].composite.titles=1
-.filter[2].composite.halign=centre
-.filter[2].composite.valign=bottom
-
-obscure=region
-.description=Obscure
-.properties.geometry=composite.geometry
-.properties.resource=resource
-.properties.length[0]=composite.out
-.composite.geometry=
-.resource=rectangle
-.composite.refresh=1
-.filter[0]=obscure
-.filter[0].start=0,0:100%x100%
-
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltdgraft$(LIBSUF)
-
-OBJS = factory.o \
- filter_telecide.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_telecide_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "telecide", filter_telecide_init );
-}
+++ /dev/null
-/*
- * filter_telecide.c -- Donald Graft's Inverse Telecine Filter
- * Copyright (C) 2003 Donald A. Graft
- * Copyright (C) 2008 Dan Dennedy <dan@dennedy.org>
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-//#define DEBUG_PATTERN_GUIDANCE
-
-#define MAX_CYCLE 6
-#define BLKSIZE 24
-#define BLKSIZE_TIMES2 (2 * BLKSIZE)
-#define GUIDE_32 1
-#define GUIDE_22 2
-#define GUIDE_32322 3
-#define AHEAD 0
-#define BEHIND 1
-#define POST_METRICS 1
-#define POST_FULL 2
-#define POST_FULL_MAP 3
-#define POST_FULL_NOMATCH 4
-#define POST_FULL_NOMATCH_MAP 5
-#define CACHE_SIZE 100000
-#define P 0
-#define C 1
-#define N 2
-#define PBLOCK 3
-#define CBLOCK 4
-
-#define NO_BACK 0
-#define BACK_ON_COMBED 1
-#define ALWAYS_BACK 2
-
-struct CACHE_ENTRY
-{
- unsigned int frame;
- unsigned int metrics[5];
- unsigned int chosen;
-};
-
-struct PREDICTION
-{
- unsigned int metric;
- unsigned int phase;
- unsigned int predicted;
- unsigned int predicted_metric;
-};
-
-struct context_s {
- int is_configured;
- mlt_properties image_cache;
- int out;
-
- int tff, chroma, blend, hints, show, debug;
- float dthresh, gthresh, vthresh, vthresh_saved, bthresh;
- int y0, y1, nt, guide, post, back, back_saved;
- int pitch, dpitch, pitchover2, pitchtimes4;
- int w, h, wover2, hover2, hplus1over2, hminus2;
- int xblocks, yblocks;
-#ifdef WINDOWED_MATCH
- unsigned int *matchc, *matchp, highest_matchc, highest_matchp;
-#endif
- unsigned int *sumc, *sump, highest_sumc, highest_sump;
- int vmetric;
- unsigned int *overrides, *overrides_p;
- int film, override, inpattern, found;
- int force;
-
- // Used by field matching.
- unsigned char *fprp, *fcrp, *fcrp_saved, *fnrp;
-// unsigned char *fprpU, *fcrpU, *fcrp_savedU, *fnrpU;
-// unsigned char *fprpV, *fcrpV, *fcrp_savedV, *fnrpV;
- unsigned char *dstp, *finalp;
-// unsigned char *dstpU, *dstpV;
- int chosen;
- unsigned int p, c, pblock, cblock, lowest, predicted, predicted_metric;
- unsigned int np, nc, npblock, ncblock, nframe;
- float mismatch;
- int pframe, x, y;
- unsigned char *crp, *prp;
- unsigned char *crpU, *prpU;
- unsigned char *crpV, *prpV;
- int hard;
- char status[80];
-
- // Metrics cache.
- struct CACHE_ENTRY *cache;
-
- // Pattern guidance data.
- int cycle;
- struct PREDICTION pred[MAX_CYCLE+1];
-};
-typedef struct context_s *context;
-
-
-static inline
-void BitBlt(uint8_t* dstp, int dst_pitch, const uint8_t* srcp,
- int src_pitch, int row_size, int height)
-{
- uint32_t y;
- for(y=0;y<height;y++)
- {
- memcpy(dstp,srcp,row_size);
- dstp+=dst_pitch;
- srcp+=src_pitch;
- }
-}
-
-static void Show(context cx, int frame, mlt_properties properties)
-{
- char use;
- char buf[512];
-
- if (cx->chosen == P) use = 'p';
- else if (cx->chosen == C) use = 'c';
- else use = 'n';
- snprintf(buf, sizeof(buf), "Telecide: frame %d: matches: %d %d %d\n", frame, cx->p, cx->c, cx->np);
- if ( cx->post )
- snprintf(buf, sizeof(buf), "%sTelecide: frame %d: vmetrics: %d %d %d [chosen=%d]\n", buf, frame, cx->pblock, cx->cblock, cx->npblock, cx->vmetric);
- if ( cx->guide )
- snprintf(buf, sizeof(buf), "%spattern mismatch=%0.2f%%\n", buf, cx->mismatch);
- snprintf(buf, sizeof(buf), "%sTelecide: frame %d: [%s %c]%s %s\n", buf, frame, cx->found ? "forcing" : "using", use,
- cx->post ? (cx->film ? " [progressive]" : " [interlaced]") : "",
- cx->guide ? cx->status : "");
- mlt_properties_set( properties, "meta.attr.telecide.markup", buf );
-}
-
-static void Debug(context cx, int frame)
-{
- char use;
-
- if (cx->chosen == P) use = 'p';
- else if (cx->chosen == C) use = 'c';
- else use = 'n';
- fprintf(stderr, "Telecide: frame %d: matches: %d %d %d\n", frame, cx->p, cx->c, cx->np);
- if ( cx->post )
- fprintf(stderr, "Telecide: frame %d: vmetrics: %d %d %d [chosen=%d]\n", frame, cx->pblock, cx->cblock, cx->npblock, cx->vmetric);
- if ( cx->guide )
- fprintf(stderr, "pattern mismatch=%0.2f%%\n", cx->mismatch);
- fprintf(stderr, "Telecide: frame %d: [%s %c]%s %s\n", frame, cx->found ? "forcing" : "using", use,
- cx->post ? (cx->film ? " [progressive]" : " [interlaced]") : "",
- cx->guide ? cx->status : "");
-}
-
-static void WriteHints(int film, int inpattern, mlt_properties frame_properties)
-{
- mlt_properties_set_int( frame_properties, "telecide.progressive", film);
- mlt_properties_set_int( frame_properties, "telecide.in_pattern", inpattern);
-}
-
-static void PutChosen(context cx, int frame, unsigned int chosen)
-{
- int f = frame % CACHE_SIZE;
- if (frame < 0 || frame > cx->out || cx->cache[f].frame != frame)
- return;
- cx->cache[f].chosen = chosen;
-}
-
-static void CacheInsert(context cx, int frame, unsigned int p, unsigned int pblock,
- unsigned int c, unsigned int cblock)
-{
- int f = frame % CACHE_SIZE;
- if (frame < 0 || frame > cx->out)
- fprintf( stderr, "%s: internal error: invalid frame %d for CacheInsert", __FUNCTION__, frame);
- cx->cache[f].frame = frame;
- cx->cache[f].metrics[P] = p;
- if (f) cx->cache[f-1].metrics[N] = p;
- cx->cache[f].metrics[C] = c;
- cx->cache[f].metrics[PBLOCK] = pblock;
- cx->cache[f].metrics[CBLOCK] = cblock;
- cx->cache[f].chosen = 0xff;
-}
-
-static int CacheQuery(context cx, int frame, unsigned int *p, unsigned int *pblock,
- unsigned int *c, unsigned int *cblock)
-{
- int f;
-
- f = frame % CACHE_SIZE;
- if (frame < 0 || frame > cx->out)
- fprintf( stderr, "%s: internal error: invalid frame %d for CacheQuery", __FUNCTION__, frame);
- if (cx->cache[f].frame != frame)
- {
- return 0;
- }
- *p = cx->cache[f].metrics[P];
- *c = cx->cache[f].metrics[C];
- *pblock = cx->cache[f].metrics[PBLOCK];
- *cblock = cx->cache[f].metrics[CBLOCK];
- return 1;
-}
-
-static int PredictHardYUY2(context cx, int frame, unsigned int *predicted, unsigned int *predicted_metric)
-{
- // Look for pattern in the actual delivered matches of the previous cycle of frames.
- // If a pattern is found, use that to predict the current match.
- if ( cx->guide == GUIDE_22 )
- {
- if (cx->cache[(frame- cx->cycle)%CACHE_SIZE ].chosen == 0xff ||
- cx->cache[(frame- cx->cycle+1)%CACHE_SIZE].chosen == 0xff)
- return 0;
- switch ((cx->cache[(frame- cx->cycle)%CACHE_SIZE ].chosen << 4) +
- (cx->cache[(frame- cx->cycle+1)%CACHE_SIZE].chosen))
- {
- case 0x11:
- *predicted = C;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C];
- break;
- case 0x22:
- *predicted = N;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N];
- break;
- default: return 0;
- }
- }
- else if ( cx->guide == GUIDE_32 )
- {
- if (cx->cache[(frame-cx->cycle)%CACHE_SIZE ].chosen == 0xff ||
- cx->cache[(frame-cx->cycle+1)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame-cx->cycle+2)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame-cx->cycle+3)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame-cx->cycle+4)%CACHE_SIZE].chosen == 0xff)
- return 0;
-
- switch ((cx->cache[(frame-cx->cycle)%CACHE_SIZE ].chosen << 16) +
- (cx->cache[(frame-cx->cycle+1)%CACHE_SIZE].chosen << 12) +
- (cx->cache[(frame-cx->cycle+2)%CACHE_SIZE].chosen << 8) +
- (cx->cache[(frame-cx->cycle+3)%CACHE_SIZE].chosen << 4) +
- (cx->cache[(frame-cx->cycle+4)%CACHE_SIZE].chosen))
- {
- case 0x11122:
- case 0x11221:
- case 0x12211:
- case 0x12221:
- case 0x21122:
- case 0x11222:
- *predicted = C;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C];
- break;
- case 0x22111:
- case 0x21112:
- case 0x22112:
- case 0x22211:
- *predicted = N;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N];
- break;
- default: return 0;
- }
- }
- else if ( cx->guide == GUIDE_32322 )
- {
- if (cx->cache[(frame- cx->cycle)%CACHE_SIZE ].chosen == 0xff ||
- cx->cache[(frame- cx->cycle +1)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame- cx->cycle +2)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame- cx->cycle +3)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame- cx->cycle +4)%CACHE_SIZE].chosen == 0xff ||
- cx->cache[(frame- cx->cycle +5)%CACHE_SIZE].chosen == 0xff)
- return 0;
-
- switch ((cx->cache[(frame- cx->cycle)%CACHE_SIZE ].chosen << 20) +
- (cx->cache[(frame- cx->cycle +1)%CACHE_SIZE].chosen << 16) +
- (cx->cache[(frame- cx->cycle +2)%CACHE_SIZE].chosen << 12) +
- (cx->cache[(frame- cx->cycle +3)%CACHE_SIZE].chosen << 8) +
- (cx->cache[(frame- cx->cycle +4)%CACHE_SIZE].chosen << 4) +
- (cx->cache[(frame- cx->cycle +5)%CACHE_SIZE].chosen))
- {
- case 0x111122:
- case 0x111221:
- case 0x112211:
- case 0x122111:
- case 0x111222:
- case 0x112221:
- case 0x122211:
- case 0x222111:
- *predicted = C;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C];
- break;
- case 0x221111:
- case 0x211112:
-
- case 0x221112:
- case 0x211122:
- *predicted = N;
- *predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N];
- break;
- default: return 0;
- }
- }
-#ifdef DEBUG_PATTERN_GUIDANCE
- fprintf( stderr, "%s: pos=%d HARD: predicted=%d\n", __FUNCTION__, frame, *predicted);
-#endif
- return 1;
-}
-
-static struct PREDICTION *PredictSoftYUY2(context cx, int frame )
-{
- // Use heuristics to look forward for a match.
- int i, j, y, c, n, phase;
- unsigned int metric;
-
- cx->pred[0].metric = 0xffffffff;
- if (frame < 0 || frame > cx->out - cx->cycle) return cx->pred;
-
- // Look at the next cycle of frames.
- for (y = frame + 1; y <= frame + cx->cycle; y++)
- {
- // Look for a frame where the current and next match values are
- // very close. Those are candidates to predict the phase, because
- // that condition should occur only once per cycle. Store the candidate
- // phases and predictions in a list sorted by goodness. The list will
- // be used by the caller to try the phases in order.
- c = cx->cache[y%CACHE_SIZE].metrics[C];
- n = cx->cache[y%CACHE_SIZE].metrics[N];
- if (c == 0) c = 1;
- metric = (100 * abs (c - n)) / c;
- phase = y % cx->cycle;
- if (metric < 5)
- {
- // Place the new candidate phase in sorted order in the list.
- // Find the insertion point.
- i = 0;
- while (metric > cx->pred[i].metric) i++;
- // Find the end-of-list marker.
- j = 0;
- while (cx->pred[j].metric != 0xffffffff) j++;
- // Shift all items below the insertion point down by one to make
- // room for the insertion.
- j++;
- for (; j > i; j--)
- {
- cx->pred[j].metric = cx->pred[j-1].metric;
- cx->pred[j].phase = cx->pred[j-1].phase;
- cx->pred[j].predicted = cx->pred[j-1].predicted;
- cx->pred[j].predicted_metric = cx->pred[j-1].predicted_metric;
- }
- // Insert the new candidate data.
- cx->pred[j].metric = metric;
- cx->pred[j].phase = phase;
- if ( cx->guide == GUIDE_32 )
- {
- switch ((frame % cx->cycle) - phase)
- {
- case -4: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case -3: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case -2: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case -1: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case 0: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case +1: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case +2: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case +3: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case +4: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- }
- }
- else if ( cx->guide == GUIDE_32322 )
- {
- switch ((frame % cx->cycle) - phase)
- {
- case -5: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case -4: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case -3: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case -2: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case -1: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case 0: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case +1: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case +2: cx->pred[j].predicted = N; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[N]; break;
- case +3: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case +4: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- case +5: cx->pred[j].predicted = C; cx->pred[j].predicted_metric = cx->cache[frame%CACHE_SIZE].metrics[C]; break;
- }
- }
- }
-#ifdef DEBUG_PATTERN_GUIDANCE
- fprintf( stderr, "%s: pos=%d metric=%d phase=%d\n", __FUNCTION__, frame, metric, phase);
-#endif
- }
- return cx->pred;
-}
-
-static
-void CalculateMetrics(context cx, int frame, unsigned char *fcrp, unsigned char *fcrpU, unsigned char *fcrpV,
- unsigned char *fprp, unsigned char *fprpU, unsigned char *fprpV)
-{
- int x, y, p, c, tmp1, tmp2, skip;
- int vc;
- unsigned char *currbot0, *currbot2, *prevbot0, *prevbot2;
- unsigned char *prevtop0, *prevtop2, *prevtop4, *currtop0, *currtop2, *currtop4;
- unsigned char *a0, *a2, *b0, *b2, *b4;
- unsigned int diff, index;
-# define T 4
-
- /* Clear the block sums. */
- for (y = 0; y < cx->yblocks; y++)
- {
- for (x = 0; x < cx->xblocks; x++)
- {
-#ifdef WINDOWED_MATCH
- matchp[y*xblocks+x] = 0;
- matchc[y*xblocks+x] = 0;
-#endif
- cx->sump[y * cx->xblocks + x] = 0;
- cx->sumc[y * cx->xblocks + x] = 0;
- }
- }
-
- /* Find the best field match. Subsample the frames for speed. */
- currbot0 = fcrp + cx->pitch;
- currbot2 = fcrp + 3 * cx->pitch;
- currtop0 = fcrp;
- currtop2 = fcrp + 2 * cx->pitch;
- currtop4 = fcrp + 4 * cx->pitch;
- prevbot0 = fprp + cx->pitch;
- prevbot2 = fprp + 3 * cx->pitch;
- prevtop0 = fprp;
- prevtop2 = fprp + 2 * cx->pitch;
- prevtop4 = fprp + 4 * cx->pitch;
- if ( cx->tff )
- {
- a0 = prevbot0;
- a2 = prevbot2;
- b0 = currtop0;
- b2 = currtop2;
- b4 = currtop4;
- }
- else
- {
- a0 = currbot0;
- a2 = currbot2;
- b0 = prevtop0;
- b2 = prevtop2;
- b4 = prevtop4;
- }
- p = c = 0;
-
- // Calculate the field match and film/video metrics.
-// if (vi.IsYV12()) skip = 1;
-// else
- skip = 1 + ( !cx->chroma );
- for (y = 0, index = 0; y < cx->h - 4; y+=4)
- {
- /* Exclusion band. Good for ignoring subtitles. */
- if (cx->y0 == cx->y1 || y < cx->y0 || y > cx->y1)
- {
- for (x = 0; x < cx->w;)
- {
-// if (vi.IsYV12())
-// index = (y/BLKSIZE)*xblocks + x/BLKSIZE;
-// else
- index = (y/BLKSIZE) * cx->xblocks + x/BLKSIZE_TIMES2;
-
- // Test combination with current frame.
- tmp1 = ((long)currbot0[x] + (long)currbot2[x]);
-// diff = abs((long)currtop0[x] - (tmp1 >> 1));
- diff = abs((((long)currtop0[x] + (long)currtop2[x] + (long)currtop4[x])) - (tmp1 >> 1) - tmp1);
- if (diff > cx->nt)
- {
- c += diff;
-#ifdef WINDOWED_MATCH
- matchc[index] += diff;
-#endif
- }
-
- tmp1 = currbot0[x] + T;
- tmp2 = currbot0[x] - T;
- vc = (tmp1 < currtop0[x] && tmp1 < currtop2[x]) ||
- (tmp2 > currtop0[x] && tmp2 > currtop2[x]);
- if (vc)
- {
- cx->sumc[index]++;
- }
-
- // Test combination with previous frame.
- tmp1 = ((long)a0[x] + (long)a2[x]);
- diff = abs((((long)b0[x] + (long)b2[x] + (long)b4[x])) - (tmp1 >> 1) - tmp1);
- if (diff > cx->nt)
- {
- p += diff;
-#ifdef WINDOWED_MATCH
- matchp[index] += diff;
-#endif
- }
-
- tmp1 = a0[x] + T;
- tmp2 = a0[x] - T;
- vc = (tmp1 < b0[x] && tmp1 < b2[x]) ||
- (tmp2 > b0[x] && tmp2 > b2[x]);
- if (vc)
- {
- cx->sump[index]++;
- }
-
- x += skip;
- if (!(x&3)) x += 4;
- }
- }
- currbot0 += cx->pitchtimes4;
- currbot2 += cx->pitchtimes4;
- currtop0 += cx->pitchtimes4;
- currtop2 += cx->pitchtimes4;
- currtop4 += cx->pitchtimes4;
- a0 += cx->pitchtimes4;
- a2 += cx->pitchtimes4;
- b0 += cx->pitchtimes4;
- b2 += cx->pitchtimes4;
- b4 += cx->pitchtimes4;
- }
-
-// if (vi.IsYV12() && chroma == true)
-// {
-// int z;
-//
-// for (z = 0; z < 2; z++)
-// {
-// // Do the same for the U plane.
-// if (z == 0)
-// {
-// currbot0 = fcrpU + pitchover2;
-// currbot2 = fcrpU + 3 * pitchover2;
-// currtop0 = fcrpU;
-// currtop2 = fcrpU + 2 * pitchover2;
-// currtop4 = fcrpU + 4 * pitchover2;
-// prevbot0 = fprpU + pitchover2;
-// prevbot2 = fprpU + 3 * pitchover2;
-// prevtop0 = fprpU;
-// prevtop2 = fprpU + 2 * pitchover2;
-// prevtop4 = fprpU + 4 * pitchover2;
-// }
-// else
-// {
-// currbot0 = fcrpV + pitchover2;
-// currbot2 = fcrpV + 3 * pitchover2;
-// currtop0 = fcrpV;
-// currtop2 = fcrpV + 2 * pitchover2;
-// currtop4 = fcrpV + 4 * pitchover2;
-// prevbot0 = fprpV + pitchover2;
-// prevbot2 = fprpV + 3 * pitchover2;
-// prevtop0 = fprpV;
-// prevtop2 = fprpV + 2 * pitchover2;
-// prevtop4 = fprpV + 4 * pitchover2;
-// }
-// if (tff == true)
-// {
-// a0 = prevbot0;
-// a2 = prevbot2;
-// b0 = currtop0;
-// b2 = currtop2;
-// b4 = currtop4;
-// }
-// else
-// {
-// a0 = currbot0;
-// a2 = currbot2;
-// b0 = prevtop0;
-// b2 = prevtop2;
-// b4 = prevtop4;
-// }
-//
-// for (y = 0, index = 0; y < hover2 - 4; y+=4)
-// {
-// /* Exclusion band. Good for ignoring subtitles. */
-// if (y0 == y1 || y < y0/2 || y > y1/2)
-// {
-// for (x = 0; x < wover2;)
-// {
-// if (vi.IsYV12())
-// index = (y/BLKSIZE)*xblocks + x/BLKSIZE;
-// else
-// index = (y/BLKSIZE)*xblocks + x/BLKSIZE_TIMES2;
-//
-// // Test combination with current frame.
-// tmp1 = ((long)currbot0[x] + (long)currbot2[x]);
-// diff = abs((((long)currtop0[x] + (long)currtop2[x] + (long)currtop4[x])) - (tmp1 >> 1) - tmp1);
-// if (diff > nt)
-// {
-// c += diff;
-//#ifdef WINDOWED_MATCH
-// matchc[index] += diff;
-//#endif
-// }
-//
-// tmp1 = currbot0[x] + T;
-// tmp2 = currbot0[x] - T;
-// vc = (tmp1 < currtop0[x] && tmp1 < currtop2[x]) ||
-// (tmp2 > currtop0[x] && tmp2 > currtop2[x]);
-// if (vc)
-// {
-// sumc[index]++;
-// }
-//
-// // Test combination with previous frame.
-// tmp1 = ((long)a0[x] + (long)a2[x]);
-// diff = abs((((long)b0[x] + (long)b2[x] + (long)b4[x])) - (tmp1 >> 1) - tmp1);
-// if (diff > nt)
-// {
-// p += diff;
-//#ifdef WINDOWED_MATCH
-// matchp[index] += diff;
-//#endif
-// }
-//
-// tmp1 = a0[x] + T;
-// tmp2 = a0[x] - T;
-// vc = (tmp1 < b0[x] && tmp1 < b2[x]) ||
-// (tmp2 > b0[x] && tmp2 > b2[x]);
-// if (vc)
-// {
-// sump[index]++;
-// }
-//
-// x ++;
-// if (!(x&3)) x += 4;
-// }
-// }
-// currbot0 += 4*pitchover2;
-// currbot2 += 4*pitchover2;
-// currtop0 += 4*pitchover2;
-// currtop2 += 4*pitchover2;
-// currtop4 += 4*pitchover2;
-// a0 += 4*pitchover2;
-// a2 += 4*pitchover2;
-// b0 += 4*pitchover2;
-// b2 += 4*pitchover2;
-// b4 += 4*pitchover2;
-// }
-// }
-// }
-//
-// // Now find the blocks that have the greatest differences.
-//#ifdef WINDOWED_MATCH
-// highest_matchp = 0;
-// for (y = 0; y < yblocks; y++)
-// {
-// for (x = 0; x < xblocks; x++)
-// {
-//if (frame == 45 && matchp[y * xblocks + x] > 2500)
-//{
-// sprintf(buf, "%d/%d = %d\n", x, y, matchp[y * xblocks + x]);
-// OutputDebugString(buf);
-//}
-// if (matchp[y * xblocks + x] > highest_matchp)
-// {
-// highest_matchp = matchp[y * xblocks + x];
-// }
-// }
-// }
-// highest_matchc = 0;
-// for (y = 0; y < yblocks; y++)
-// {
-// for (x = 0; x < xblocks; x++)
-// {
-//if (frame == 44 && matchc[y * xblocks + x] > 2500)
-//{
-// sprintf(buf, "%d/%d = %d\n", x, y, matchc[y * xblocks + x]);
-// OutputDebugString(buf);
-//}
-// if (matchc[y * xblocks + x] > highest_matchc)
-// {
-// highest_matchc = matchc[y * xblocks + x];
-// }
-// }
-// }
-//#endif
- if ( cx->post )
- {
- cx->highest_sump = 0;
- for (y = 0; y < cx->yblocks; y++)
- {
- for (x = 0; x < cx->xblocks; x++)
- {
- if (cx->sump[y * cx->xblocks + x] > cx->highest_sump)
- {
- cx->highest_sump = cx->sump[y * cx->xblocks + x];
- }
- }
- }
- cx->highest_sumc = 0;
- for (y = 0; y < cx->yblocks; y++)
- {
- for (x = 0; x < cx->xblocks; x++)
- {
- if (cx->sumc[y * cx->xblocks + x] > cx->highest_sumc)
- {
- cx->highest_sumc = cx->sumc[y * cx->xblocks + x];
- }
- }
- }
- }
-#ifdef WINDOWED_MATCH
- CacheInsert(frame, highest_matchp, highest_sump, highest_matchc, highest_sumc);
-#else
- CacheInsert( cx, frame, p, cx->highest_sump, c, cx->highest_sumc);
-#endif
-}
-
-
-/** Process the image.
-*/
-
-static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_service( frame );
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
- mlt_properties frame_properties = mlt_frame_properties( frame );
- context cx = mlt_properties_get_data( properties, "context", NULL );
- mlt_service producer = mlt_service_producer( mlt_filter_service( filter ) );
- cx->out = producer? mlt_producer_get_playtime( MLT_PRODUCER( producer ) ) : 999999;
-
- if ( ! cx->is_configured )
- {
- cx->back = mlt_properties_get_int( properties, "back" );
- cx->chroma = mlt_properties_get_int( properties, "chroma" );
- cx->guide = mlt_properties_get_int( properties, "guide" );
- cx->gthresh = mlt_properties_get_double( properties, "gthresh" );
- cx->post = mlt_properties_get_int( properties, "post" );
- cx->vthresh = mlt_properties_get_double( properties, "vthresh" );
- cx->bthresh = mlt_properties_get_double( properties, "bthresh" );
- cx->dthresh = mlt_properties_get_double( properties, "dthresh" );
- cx->blend = mlt_properties_get_int( properties, "blend" );
- cx->nt = mlt_properties_get_int( properties, "nt" );
- cx->y0 = mlt_properties_get_int( properties, "y0" );
- cx->y1 = mlt_properties_get_int( properties, "y1" );
- cx->hints = mlt_properties_get_int( properties, "hints" );
- cx->debug = mlt_properties_get_int( properties, "debug" );
- cx->show = mlt_properties_get_int( properties, "show" );
- }
-
- // Get the image
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- if ( ! cx->sump )
- {
- int guide = mlt_properties_get_int( properties, "guide" );
- cx->cycle = 0;
- if ( guide == GUIDE_32 )
- {
- // 24fps to 30 fps telecine.
- cx->cycle = 5;
- }
- else if ( guide == GUIDE_22 )
- {
- // PAL guidance (expect the current match to be continued).
- cx->cycle = 2;
- }
- else if ( guide == GUIDE_32322 )
- {
- // 25fps to 30 fps telecine.
- cx->cycle = 6;
- }
-
- cx->xblocks = (*width+BLKSIZE-1) / BLKSIZE;
- cx->yblocks = (*height+BLKSIZE-1) / BLKSIZE;
- cx->sump = (unsigned int *) mlt_pool_alloc( cx->xblocks * cx->yblocks * sizeof(unsigned int) );
- cx->sumc = (unsigned int *) mlt_pool_alloc( cx->xblocks * cx->yblocks * sizeof(unsigned int) );
- mlt_properties_set_data( properties, "sump", cx->sump, cx->xblocks * cx->yblocks * sizeof(unsigned int), (mlt_destructor)mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "sumc", cx->sumc, cx->xblocks * cx->yblocks * sizeof(unsigned int), (mlt_destructor)mlt_pool_release, NULL );
- cx->tff = mlt_properties_get_int( frame_properties, "top_field_first" );
- // fprintf(stderr, "%s: TOP FIELD FIRST %d\n", __FUNCTION__, cx->tff );
- }
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // Put the current image into the image cache, keyed on position
- size_t image_size = (*width * *height) << 1;
- mlt_position pos = mlt_frame_get_position( frame );
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- memcpy( image_copy, *image, image_size );
- char key[20];
- sprintf( key, "%d", pos );
- mlt_properties_set_data( cx->image_cache, key, image_copy, image_size, (mlt_destructor)mlt_pool_release, NULL );
-
- // Only if we have enough frame images cached
- if ( pos > 1 && pos > cx->cycle + 1 )
- {
- pos -= cx->cycle + 1;
- // Get the current frame image
- sprintf( key, "%d", pos );
- cx->fcrp = mlt_properties_get_data( cx->image_cache, key, NULL );
- if (!cx->fcrp) return error;
-
- // Get the previous frame image
- cx->pframe = pos == 0 ? 0 : pos - 1;
- sprintf( key, "%d", cx->pframe );
- cx->fprp = mlt_properties_get_data( cx->image_cache, key, NULL );
- if (!cx->fprp) return error;
-
- // Get the next frame image
- cx->nframe = pos > cx->out ? cx->out : pos + 1;
- sprintf( key, "%d", cx->nframe );
- cx->fnrp = mlt_properties_get_data( cx->image_cache, key, NULL );
- if (!cx->fnrp) return error;
-
- cx->pitch = *width << 1;
- cx->pitchover2 = cx->pitch >> 1;
- cx->pitchtimes4 = cx->pitch << 2;
- cx->w = *width << 1;
- cx->h = *height;
- if ((cx->w/2) & 1)
- fprintf( stderr, "%s: width must be a multiple of 2\n", __FUNCTION__ );
- if (cx->h & 1)
- fprintf( stderr, "%s: height must be a multiple of 2\n", __FUNCTION__ );
- cx->wover2 = cx->w/2;
- cx->hover2 = cx->h/2;
- cx->hplus1over2 = (cx->h+1)/2;
- cx->hminus2 = cx->h - 2;
- cx->dpitch = cx->pitch;
-
- // Ensure that the metrics for the frames
- // after the current frame are in the cache. They will be used for
- // pattern guidance.
- if ( cx->guide )
- {
- for ( cx->y = pos + 1; (cx->y <= pos + cx->cycle + 1) && (cx->y <= cx->out); cx->y++ )
- {
- if ( ! CacheQuery( cx, cx->y, &cx->p, &cx->pblock, &cx->c, &cx->cblock ) )
- {
- sprintf( key, "%d", cx->y );
- cx->crp = (unsigned char *) mlt_properties_get_data( cx->image_cache, key, NULL );
- sprintf( key, "%d", cx->y ? cx->y - 1 : 1 );
- cx->prp = (unsigned char *) mlt_properties_get_data( cx->image_cache, key, NULL );
- CalculateMetrics( cx, cx->y, cx->crp, NULL, NULL, cx->prp, NULL, NULL ); }
- }
- }
-
- // Check for manual overrides of the field matching.
- cx->found = 0;
- cx->film = 1;
- cx->override = 0;
- cx->inpattern = 0;
- cx->vthresh = cx->vthresh;
- cx->back = cx->back_saved;
-
- // Get the metrics for the current-previous (p), current-current (c), and current-next (n) match candidates.
- if ( ! CacheQuery( cx, pos, &cx->p, &cx->pblock, &cx->c, &cx->cblock ) )
- {
- CalculateMetrics( cx, pos, cx->fcrp, NULL, NULL, cx->fprp, NULL, NULL );
- CacheQuery( cx, pos, &cx->p, &cx->pblock, &cx->c, &cx->cblock );
- }
- if ( ! CacheQuery( cx, cx->nframe, &cx->np, &cx->npblock, &cx->nc, &cx->ncblock ) )
- {
- CalculateMetrics( cx, cx->nframe, cx->fnrp, NULL, NULL, cx->fcrp, NULL, NULL );
- CacheQuery( cx, cx->nframe, &cx->np, &cx->npblock, &cx->nc, &cx->ncblock );
- }
-
- // Determine the best candidate match.
- if ( !cx->found )
- {
- cx->lowest = cx->c;
- cx->chosen = C;
- if ( cx->back == ALWAYS_BACK && cx->p < cx->lowest )
- {
- cx->lowest = cx->p;
- cx->chosen = P;
- }
- if ( cx->np < cx->lowest )
- {
- cx->lowest = cx->np;
- cx->chosen = N;
- }
- }
- if ((pos == 0 && cx->chosen == P) || (pos == cx->out && cx->chosen == N))
- {
- cx->chosen = C;
- cx->lowest = cx->c;
- }
-
- // See if we can apply pattern guidance.
- cx->mismatch = 100.0;
- if ( cx->guide )
- {
- cx->hard = 0;
- if ( pos >= cx->cycle && PredictHardYUY2( cx, pos, &cx->predicted, &cx->predicted_metric) )
- {
- cx->inpattern = 1;
- cx->mismatch = 0.0;
- cx->hard = 1;
- if ( cx->chosen != cx->predicted )
- {
- // The chosen frame doesn't match the prediction.
- if ( cx->predicted_metric == 0 )
- cx->mismatch = 0.0;
- else
- cx->mismatch = (100.0 * abs( cx->predicted_metric - cx->lowest ) ) / cx->predicted_metric;
- if ( cx->mismatch < cx->gthresh )
- {
- // It's close enough, so use the predicted one.
- if ( !cx->found )
- {
- cx->chosen = cx->predicted;
- cx->override = 1;
- }
- }
- else
- {
- cx->hard = 0;
- cx->inpattern = 0;
- }
- }
- }
-
- if ( !cx->hard && cx->guide != GUIDE_22 )
- {
- int i;
- struct PREDICTION *pred = PredictSoftYUY2( cx, pos );
-
- if ( ( pos <= cx->out - cx->cycle) && ( pred[0].metric != 0xffffffff ) )
- {
- // Apply pattern guidance.
- // If the predicted match metric is within defined percentage of the
- // best calculated one, then override the calculated match with the
- // predicted match.
- i = 0;
- while ( pred[i].metric != 0xffffffff )
- {
- cx->predicted = pred[i].predicted;
- cx->predicted_metric = pred[i].predicted_metric;
-#ifdef DEBUG_PATTERN_GUIDANCE
- fprintf(stderr, "%s: pos=%d predicted=%d\n", __FUNCTION__, pos, cx->predicted);
-#endif
- if ( cx->chosen != cx->predicted )
- {
- // The chosen frame doesn't match the prediction.
- if ( cx->predicted_metric == 0 )
- cx->mismatch = 0.0;
- else
- cx->mismatch = (100.0 * abs( cx->predicted_metric - cx->lowest )) / cx->predicted_metric;
- if ( (int) cx->mismatch <= cx->gthresh )
- {
- // It's close enough, so use the predicted one.
- if ( !cx->found )
- {
- cx->chosen = cx->predicted;
- cx->override = 1;
- }
- cx->inpattern = 1;
- break;
- }
- else
- {
- // Looks like we're not in a predictable pattern.
- cx->inpattern = 0;
- }
- }
- else
- {
- cx->inpattern = 1;
- cx->mismatch = 0.0;
- break;
- }
- i++;
- }
- }
- }
- }
-
- // Check the match for progressive versus interlaced.
- if ( cx->post )
- {
- if (cx->chosen == P) cx->vmetric = cx->pblock;
- else if (cx->chosen == C) cx->vmetric = cx->cblock;
- else if (cx->chosen == N) cx->vmetric = cx->npblock;
-
- if ( !cx->found && cx->back == BACK_ON_COMBED && cx->vmetric > cx->bthresh && cx->p < cx->lowest )
- {
- // Backward match.
- cx->vmetric = cx->pblock;
- cx->chosen = P;
- cx->inpattern = 0;
- cx->mismatch = 100;
- }
- if ( cx->vmetric > cx->vthresh )
- {
- // After field matching and pattern guidance the frame is still combed.
- cx->film = 0;
- if ( !cx->found && ( cx->post == POST_FULL_NOMATCH || cx->post == POST_FULL_NOMATCH_MAP ) )
- {
- cx->chosen = C;
- cx->vmetric = cx->cblock;
- cx->inpattern = 0;
- cx->mismatch = 100;
- }
- }
- }
- cx->vthresh = cx->vthresh_saved;
-
- // Setup strings for debug info.
- if ( cx->inpattern && !cx->override ) strcpy( cx->status, "[in-pattern]" );
- else if ( cx->inpattern && cx->override ) strcpy( cx->status, "[in-pattern*]" );
- else strcpy( cx->status, "[out-of-pattern]" );
-
- // Assemble and output the reconstructed frame according to the final match.
- cx->dstp = *image;
- if ( cx->chosen == N )
- {
- // The best match was with the next frame.
- if ( cx->tff )
- {
- BitBlt( cx->dstp, 2 * cx->dpitch, cx->fnrp, 2 * cx->pitch, cx->w, cx->hover2 );
- BitBlt( cx->dstp + cx->dpitch, 2 * cx->dpitch, cx->fcrp + cx->pitch, 2 * cx->pitch, cx->w, cx->hover2 );
- }
- else
- {
- BitBlt( cx->dstp, 2 * cx->dpitch, cx->fcrp, 2 * cx->pitch, cx->w, cx->hplus1over2 );
- BitBlt( cx->dstp + cx->dpitch, 2 * cx->dpitch, cx->fnrp + cx->pitch, 2 * cx->pitch, cx->w, cx->hover2 );
- }
- }
- else if ( cx->chosen == C )
- {
- // The best match was with the current frame.
- BitBlt( cx->dstp, 2 * cx->dpitch, cx->fcrp, 2 * cx->pitch, cx->w, cx->hplus1over2 );
- BitBlt( cx->dstp + cx->dpitch, 2 * cx->dpitch, cx->fcrp + cx->pitch, 2 * cx->pitch, cx->w, cx->hover2 );
- }
- else if ( ! cx->tff )
- {
- // The best match was with the previous frame.
- BitBlt( cx->dstp, 2 * cx->dpitch, cx->fprp, 2 * cx->pitch, cx->w, cx->hplus1over2 );
- BitBlt( cx->dstp + cx->dpitch, 2 * cx->dpitch, cx->fcrp + cx->pitch, 2 * cx->pitch, cx->w, cx->hover2 );
- }
- else
- {
- // The best match was with the previous frame.
- BitBlt( cx->dstp, 2 * cx->dpitch, cx->fcrp, 2 * cx->pitch, cx->w, cx->hplus1over2 );
- BitBlt( cx->dstp + cx->dpitch, 2 * cx->dpitch, cx->fprp + cx->pitch, 2 * cx->pitch, cx->w, cx->hover2 );
- }
- if ( cx->guide )
- PutChosen( cx, pos, cx->chosen );
-
- if ( !cx->post || cx->post == POST_METRICS )
- {
- if ( cx->force == '+') cx->film = 0;
- else if ( cx->force == '-' ) cx->film = 1;
- }
- else if ((cx->force == '+') ||
- ((cx->post == POST_FULL || cx->post == POST_FULL_MAP || cx->post == POST_FULL_NOMATCH || cx->post == POST_FULL_NOMATCH_MAP)
- && (cx->film == 0 && cx->force != '-')))
- {
- unsigned char *dstpp, *dstpn;
- int v1, v2;
-
- if ( cx->blend )
- {
- // Do first and last lines.
- uint8_t *final = mlt_pool_alloc( image_size );
- cx->finalp = final;
- mlt_properties_set_data( frame_properties, "image", final, image_size, (mlt_destructor)mlt_pool_release, NULL );
- dstpn = cx->dstp + cx->dpitch;
- for ( cx->x = 0; cx->x < cx->w; cx->x++ )
- {
- cx->finalp[cx->x] = (((int)cx->dstp[cx->x] + (int)dstpn[cx->x]) >> 1);
- }
- cx->finalp = final + (cx->h-1)*cx->dpitch;
- cx->dstp = *image + (cx->h-1)*cx->dpitch;
- dstpp = cx->dstp - cx->dpitch;
- for ( cx->x = 0; cx->x < cx->w; cx->x++ )
- {
- cx->finalp[cx->x] = (((int)cx->dstp[cx->x] + (int)dstpp[cx->x]) >> 1);
- }
- // Now do the rest.
- cx->dstp = *image + cx->dpitch;
- dstpp = cx->dstp - cx->dpitch;
- dstpn = cx->dstp + cx->dpitch;
- cx->finalp = final + cx->dpitch;
- for ( cx->y = 1; cx->y < cx->h - 1; cx->y++ )
- {
- for ( cx->x = 0; cx->x < cx->w; cx->x++ )
- {
- v1 = (int) cx->dstp[cx->x] - cx->dthresh;
- if ( v1 < 0 )
- v1 = 0;
- v2 = (int) cx->dstp[cx->x] + cx->dthresh;
- if (v2 > 235) v2 = 235;
- if ((v1 > dstpp[cx->x] && v1 > dstpn[cx->x]) || (v2 < dstpp[cx->x] && v2 < dstpn[cx->x]))
- {
- if ( cx->post == POST_FULL_MAP || cx->post == POST_FULL_NOMATCH_MAP )
- {
- if (cx->x & 1) cx->finalp[cx->x] = 128;
- else cx->finalp[cx->x] = 235;
- }
- else
- cx->finalp[cx->x] = ((int)dstpp[cx->x] + (int)dstpn[cx->x] + (int)cx->dstp[cx->x] + (int)cx->dstp[cx->x]) >> 2;
- }
- else cx->finalp[cx->x] = cx->dstp[cx->x];
- }
- cx->finalp += cx->dpitch;
- cx->dstp += cx->dpitch;
- dstpp += cx->dpitch;
- dstpn += cx->dpitch;
- }
-
-
- if (cx->show ) Show( cx, pos, frame_properties);
- if (cx->debug) Debug(cx, pos);
- if (cx->hints) WriteHints(cx->film, cx->inpattern, frame_properties);
- goto final;
- }
-
- // Interpolate mode.
- cx->dstp = *image + cx->dpitch;
- dstpp = cx->dstp - cx->dpitch;
- dstpn = cx->dstp + cx->dpitch;
- for ( cx->y = 1; cx->y < cx->h - 1; cx->y+=2 )
- {
- for ( cx->x = 0; cx->x < cx->w; cx->x++ )
- {
- v1 = (int) cx->dstp[cx->x] - cx->dthresh;
- if (v1 < 0) v1 = 0;
- v2 = (int) cx->dstp[cx->x] + cx->dthresh;
- if (v2 > 235) v2 = 235;
- if ((v1 > dstpp[cx->x] && v1 > dstpn[cx->x]) || (v2 < dstpp[cx->x] && v2 < dstpn[cx->x]))
- {
- if ( cx->post == POST_FULL_MAP || cx->post == POST_FULL_NOMATCH_MAP )
- {
- if (cx->x & 1) cx->dstp[cx->x] = 128;
- else cx->dstp[cx->x] = 235;
- }
- else
- cx->dstp[cx->x] = (dstpp[cx->x] + dstpn[cx->x]) >> 1;
- }
- }
- cx->dstp += 2 * cx->dpitch;
- dstpp += 2 * cx->dpitch;
- dstpn += 2 * cx->dpitch;
- }
- }
- if (cx->show ) Show( cx, pos, frame_properties);
- if (cx->debug) Debug(cx, pos);
- if (cx->hints) WriteHints(cx->film, cx->inpattern, frame_properties);
-
-final:
- // Flush frame at tail of period from the cache
- sprintf( key, "%d", pos - 1 );
- mlt_properties_set_data( cx->image_cache, key, NULL, 0, NULL, NULL );
- }
- else
- {
- // Signal the first {cycle} frames as invalid
- mlt_properties_set_int( frame_properties, "garbage", 1 );
- }
- }
- else if ( error == 0 && *format == mlt_image_yuv420p )
- {
- fprintf(stderr,"%s: %d pos %d\n", __FUNCTION__, *width * *height * 3/2, mlt_frame_get_position(frame) );
- }
-
- return error;
-}
-
-/** Process the frame object.
-*/
-
-static mlt_frame process( mlt_filter this, mlt_frame frame )
-{
- // Push the filter on to the stack
- mlt_frame_push_service( frame, this );
-
- // Push the frame filter
- mlt_frame_push_get_image( frame, get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_telecide_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = process;
-
- // Allocate the context and set up for garbage collection
- context cx = (context) mlt_pool_alloc( sizeof(struct context_s) );
- memset( cx, 0, sizeof( struct context_s ) );
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- mlt_properties_set_data( properties, "context", cx, sizeof(struct context_s), (mlt_destructor)mlt_pool_release, NULL );
-
- // Allocate the metrics cache and set up for garbage collection
- cx->cache = (struct CACHE_ENTRY *) mlt_pool_alloc(CACHE_SIZE * sizeof(struct CACHE_ENTRY ));
- mlt_properties_set_data( properties, "cache", cx->cache, CACHE_SIZE * sizeof(struct CACHE_ENTRY), (mlt_destructor)mlt_pool_release, NULL );
- int i;
- for (i = 0; i < CACHE_SIZE; i++)
- {
- cx->cache[i].frame = 0xffffffff;
- cx->cache[i].chosen = 0xff;
- }
-
- // Allocate the image cache and set up for garbage collection
- cx->image_cache = mlt_properties_new();
- mlt_properties_set_data( properties, "image_cache", cx->image_cache, 0, (mlt_destructor)mlt_properties_close, NULL );
-
- // Initialize the parameter defaults
- mlt_properties_set_int( properties, "guide", 0 );
- mlt_properties_set_int( properties, "back", 0 );
- mlt_properties_set_int( properties, "chroma", 0 );
- mlt_properties_set_int( properties, "post", POST_FULL );
- mlt_properties_set_double( properties, "gthresh", 10.0 );
- mlt_properties_set_double( properties, "vthresh", 50.0 );
- mlt_properties_set_double( properties, "bthresh", 50.0 );
- mlt_properties_set_double( properties, "dthresh", 7.0 );
- mlt_properties_set_int( properties, "blend", 0 );
- mlt_properties_set_int( properties, "nt", 10 );
- mlt_properties_set_int( properties, "y0", 0 );
- mlt_properties_set_int( properties, "y1", 0 );
- mlt_properties_set_int( properties, "hints", 1 );
- }
- return this;
-}
-
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltdv$(LIBSUF)
-
-OBJS = factory.o \
- producer_libdv.o \
- consumer_libdv.o
-
-CFLAGS += -I../..
-CFLAGS += `pkg-config --cflags libdv`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `pkg-config --libs libdv`
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- pkg-config libdv 2> /dev/null
- disable_libdv=$?
-
- if [ "$disable_libdv" != "0" ]
- then
- echo "- libdv not found: disabling"
- touch ../disable-dv
- exit 0
- fi
-
-fi
-
+++ /dev/null
-/*
- * consumer_libdv.c -- a DV encoder based on libdv
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// mlt Header files
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-
-// System header files
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-
-// libdv header files
-#include <libdv/dv.h>
-
-#define FRAME_SIZE_525_60 10 * 150 * 80
-#define FRAME_SIZE_625_50 12 * 150 * 80
-
-// 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 );
-static void *consumer_thread( void *arg );
-static void consumer_close( mlt_consumer this );
-
-/** Initialise the dv consumer.
-*/
-
-mlt_consumer consumer_libdv_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Allocate the consumer
- mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) );
-
- // If memory allocated and initialises without error
- if ( this != NULL && mlt_consumer_init( this, NULL, profile ) == 0 )
- {
- // Get properties from the consumer
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Assign close callback
- this->close = consumer_close;
-
- // Interpret the argument
- if ( arg != NULL )
- mlt_properties_set( properties, "target", arg );
-
- // 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 );
-
- // Terminate at end of the stream by default
- mlt_properties_set_int( properties, "terminate_on_pause", 1 );
-
- // Set up start/stop/terminated callbacks
- this->start = consumer_start;
- this->stop = consumer_stop;
- this->is_stopped = consumer_is_stopped;
- }
- else
- {
- // Clean up in case of init failure
- free( this );
- this = NULL;
- }
-
- // Return this
- 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 );
-
- // Close the output file :-) - this is obtuse - doesn't matter if output file
- // exists or not - the destructor will kick in if it does
- mlt_properties_set_data( properties, "output_file", NULL, 0, NULL, 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.
-*/
-
-static dv_encoder_t *libdv_get_encoder( mlt_consumer this, mlt_frame frame )
-{
- // Get the properties of the consumer
- mlt_properties this_properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Obtain the dv_encoder
- dv_encoder_t *encoder = mlt_properties_get_data( this_properties, "dv_encoder", NULL );
-
- // Construct one if we don't have one
- if ( encoder == NULL )
- {
- // Get the fps of the consumer (for now - should be from frame)
- double fps = mlt_properties_get_double( this_properties, "fps" );
-
- // Create the encoder
- encoder = dv_encoder_new( 0, 0, 0 );
-
- // Encoder settings
- encoder->isPAL = fps == 25;
- encoder->is16x9 = 0;
- encoder->vlc_encode_passes = 1;
- encoder->static_qno = 0;
- encoder->force_dct = DV_DCT_AUTO;
-
- // Store the encoder on the properties
- mlt_properties_set_data( this_properties, "dv_encoder", encoder, 0, ( mlt_destructor )dv_encoder_free, NULL );
- }
-
- // Return the encoder
- return encoder;
-}
-
-
-/** The libdv encode video method.
-*/
-
-static int consumer_encode_video( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
-{
- // Obtain the dv_encoder
- dv_encoder_t *encoder = libdv_get_encoder( this, frame );
-
- // Get the properties of the consumer
- mlt_properties this_properties = MLT_CONSUMER_PROPERTIES( this );
-
- // This will hold the size of the dv frame
- int size = 0;
-
- // Is the image rendered
- int rendered = mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "rendered" );
-
- // Get width and height
- int width = mlt_properties_get_int( this_properties, "width" );
- int height = mlt_properties_get_int( this_properties, "height" );
-
- // If we get an encoder, then encode the image
- if ( rendered && encoder != NULL )
- {
- // Specify desired image properties
- mlt_image_format fmt = mlt_image_yuv422;
- uint8_t *image = NULL;
-
- // Get the image
- mlt_events_fire( this_properties, "consumer-frame-show", frame, NULL );
- mlt_frame_get_image( frame, &image, &fmt, &width, &height, 0 );
-
- // Check that we get what we expected
- if ( fmt != mlt_image_yuv422 ||
- width != mlt_properties_get_int( this_properties, "width" ) ||
- height != mlt_properties_get_int( this_properties, "height" ) ||
- image == NULL )
- {
- // We should try to recover here
- fprintf( stderr, "We have a problem houston...\n" );
- }
- else
- {
- // Calculate the size of the dv frame
- size = height == 576 ? FRAME_SIZE_625_50 : FRAME_SIZE_525_60;
- }
-
- // Process the frame
- if ( size != 0 )
- {
- // Encode the image
- dv_encode_full_frame( encoder, &image, e_dv_color_yuv, dv_frame );
- }
- }
- else if ( encoder != NULL )
- {
- // Calculate the size of the dv frame (duplicate of previous)
- size = height == 576 ? FRAME_SIZE_625_50 : FRAME_SIZE_525_60;
- }
-
- return size;
-}
-
-/** The libdv encode audio method.
-*/
-
-static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_frame frame )
-{
- // Get the properties of the consumer
- mlt_properties this_properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the properties of the frame
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the dv_encoder
- dv_encoder_t *encoder = libdv_get_encoder( this, frame );
-
- // Only continue if we have an encoder
- if ( encoder != NULL )
- {
- // Get the frame count
- int count = mlt_properties_get_int( this_properties, "count" );
-
- // Default audio args
- mlt_audio_format fmt = mlt_audio_pcm;
- int channels = 2;
- int frequency = mlt_properties_get_int( this_properties, "frequency" );
- int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count );
- int16_t *pcm = NULL;
-
- // Get the frame number
- time_t start = time( NULL );
- int height = mlt_properties_get_int( this_properties, "height" );
- int is_pal = height == 576;
- int is_wide = mlt_properties_get_int( this_properties, "display_aspect_num" ) == 16;
-
- // Temporary - audio buffer allocation
- int16_t *audio_buffers[ 4 ];
- int i = 0;
- int j = 0;
- for ( i = 0 ; i < 4; i ++ )
- audio_buffers[ i ] = mlt_pool_alloc( 2 * DV_AUDIO_MAX_SAMPLES );
-
- // Get the audio
- mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples );
-
- // Inform the encoder of the number of audio samples
- encoder->samples_this_frame = samples;
-
- // Fill the audio buffers correctly
- if ( mlt_properties_get_double( frame_properties, "_speed" ) == 1.0 )
- {
- for ( i = 0; i < samples; i ++ )
- for ( j = 0; j < channels; j++ )
- audio_buffers[ j ][ i ] = *pcm ++;
- }
- else
- {
- for ( j = 0; j < channels; j++ )
- memset( audio_buffers[ j ], 0, 2 * DV_AUDIO_MAX_SAMPLES );
- }
-
- // Encode audio on frame
- dv_encode_full_audio( encoder, audio_buffers, channels, frequency, dv_frame );
-
- // Specify meta data on the frame
- dv_encode_metadata( dv_frame, is_pal, is_wide, &start, count );
- dv_encode_timecode( dv_frame, is_pal, count );
-
- // Update properties
- mlt_properties_set_int( this_properties, "count", ++ count );
-
- // Temporary - free audio buffers
- for ( i = 0 ; i < 4; i ++ )
- mlt_pool_release( audio_buffers[ i ] );
- }
-}
-
-/** The libdv output method.
-*/
-
-static void consumer_output( mlt_consumer this, uint8_t *dv_frame, int size, mlt_frame frame )
-{
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- FILE *output = stdout;
- char *target = mlt_properties_get( properties, "target" );
-
- if ( target != NULL )
- {
- output = mlt_properties_get_data( properties, "output_file", NULL );
- if ( output == NULL )
- {
- output = fopen( target, "w" );
- if ( output != NULL )
- mlt_properties_set_data( properties, "output_file", output, 0, ( mlt_destructor )fclose, 0 );
- }
- }
-
- if ( output != NULL )
- {
- fwrite( dv_frame, size, 1, output );
- fflush( output );
- }
- else
- {
- fprintf( stderr, "Unable to open %s\n", target );
- }
-}
-
-/** The main thread - the argument is simply the consumer.
-*/
-
-static void *consumer_thread( void *arg )
-{
- // Map the argument to the object
- mlt_consumer this = arg;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get the terminate_on_pause property
- int top = mlt_properties_get_int( properties, "terminate_on_pause" );
-
- // Get the handling methods
- int ( *video )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "video", NULL );
- int ( *audio )( mlt_consumer, uint8_t *, mlt_frame ) = mlt_properties_get_data( properties, "audio", NULL );
- int ( *output )( mlt_consumer, uint8_t *, int, mlt_frame ) = mlt_properties_get_data( properties, "output", NULL );
-
- // Allocate a single PAL frame for encoding
- uint8_t *dv_frame = mlt_pool_alloc( FRAME_SIZE_625_50 );
-
- // Frame and size
- mlt_frame frame = NULL;
- int size = 0;
-
- // Loop while running
- while( mlt_properties_get_int( properties, "running" ) )
- {
- // Get the frame
- frame = mlt_consumer_rt_frame( this );
-
- // Check that we have a frame to work with
- if ( frame != NULL )
- {
- // Terminate on pause
- if ( top && mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0 )
- {
- mlt_frame_close( frame );
- break;
- }
-
- // Obtain the dv_encoder
- if ( libdv_get_encoder( this, frame ) != NULL )
- {
- // Encode the image
- 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" );
- }
- }
- }
-
- // Tidy up
- mlt_pool_release( dv_frame );
-
- mlt_consumer_stopped( this );
-
- return NULL;
-}
-
-/** Close the consumer.
-*/
-
-static void consumer_close( mlt_consumer this )
-{
- // Stop the consumer
- mlt_consumer_stop( this );
-
- // Close the parent
- mlt_consumer_close( this );
-
- // Free the memory
- free( this );
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-
-#include <framework/mlt.h>
-
-extern mlt_consumer consumer_libdv_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_libdv_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "libdv", consumer_libdv_init );
- MLT_REGISTER( producer_type, "libdv", producer_libdv_init );
-}
+++ /dev/null
-/*
- * producer_libdv.c -- simple libdv test case
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_deque.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_profile.h>
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <libdv/dv.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define FRAME_SIZE_525_60 10 * 150 * 80
-#define FRAME_SIZE_625_50 12 * 150 * 80
-
-/** To conserve resources, we maintain a stack of dv decoders.
-*/
-
-static pthread_mutex_t decoder_lock = PTHREAD_MUTEX_INITIALIZER;
-static mlt_properties dv_decoders = NULL;
-
-dv_decoder_t *dv_decoder_alloc( )
-{
- // We'll return a dv_decoder
- dv_decoder_t *this = NULL;
-
- // Lock the mutex
- pthread_mutex_lock( &decoder_lock );
-
- // Create the properties if necessary
- if ( dv_decoders == NULL )
- {
- // Create the properties
- dv_decoders = mlt_properties_new( );
-
- // Create the stack
- mlt_properties_set_data( dv_decoders, "stack", mlt_deque_init( ), 0, ( mlt_destructor )mlt_deque_close, NULL );
-
- // Register the properties for clean up
- mlt_factory_register_for_clean_up( dv_decoders, ( mlt_destructor )mlt_properties_close );
- }
-
- // Now try to obtain a decoder
- if ( dv_decoders != NULL )
- {
- // Obtain the stack
- mlt_deque stack = mlt_properties_get_data( dv_decoders, "stack", NULL );
-
- // Pop the top of the stack
- this = mlt_deque_pop_back( stack );
-
- // Create a new decoder if none available
- if ( this == NULL )
- {
- // We'll need a unique property ID for this
- char label[ 256 ];
-
- // Configure the decoder
- this = dv_decoder_new( FALSE, FALSE, FALSE );
- this->quality = DV_QUALITY_COLOR | DV_QUALITY_AC_2;
- this->audio->arg_audio_emphasis = 2;
- dv_set_audio_correction( this, DV_AUDIO_CORRECT_AVERAGE );
- dv_set_error_log( this, NULL );
-
- // Register it with the properties to ensure clean up
- sprintf( label, "%p", this );
- mlt_properties_set_data( dv_decoders, label, this, 0, ( mlt_destructor )dv_decoder_free, NULL );
- }
- }
-
- // Unlock the mutex
- pthread_mutex_unlock( &decoder_lock );
-
- return this;
-}
-
-void dv_decoder_return( dv_decoder_t *this )
-{
- // Lock the mutex
- pthread_mutex_lock( &decoder_lock );
-
- // Now try to return the decoder
- if ( dv_decoders != NULL )
- {
- // Obtain the stack
- mlt_deque stack = mlt_properties_get_data( dv_decoders, "stack", NULL );
-
- // Push it back
- mlt_deque_push_back( stack, this );
- }
-
- // Unlock the mutex
- pthread_mutex_unlock( &decoder_lock );
-}
-
-
-typedef struct producer_libdv_s *producer_libdv;
-
-struct producer_libdv_s
-{
- struct mlt_producer_s parent;
- int fd;
- int is_pal;
- uint64_t file_size;
- int frame_size;
- long frames_in_file;
- mlt_producer alternative;
-};
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-static int producer_collect_info( producer_libdv this, mlt_profile profile );
-
-mlt_producer producer_libdv_init( mlt_profile profile, mlt_service_type type, const char *id, char *filename )
-{
- producer_libdv this = calloc( sizeof( struct producer_libdv_s ), 1 );
-
- if ( filename != NULL && this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- int destroy = 0;
- mlt_producer producer = &this->parent;
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Set the resource property (required for all producers)
- mlt_properties_set( properties, "resource", filename );
-
- // Register transport implementation with the producer
- producer->close = ( mlt_destructor )producer_close;
-
- // Register our get_frame implementation with the producer
- producer->get_frame = producer_get_frame;
-
- // If we have mov or dv, then we'll use an alternative producer
- if ( strchr( filename, '.' ) != NULL && (
- strncasecmp( strrchr( filename, '.' ), ".avi", 4 ) == 0 ||
- strncasecmp( strrchr( filename, '.' ), ".mov", 4 ) == 0 ) )
- {
- // Load via an alternative mechanism
- mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) );
- this->alternative = mlt_factory_producer( profile, "kino", filename );
-
- // If it's unavailable, then clean up
- if ( this->alternative == NULL )
- destroy = 1;
- else
- mlt_properties_pass( properties, MLT_PRODUCER_PROPERTIES( this->alternative ), "" );
- this->is_pal = ( ( int ) mlt_producer_get_fps( producer ) ) == 25;
- }
- else
- {
- // Open the file if specified
- this->fd = open( filename, O_RDONLY );
-
- // Collect info
- if ( this->fd == -1 || !producer_collect_info( this, profile ) )
- destroy = 1;
- }
-
- // If we couldn't open the file, then destroy it now
- if ( destroy )
- {
- mlt_producer_close( producer );
- producer = NULL;
- }
-
- // Return the producer
- return producer;
- }
- free( this );
- return NULL;
-}
-
-static int read_frame( int fd, uint8_t* frame_buf, int *isPAL )
-{
- int result = read( fd, frame_buf, FRAME_SIZE_525_60 ) == FRAME_SIZE_525_60;
- if ( result )
- {
- *isPAL = ( frame_buf[3] & 0x80 );
- if ( *isPAL )
- {
- int diff = FRAME_SIZE_625_50 - FRAME_SIZE_525_60;
- result = read( fd, frame_buf + FRAME_SIZE_525_60, diff ) == diff;
- }
- }
-
- return result;
-}
-
-static int producer_collect_info( producer_libdv this, mlt_profile profile )
-{
- int valid = 0;
-
- uint8_t *dv_data = mlt_pool_alloc( FRAME_SIZE_625_50 );
-
- if ( dv_data != NULL )
- {
- // Read the first frame
- valid = read_frame( this->fd, dv_data, &this->is_pal );
-
- // If it looks like a valid frame, the get stats
- if ( valid )
- {
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
-
- // Get a dv_decoder
- dv_decoder_t *dv_decoder = dv_decoder_alloc( );
-
- // Determine the file size
- struct stat buf;
- fstat( this->fd, &buf );
-
- // Store the file size
- this->file_size = buf.st_size;
-
- // Determine the frame size
- this->frame_size = this->is_pal ? FRAME_SIZE_625_50 : FRAME_SIZE_525_60;
-
- // Determine the number of frames in the file
- this->frames_in_file = this->file_size / this->frame_size;
-
- // Calculate default in/out points
- int fps = 1000 * ( this->is_pal ? 25 : ( 30000.0 / 1001.0 ) );
- if ( ( int )( mlt_profile_fps( profile ) * 1000 ) == fps )
- {
- if ( this->frames_in_file > 0 )
- {
- mlt_properties_set_position( properties, "length", this->frames_in_file );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", this->frames_in_file - 1 );
- }
- }
- else
- {
- valid = 0;
- }
-
- // Parse the header for meta info
- dv_parse_header( dv_decoder, dv_data );
- mlt_properties_set_double( properties, "aspect_ratio",
- dv_format_wide( dv_decoder ) ? ( this->is_pal ? 118.0/81.0 : 40.0/33.0 ) : ( this->is_pal ? 59.0/54.0 : 10.0/11.0 ) );
- mlt_properties_set_double( properties, "source_fps", this->is_pal ? 25 : ( 30000.0 / 1001.0 ) );
- mlt_properties_set_int( properties, "meta.media.nb_streams", 2 );
- mlt_properties_set_int( properties, "video_index", 0 );
- mlt_properties_set( properties, "meta.media.0.stream.type", "video" );
- mlt_properties_set( properties, "meta.media.0.codec.name", "dvvideo" );
- mlt_properties_set( properties, "meta.media.0.codec.long_name", "DV (Digital Video)" );
- mlt_properties_set_int( properties, "audio_index", 1 );
- mlt_properties_set( properties, "meta.media.1.stream.type", "audio" );
- mlt_properties_set( properties, "meta.media.1.codec.name", "pcm_s16le" );
- mlt_properties_set( properties, "meta.media.1.codec.long_name", "signed 16-bit little-endian PCM" );
-
- // Return the decoder
- dv_decoder_return( dv_decoder );
- }
-
- mlt_pool_release( dv_data );
- }
-
- return valid;
-}
-
-static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- int pitches[3] = { 0, 0, 0 };
- uint8_t *pixels[3] = { NULL, NULL, NULL };
-
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get a dv_decoder
- dv_decoder_t *decoder = dv_decoder_alloc( );
-
- // Get the dv data
- uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL );
-
- // Get and set the quality request
- char *quality = mlt_frame_pop_service( this );
-
- if ( quality != NULL )
- {
- if ( strncmp( quality, "fast", 4 ) == 0 )
- decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_DC );
- else if ( strncmp( quality, "best", 4 ) == 0 )
- decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_2 );
- else
- decoder->quality = ( DV_QUALITY_COLOR | DV_QUALITY_AC_1 );
- }
-
- // Parse the header for meta info
- dv_parse_header( decoder, dv_data );
-
- // Assign width and height according to the frame
- *width = 720;
- *height = dv_data[ 3 ] & 0x80 ? 576 : 480;
-
- // Extract an image of the format requested
- if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p )
- {
- // Allocate an image
- uint8_t *image = mlt_pool_alloc( *width * ( *height + 1 ) * 2 );
-
- // Pass to properties for clean up
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Decode the image
- pitches[ 0 ] = *width * 2;
- pixels[ 0 ] = image;
- dv_decode_full_frame( decoder, dv_data, e_dv_color_yuv, pixels, pitches );
-
- // Assign result
- *buffer = image;
- *format = mlt_image_yuv422;
- }
- else
- {
- // Allocate an image
- uint8_t *image = mlt_pool_alloc( *width * ( *height + 1 ) * 3 );
-
- // Pass to properties for clean up
- mlt_properties_set_data( properties, "image", image, *width * ( *height + 1 ) * 3, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Decode the frame
- pitches[ 0 ] = 720 * 3;
- pixels[ 0 ] = image;
- dv_decode_full_frame( decoder, dv_data, e_dv_color_rgb, pixels, pitches );
-
- // Assign result
- *buffer = image;
- *format = mlt_image_rgb24;
- }
-
- // Return the decoder
- dv_decoder_return( decoder );
-
- return 0;
-}
-
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- int16_t *p;
- int i, j;
- int16_t *audio_channels[ 4 ];
-
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get a dv_decoder
- dv_decoder_t *decoder = dv_decoder_alloc( );
-
- // Get the dv data
- uint8_t *dv_data = mlt_properties_get_data( properties, "dv_data", NULL );
-
- // Parse the header for meta info
- dv_parse_header( decoder, dv_data );
-
- // 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 );
-
- // 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)
- mlt_frame_get_audio( this, buffer, format, frequency, channels, samples );
- }
-
- // Return the decoder
- dv_decoder_return( decoder );
-
- return 0;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Access the private data
- producer_libdv this = producer->child;
-
- // Will carry the frame data
- uint8_t *data = NULL;
-
- // Obtain the current frame number
- uint64_t position = mlt_producer_frame( producer );
-
- if ( this->alternative == NULL )
- {
- // Convert timecode to a file position (ensuring that we're on a frame boundary)
- uint64_t offset = position * this->frame_size;
-
- // Allocate space
- data = mlt_pool_alloc( FRAME_SIZE_625_50 );
-
- // Create an empty frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- // Seek and fetch
- if ( this->fd != 0 &&
- lseek( this->fd, offset, SEEK_SET ) == offset &&
- read_frame( this->fd, data, &this->is_pal ) )
- {
- // Pass the dv data
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "dv_data", data, FRAME_SIZE_625_50, ( mlt_destructor )mlt_pool_release, NULL );
- }
- else
- {
- mlt_pool_release( data );
- data = NULL;
- }
- }
- else
- {
- // Seek
- mlt_producer_seek( this->alternative, position );
-
- // Fetch
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( this->alternative ), frame, 0 );
-
- // Verify
- if ( *frame != NULL )
- data = mlt_properties_get_data( MLT_FRAME_PROPERTIES( *frame ), "dv_data", NULL );
- }
-
- if ( data != NULL )
- {
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Get a dv_decoder
- dv_decoder_t *dv_decoder = dv_decoder_alloc( );
-
- mlt_properties_set_int( properties, "test_image", 0 );
- mlt_properties_set_int( properties, "test_audio", 0 );
-
- // Update other info on the frame
- mlt_properties_set_int( properties, "width", 720 );
- mlt_properties_set_int( properties, "height", this->is_pal ? 576 : 480 );
- mlt_properties_set_int( properties, "real_width", 720 );
- mlt_properties_set_int( properties, "real_height", this->is_pal ? 576 : 480 );
- mlt_properties_set_int( properties, "top_field_first", !this->is_pal ? 0 : ( data[ 5 ] & 0x07 ) == 0 ? 0 : 1 );
-
- // Parse the header for meta info
- dv_parse_header( dv_decoder, data );
- //mlt_properties_set_int( properties, "progressive", dv_is_progressive( dv_decoder ) );
- mlt_properties_set_double( properties, "aspect_ratio",
- dv_format_wide( dv_decoder ) ? ( this->is_pal ? 118.0/81.0 : 40.0/33.0 ) : ( this->is_pal ? 59.0/54.0 : 10.0/11.0 ) );
-
-
- mlt_properties_set_int( properties, "frequency", dv_decoder->audio->frequency );
- mlt_properties_set_int( properties, "channels", dv_decoder->audio->num_channels );
-
- // Register audio callback
- if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "audio_index" ) > 0 )
- mlt_frame_push_audio( *frame, producer_get_audio );
-
- if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "video_index" ) > -1 )
- {
- // Push the quality string
- mlt_frame_push_service( *frame, mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "quality" ) );
-
- // Push the get_image method on to the stack
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Return the decoder
- dv_decoder_return( dv_decoder );
- }
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- // Obtain this
- producer_libdv this = parent->child;
-
- // Close the file
- if ( this->fd > 0 )
- close( this->fd );
-
- if ( this->alternative )
- mlt_producer_close( this->alternative );
-
- // Close the parent
- parent->close = NULL;
- mlt_producer_close( parent );
-
- // Free the memory
- free( this );
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmlteffectv$(LIBSUF)
-
-OBJS = factory.o \
- filter_burn.o \
- image.o \
- utils.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2007 Stephane Fillod
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt.h>
-#include <string.h>
-
-extern mlt_filter filter_burn_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "BurningTV", filter_burn_init );
- MLT_REGISTER( filter_type, "burningtv", filter_burn_init );
-}
+++ /dev/null
-/*
- * filter_burn.c -- burning filter
- * Copyright (C) 2007 Stephane Fillod
- *
- * Filter taken from EffecTV - Realtime Digital Video Effector
- * Copyright (C) 2001-2006 FUKUCHI Kentaro
- *
- * BurningTV - burns incoming objects.
- * Copyright (C) 2001-2002 FUKUCHI Kentaro
- *
- * Fire routine is taken from Frank Jan Sorensen's demo program.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "utils.h"
-
-
-#define MaxColor 120
-#define Decay 15
-#define MAGIC_THRESHOLD "50"
-
-static RGB32 palette[256];
-
-/* FIXME: endianess? */
-static void makePalette(void)
-{
- int i, r, g, b;
-
- for(i=0; i<MaxColor; i++) {
- HSItoRGB(4.6-1.5*i/MaxColor, (double)i/MaxColor, (double)i/MaxColor, &r, &g, &b);
- palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
- }
- for(i=MaxColor; i<256; i++) {
- if(r<255)r++;if(r<255)r++;if(r<255)r++;
- if(g<255)g++;
- if(g<255)g++;
- if(b<255)b++;
- if(b<255)b++;
- palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
- }
-}
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- RGB32 *background;
- unsigned char *diff;
- unsigned char *buffer;
-
- // Get the filter
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // Get the "Burn the foreground" value
- int burn_foreground = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "foreground" );
- int y_threshold = image_set_threshold_y(
- mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "threshold" ));
-
- // We'll process pixel by pixel
- int x = 0;
- int y = 0;
- int i;
-
- int video_width = *width;
- int video_height = *height;
- int video_area = video_width * video_height;
- // We need to create a new frame as this effect modifies the input
- RGB32 *dest = mlt_pool_alloc( video_area * sizeof(RGB32) );
- RGB32 *src = (RGB32*)dest;
-
- unsigned char v, w;
- RGB32 a, b;
-
- mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)dest, video_area);
-
-
- diff = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
- "_diff", NULL );
- if (diff == NULL)
- {
- diff = mlt_pool_alloc(video_area*sizeof(unsigned char));
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_diff",
- diff, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
- }
-
- buffer = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
- "_buffer", NULL );
- if (buffer == NULL)
- {
- buffer = mlt_pool_alloc(video_area*sizeof(unsigned char));
- memset(buffer, 0, video_area*sizeof(unsigned char));
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_buffer",
- buffer, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
- }
-
-
- if (burn_foreground == 1) {
- /* to burn the foreground, we need a background */
- background = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
- "_background", NULL );
- if (background == NULL)
- {
- background = mlt_pool_alloc(video_area*sizeof(RGB32));
- image_bgset_y(background, src, video_area, y_threshold);
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_background",
- background, video_area*sizeof(RGB32), mlt_pool_release, NULL );
- }
- }
-
- if (burn_foreground == 1) {
- image_bgsubtract_y(diff, background, src, video_area, y_threshold);
- } else {
- /* default */
- image_y_over(diff, src, video_area, y_threshold);
- }
-
- for(x=1; x<video_width-1; x++) {
- v = 0;
- for(y=0; y<video_height-1; y++) {
- w = diff[y*video_width+x];
- buffer[y*video_width+x] |= v ^ w;
- v = w;
- }
- }
- for(x=1; x<video_width-1; x++) {
- i = video_width + x;
- for(y=1; y<video_height; y++) {
- v = buffer[i];
- if(v<Decay)
- buffer[i-video_width] = 0;
- else
- buffer[i-video_width+fastrand()%3-1] = v - (fastrand()&Decay);
- i += video_width;
- }
- }
-
- i = 1;
- for(y=0; y<video_height; y++) {
- for(x=1; x<video_width-1; x++) {
- /* FIXME: endianess? */
- a = (src[i] & 0xfefeff) + palette[buffer[i]];
- b = a & 0x1010100;
- dest[i] = a | (b - (b >> 8));
- i++;
- }
- i += 2;
- }
-
- mlt_convert_rgb24a_to_yuv422((uint8_t *)dest, *width, *height, *width * sizeof(RGB32),
- *image, NULL );
-
- mlt_pool_release(dest);
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the frame filter
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_burn_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "foreground", "0" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "threshold", MAGIC_THRESHOLD );
- }
- if (!palette[128])
- {
- makePalette();
- }
- return this;
-}
-
+++ /dev/null
-/*
- * EffecTV - Realtime Digital Video Effector
- * Copyright (C) 2001-2006 FUKUCHI Kentaro
- *
- * image.c: utilities for image processing.
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include "utils.h"
-
-
-/*
- * Collection of background subtraction functions
- */
-
-/* checks only fake-Y value */
-/* In these function Y value is treated as R*2+G*4+B. */
-
-int image_set_threshold_y(int threshold)
-{
- int y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
-
- return y_threshold;
-}
-
-void image_bgset_y(RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
-{
- int i;
- int R, G, B;
- const RGB32 *p;
- short *q;
-
- p = src;
- q = (short *)background;
- for(i=0; i<video_area; i++) {
- /* FIXME: endianess */
-
- R = ((*p)&0xff0000)>>(16-1);
- G = ((*p)&0xff00)>>(8-2);
- B = (*p)&0xff;
- *q = (short)(R + G + B);
- p++;
- q++;
- }
-}
-
-void image_bgsubtract_y(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
-{
- int i;
- int R, G, B;
- const RGB32 *p;
- const short *q;
- unsigned char *r;
- int v;
-
- p = src;
- q = (const short *)background;
- r = diff;
- for(i=0; i<video_area; i++) {
- /* FIXME: endianess */
-
- R = ((*p)&0xff0000)>>(16-1);
- G = ((*p)&0xff00)>>(8-2);
- B = (*p)&0xff;
- v = (R + G + B) - (int)(*q);
- *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
-
- p++;
- q++;
- r++;
- }
-
-/* The origin of subtraction function is;
- * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
- *
- * This functions is transformed to;
- * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
- *
- * (v + threshold)>>24 is 0xff when v is less than -threshold.
- * (v - threshold)>>24 is 0xff when v is less than threshold.
- * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
- * abs(src - dest) > threshold.
- */
-}
-
-/* Background image is refreshed every frame */
-void image_bgsubtract_update_y(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
-{
- int i;
- int R, G, B;
- const RGB32 *p;
- short *q;
- unsigned char *r;
- int v;
-
- p = src;
- q = (short *)background;
- r = diff;
- for(i=0; i<video_area; i++) {
- /* FIXME: endianess */
-
- R = ((*p)&0xff0000)>>(16-1);
- G = ((*p)&0xff00)>>(8-2);
- B = (*p)&0xff;
- v = (R + G + B) - (int)(*q);
- *q = (short)(R + G + B);
- *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
-
- p++;
- q++;
- r++;
- }
-}
-
-/* checks each RGB value */
-
-/* The range of r, g, b are [0..7] */
-RGB32 image_set_threshold_RGB(int r, int g, int b)
-{
- unsigned char R, G, B;
- RGB32 rgb_threshold;
-
- R = G = B = 0xff;
- R = R<<r;
- G = G<<g;
- B = B<<b;
- rgb_threshold = (RGB32)(R<<16 | G<<8 | B);
-
- return rgb_threshold;
-}
-
-void image_bgset_RGB(RGB32 *background, const RGB32 *src, int video_area)
-{
- int i;
- RGB32 *p;
-
- p = background;
- for(i=0; i<video_area; i++) {
- *p++ = (*src++) & 0xfefefe;
- }
-}
-
-void image_bgsubtract_RGB(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
-{
- int i;
- const RGB32 *p, *q;
- unsigned a, b;
- unsigned char *r;
-
- p = src;
- q = background;
- r = diff;
- for(i=0; i<video_area; i++) {
- a = (*p++)|0x1010100;
- b = *q++;
- a = a - b;
- b = a & 0x1010100;
- b = b - (b>>8);
- b = b ^ 0xffffff;
- a = a ^ b;
- a = a & rgb_threshold;
- *r++ = (0 - a)>>24;
- }
-}
-
-void image_bgsubtract_update_RGB(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
-{
- int i;
- const RGB32 *p;
- RGB32 *q;
- unsigned a, b;
- unsigned char *r;
-
- p = src;
- q = background;
- r = diff;
- for(i=0; i<video_area; i++) {
- a = *p|0x1010100;
- b = *q&0xfefefe;
- *q++ = *p++;
- a = a - b;
- b = a & 0x1010100;
- b = b - (b>>8);
- b = b ^ 0xffffff;
- a = a ^ b;
- a = a & rgb_threshold;
- *r++ = (0 - a)>>24;
- }
-}
-
-/* noise filter for subtracted image. */
-void image_diff_filter(unsigned char *diff2, const unsigned char *diff, int width, int height)
-{
- int x, y;
- const unsigned char *src;
- unsigned char *dest;
- unsigned int count;
- unsigned int sum1, sum2, sum3;
-
- src = diff;
- dest = diff2 + width +1;
- for(y=1; y<height-1; y++) {
- sum1 = src[0] + src[width] + src[width*2];
- sum2 = src[1] + src[width+1] + src[width*2+1];
- src += 2;
- for(x=1; x<width-1; x++) {
- sum3 = src[0] + src[width] + src[width*2];
- count = sum1 + sum2 + sum3;
- sum1 = sum2;
- sum2 = sum3;
- *dest++ = (0xff*3 - count)>>24;
- src++;
- }
- dest += 2;
- }
-}
-
-/* Y value filters */
-void image_y_over(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
-{
- int i;
- int R, G, B, v;
- unsigned char *p = diff;
-
- for(i = video_area; i>0; i--) {
- R = ((*src)&0xff0000)>>(16-1);
- G = ((*src)&0xff00)>>(8-2);
- B = (*src)&0xff;
- v = y_threshold - (R + G + B);
- *p = (unsigned char)(v>>24);
- src++;
- p++;
- }
-}
-
-void image_y_under(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
-{
- int i;
- int R, G, B, v;
- unsigned char *p = diff;
-
- for(i = video_area; i>0; i--) {
- R = ((*src)&0xff0000)>>(16-1);
- G = ((*src)&0xff00)>>(8-2);
- B = (*src)&0xff;
- v = (R + G + B) - y_threshold;
- *p = (unsigned char)(v>>24);
- src++;
- p++;
- }
-}
-
-/* tiny edge detection */
-void image_edge(unsigned char *diff2, const RGB32 *src, int width, int height, int y_threshold)
-{
- int x, y;
- const unsigned char *p;
- unsigned char *q;
- int r, g, b;
- int ar, ag, ab;
- int w;
-
- p = (const unsigned char *)src;
- q = diff2;
- w = width * sizeof(RGB32);
-
- for(y=0; y<height - 1; y++) {
- for(x=0; x<width - 1; x++) {
- b = p[0];
- g = p[1];
- r = p[2];
- ab = abs(b - p[4]);
- ag = abs(g - p[5]);
- ar = abs(r - p[6]);
- ab += abs(b - p[w]);
- ag += abs(g - p[w+1]);
- ar += abs(r - p[w+2]);
- b = ab+ag+ar;
- if(b > y_threshold) {
- *q = 255;
- } else {
- *q = 0;
- }
- q++;
- p += 4;
- }
- p += 4;
- *q++ = 0;
- }
- memset(q, 0, width);
-}
-
-/* horizontal flipping */
-void image_hflip(const RGB32 *src, RGB32 *dest, int width, int height)
-{
- int x, y;
-
- src += width - 1;
- for(y=0; y<height; y++) {
- for(x=0; x<width; x++) {
- *dest++ = *src--;
- }
- src += width * 2;
- }
-}
-
+++ /dev/null
-/*
- * EffecTV - Realtime Digital Video Effector
- * Copyright (C) 2001-2006 FUKUCHI Kentaro
- *
- * utils.c: utilities
- *
- */
-
-#include <math.h>
-#include "utils.h"
-
-/*
- * HSI color system utilities
- */
-static int itrunc(double f)
-{
- int i;
-
- i=(int)f;
- if(i<0)i=0;
- if(i>255)i=255;
- return i;
-}
-
-void HSItoRGB(double H, double S, double I, int *r, int *g, int *b)
-{
- double T,Rv,Gv,Bv;
-
- Rv=1+S*sin(H-2*M_PI/3);
- Gv=1+S*sin(H);
- Bv=1+S*sin(H+2*M_PI/3);
- T=255.999*I/2;
- *r=itrunc(Rv*T);
- *g=itrunc(Gv*T);
- *b=itrunc(Bv*T);
-}
-
-/*
- * fastrand - fast fake random number generator
- * Warning: The low-order bits of numbers generated by fastrand()
- * are bad as random numbers. For example, fastrand()%4
- * generates 1,2,3,0,1,2,3,0...
- * You should use high-order bits.
- */
-#ifdef __DARWIN__
-static
-#endif
-unsigned int fastrand_val;
-
-unsigned int fastrand(void)
-{
- return (fastrand_val=fastrand_val*1103515245+12345);
-}
-
-void fastsrand(unsigned int seed)
-{
- fastrand_val = seed;
-}
+++ /dev/null
-/*
- * EffecTV - Realtime Digital Video Effector
- * Copyright (C) 2001-2006 FUKUCHI Kentaro
- *
- * utils.h: header file for utils
- *
- */
-
-#ifndef __UTILS_H__
-#define __UTILS_H__
-
-#include <inttypes.h>
-
-typedef uint32_t RGB32;
-
-/* DEFINE's by nullset@dookie.net */
-#define RED(n) ((n>>16) & 0x000000FF)
-#define GREEN(n) ((n>>8) & 0x000000FF)
-#define BLUE(n) ((n>>0) & 0x000000FF)
-#define RGB(r,g,b) ((0<<24) + (r<<16) + (g <<8) + (b))
-#define INTENSITY(n) ( ( (RED(n)+GREEN(n)+BLUE(n))/3))
-
-/* utils.c */
-void HSItoRGB(double H, double S, double I, int *r, int *g, int *b);
-
-#ifndef __DARWIN__
-extern unsigned int fastrand_val;
-#define inline_fastrand() (fastrand_val=fastrand_val*1103515245+12345)
-#endif
-unsigned int fastrand(void);
-void fastsrand(unsigned int);
-
-/* image.c */
-int image_set_threshold_y(int threshold);
-void image_bgset_y(RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
-void image_bgsubtract_y(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
-void image_bgsubtract_update_y(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
-RGB32 image_set_threshold_RGB(int r, int g, int b);
-void image_bgset_RGB(RGB32 *background, const RGB32 *src, int video_area);
-void image_bgsubtract_RGB(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold);
-void image_bgsubtract_update_RGB(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold);
-void image_diff_filter(unsigned char *diff2, const unsigned char *diff, int width, int height);
-void image_y_over(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold);
-void image_y_under(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold);
-void image_edge(unsigned char *diff2, const RGB32 *src, int width, int height, int y_threshold);
-void image_hflip(const RGB32 *src, RGB32 *dest, int width, int height);
-
-#endif /* __UTILS_H__ */
+++ /dev/null
-include ../../../config.mak
-
-all:
-
-depend:
-
-distclean:
-
-clean:
-
-install: all
- install -d $(DESTDIR)$(prefix)/share/mlt/feeds/PAL
- install -d $(DESTDIR)$(prefix)/share/mlt/feeds/NTSC
- install -m 644 PAL/*.* $(DESTDIR)$(prefix)/share/mlt/feeds/PAL
- install -m 644 NTSC/*.* $(DESTDIR)$(prefix)/share/mlt/feeds/NTSC
+++ /dev/null
-# This properties file describes the fx available to the data_feed and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-#
-# The titles filter definition
-#
-
-titles=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,70%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-
-#
-# The top titles filter definition
-#
-
-top-titles=region
-.description=Top Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,5%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.halign=centre
-.filter[1].composite.titles=1
-
-#
-# OK - Silly example...
-#
-
-tickertape=region
-.description=Tickertape
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0%,93%:100%x7%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=100%,0%:300%x100%:100;-1=-300%,0%:300%x100%:100
-.filter[1].producer.font=San 32
-.filter[1].composite.titles=1
-
-#
-# ETV Location
-#
-
-location=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,80:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=-100%,0%:100%x100%:100;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:0;24=0%,0%:100%x100%:0;49=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=center
-
-courtesy=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,115:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=-100%,0%:100%x100%:0;12=-100%,0%:100%x100%:0;37=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=ETV Exclusive
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:0;37=0%,0%:100%x100%:0;61=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=right
-
-exclusive=region
-.description=Exclusive
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=0,115:230x30
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=ETV Exclusive
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=right
-
-file_shot=region
-.description=Titles
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=590,160:80x25
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=File Shot
-.filter[1].producer.font=San 20
-.filter[1].composite.geometry=1%,1%:99%x99%:15;25=1%,1%:99%x99%:100
-.filter[1].composite.titles=0
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-special=region
-.description=Titles
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=465,375:255x35
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=100%,0%:100%x100%:0;49=100%,0%:100%x100%:0;74=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Special
-.filter[1].producer.font=San 24
-.filter[1].composite.geometry=100%,0%:100%x100%:0;49=100%,0%:100%x100%:0;74=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-ticker=region
-.description=Tickertape
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0,500:722x75
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c010100
-.filter[0].composite.geometry=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Ticker - provided for reference
-.filter[1].composite.geometry=0%,0%:100%x100%:100
-.filter[1].composite.titles=0
-.filter[1].producer.font=San 24
-.filter[1].composite.halign=centre
-.filter[1].composite.titles=1
-.filter[1].composite.valign=centre
-
-super=region
-.description=Transcription
-.properties.0=filter[1].producer.markup
-.properties.1=filter[2].producer.markup
-.properties.align=filter[1].composite.valign
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.properties.length[2]=filter[2].composite.out
-.period=2
-.composite.geometry=0,410:720x90
-.filter[0]=watermark
-.filter[0].resource=colour:0xbbbbbb00
-.filter[0].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[0].composite.titles=1
-.filter[0].composite.luma=%luma18.pgm
-.filter[0].composite.out=25
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=
-.filter[1].producer.font=San 32
-.filter[1].producer.fgcolour=0x6c0101ff
-.filter[1].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=top
-.filter[2]=watermark
-.filter[2].resource=pango:
-.filter[2].producer.markup=
-.filter[2].producer.font=San 32
-.filter[2].producer.fgcolour=0x6c0101ff
-.filter[2].composite.geometry=0%,0%:100%x100%:10;25=0%,0%:100%x100%:100
-.filter[2].composite.titles=1
-.filter[2].composite.halign=centre
-.filter[2].composite.valign=bottom
-
-obscure=region
-.description=Obscure
-.properties.geometry=composite.geometry
-.properties.resource=resource
-.properties.length[0]=composite.out
-.composite.geometry=
-.resource=rectangle
-.composite.refresh=1
-.filter[0]=obscure
-.filter[0].start=0,0:100%x100%
-
+++ /dev/null
-# This properties file describes the fx available to the data_feed and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-obscure=region
-.description=Obscure
-.properties.geometry=composite.geometry
-.properties.resource=resource
-.properties.length[0]=composite.out
-.composite.geometry=
-.resource=rectangle
-.composite.refresh=1
-.filter[0]=obscure
-.filter[0].start=0,0:100%x100%
-
+++ /dev/null
-border_left=watermark
-.description=Border Left
-.resource=colour:black
-.reverse=1
-.period=2
-.properties.length[0]=composite.out
-.composite.geometry=0,0:100%x100%;25=2.5%,17.5%:45%x45%
-.composite.halign=c
-.composite.valign=c
-.composite.fill=1
-
-border_right=watermark
-.description=Border Right
-.resource=colour:black
-.reverse=1
-.period=2
-.properties.length[0]=composite.out
-.composite.geometry=0,0:100%x100%;25=52.5%,17.5%:45%x45%
-.composite.halign=c
-.composite.valign=c
-.composite.fill=1
-
+++ /dev/null
-# This properties file describes the fx available to the data_send and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-#
-# The titles filter definition
-#
-
-titles=region
-.description=Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,70%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-
-#
-# The top titles filter definition
-#
-
-top-titles=region
-.description=Top Titles
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.period=2
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=5%,5%:90%x20%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[0].composite.geometry=0%,0%:100%x100%:0;5=0%,0%:100%x100%:40
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=0%,0%:100%x100%:0;8=0%,0%:100%x100%:100
-.filter[1].composite.titles=1
-
-#
-# OK - Silly example...
-#
-
-tickertape=region
-.description=Tickertape
-.properties.markup=filter[1].producer.markup
-.type.markup=text
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0%,93%:100%x7%
-.filter[0]=watermark
-.filter[0].resource=colour:0x000000
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.markup=Shotcut
-.filter[1].composite.geometry=100%,0%:300%x100%:100;-1=-300%,0%:300%x100%:100
-.filter[1].producer.font=San 32
-.filter[1].composite.titles=1
-
+++ /dev/null
-# This properties file describes the fx available to the data_feed and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-location=region
-.description=Titles
-.properties.markup=filter[1].producer.text
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.period=2
-.properties.length[0]=composite.out
-.composite.geometry=0,80:230x30:0;12=,:x:100
-.composite.luma=%luma01.pgm
-.composite.softness=.3
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=
-.filter[1].producer.font=Sans
-.filter[1].producer.size=24
-.filter[1].composite.geometry=0,0:95%x100%
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=center
-
-courtesy=region
-.description=Courtesy
-.properties.markup=filter[1].producer.text
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.period=2
-.properties.length[0]=composite.out
-.composite.geometry=0,115:230x30:0;12=,:x:100
-.composite.luma=%luma01.pgm
-.composite.softness=.3
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=
-.filter[1].producer.font=Sans
-.filter[1].producer.size=24
-.filter[1].composite.geometry=0,0:95%x100%
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=centre
-
-exclusive=region
-.description=Exclusive
-.properties.markup=filter[1].producer.text
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.period=2
-.properties.length[0]=composite.out
-.composite.geometry=-230,115:230x30;12=0
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=ETV Exclusive
-.filter[1].producer.font=Sans
-.filter[1].producer.size=24
-.filter[1].producer.weight=700
-.filter[1].composite.geometry=0,0:95%x100%
-.filter[1].composite.titles=1
-.filter[1].composite.halign=right
-.filter[1].composite.valign=centre
-
-file_shot=region
-.description=Titles
-.period=2
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.properties.length[0]=composite.out
-.composite.geometry=590,160:80x25:0;12=,:x:100
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=File Shot
-.filter[1].producer.font=Sans
-.filter[1].producer.size=18
-.filter[1].producer.weight=700
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-special=region
-.description=Special
-.period=2
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.properties.length[0]=filter[0].composite.out
-.properties.length[1]=filter[1].composite.out
-.composite.geometry=465,375:255x35
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.geometry=100%,0%:100%x100%:0;12=0%,0%:x:100
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=Special
-.filter[1].producer.font=Sans
-.filter[1].producer.size=24
-.filter[1].producer.weight=700
-.filter[1].composite.geometry=100%,0%:100%x100%:0;12=0%,0%:x:100
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-ticker=region
-.description=Tickertape
-.properties.markup=filter[1].producer.text
-.properties.font=filter[1].producer.font
-.properties.size=filter[1].producer.size
-.properties.length[0]=filter[1].composite.out
-.composite.geometry=0,500:722x75
-.filter[0]=watermark
-.filter[0].resource=colour:0x6c0101ff
-.filter[0].composite.titles=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=Ticker - provided for reference
-.filter[1].producer.font=Sans
-.filter[1].producer.size=24
-.filter[1].producer.weight=700
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=centre
-
-super=region
-.description=Transcription
-.properties.0=filter[1].producer.text
-.properties.1=filter[2].producer.text
-.properties.align=filter[1].composite.valign
-.properties.weight=filter[1].producer.weight
-.properties.f0=filter[1].producer.font
-.properties.s0=filter[1].producer.size
-.properties.f1=filter[2].producer.font
-.properties.s1=filter[2].producer.size
-.properties.length[0]=composite.out
-.period=2
-.composite.geometry=0,410:720x90:0;25=,:x:100
-.composite.luma=%luma01.pgm
-.composite.luma_invert=1
-.composite.softness=.3
-.filter[0]=watermark
-.filter[0].resource=colour:0xbbbbbbff
-.filter[0].composite.geometry=0,0:100%:100%:70
-.filter[0].composite.distort=1
-.filter[1]=watermark
-.filter[1].resource=pango:
-.filter[1].producer.text=
-.filter[1].producer.font=Sans
-.filter[1].producer.size=32
-.filter[1].producer.weight=700
-.filter[1].producer.fgcolour=0x6c0101ff
-.filter[1].composite.titles=1
-.filter[1].composite.halign=centre
-.filter[1].composite.valign=top
-.filter[2]=watermark
-.filter[2].resource=pango:
-.filter[2].producer.text=
-.filter[2].producer.font=Sans
-.filter[2].producer.size=32
-.filter[2].producer.fgcolour=0x6c0101ff
-.filter[2].composite.titles=1
-.filter[2].composite.halign=centre
-.filter[2].composite.valign=bottom
-
+++ /dev/null
-greyscale=greyscale
-.description=Greyscale
-
-sepia=sepia
-.description=Sepia
-
-charcoal=charcoal
-.description=Charcoal
-
-invert=invert
-.description=Invert
-
+++ /dev/null
-# This properties file describes the fx available to the data_feed and
-# data_show filters
-#
-# Syntax is as follows:
-#
-# name=<filter>
-# name.description=<user defined>
-# name.properties.<variable>=<full-property>
-# name.<property>=value
-# etc
-#
-# Typically, the <filter> is a 'region' and additional filters are
-# included as properties using the normal region filter syntax.
-#
-
-obscure0=region
-.description=Primary Obscure
-.properties.geometry=composite.geometry
-.properties.resource=resource
-.properties.length[0]=composite.out
-.composite.geometry=
-.resource=rectangle
-.composite.refresh=1
-.filter[0]=obscure
-
-obscure1=region
-.description=Secondary Obscure
-.properties.geometry=composite.geometry
-.properties.resource=resource
-.properties.length[0]=composite.out
-.composite.geometry=
-.resource=rectangle
-.composite.refresh=1
-.filter[0]=obscure
-
+++ /dev/null
-http://*=avformat
-<?xml*=westley-xml
-*.westley=westley
-*.kdenlive=westley
-*.inigo=inigo_file
-*.asf=avformat
-*.avi=mcdv,avformat,libdv
-*.bmp=pixbuf,qimage,sdl_image
-*.dv=mcdv,avformat,libdv
-*.dif=mcdv,avformat,libdv
-*.exr=qimage
-*.gif=pixbuf,qimage,sdl_image
-*.graphics=westley
-*.jfx=westley
-*.jef=westley
-*.jpg=pixbuf,qimage,sdl_image
-*.jpeg=pixbuf,qimage,sdl_image
-*.kino=westley
-*.mp3=avformat
-*.mov=mcdv,avformat,libdv
-*.mpg=mcmpeg,avformat
-*.mpeg=mcmpeg,avformat
-*.mpl=pango
-*.ogg=avformat,vorbis
-*.pcx=pixbuf,qimage,sdl_image
-*.pgm=pgm,pixbuf,qimage,sdl_image
-*.png=pixbuf,qimage,sdl_image
-*.psd=qimage
-*.story=westley
-*.svg=pixbuf,qimage
-*.tga=pixbuf,qimage,sdl_image
-*.tif=pixbuf,qimage,sdl_image
-*.tiff=pixbuf,qimage,sdl_image
-*.txt=pango
-*.vob=mcmpeg,avformat
-*.wav=avformat
-*.wmv=avformat
-*.xcf=qimage,sdl_image
-*=avformat
+++ /dev/null
-# This file defines the normalisers, their fallbacks and the order they're attached
-#
-# The names on the left are arbitrary, but the order in which they occur is the
-# order in which they're applied.
-#
-# The names of the services on the right dictate the preference used (if unavailable
-# the second and third are applied as applicable).
-
-crop=crop:1
-deinterlace=deinterlace,avdeinterlace
-rescaler=mcrescale,gtkrescale,rescale,swscale
-resizer=resize
-resampler=resample,soxresample,avresample
-data=data_feed:attr_check
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltfezzik$(LIBSUF)
-
-OBJS = factory.o \
- producer_fezzik.o \
- producer_hold.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
- install -m 644 ../fezzik.dict "$(DESTDIR)$(prefix)/share/mlt"
- install -m 644 ../fezzik.ini "$(DESTDIR)$(prefix)/share/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-#include <string.h>
-
-extern mlt_producer producer_fezzik_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_hold_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( producer_type, "fezzik", producer_fezzik_init );
- MLT_REGISTER( producer_type, "hold", producer_hold_init );
-}
+++ /dev/null
-/*
- * producer_fezzik.c -- a normalising filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <fnmatch.h>
-#include <assert.h>
-
-#include <framework/mlt.h>
-
-static mlt_properties dictionary = NULL;
-static mlt_properties normalisers = NULL;
-
-static mlt_producer create_from( mlt_profile profile, char *file, char *services )
-{
- mlt_producer producer = NULL;
- char *temp = strdup( services );
- char *service = temp;
- do
- {
- char *p = strchr( service, ',' );
- if ( p != NULL )
- *p ++ = '\0';
- producer = mlt_factory_producer( profile, service, file );
- service = p;
- }
- while ( producer == NULL && service != NULL );
- free( temp );
- return producer;
-}
-
-static mlt_producer create_producer( mlt_profile profile, char *file )
-{
- mlt_producer result = NULL;
-
- // 1st Line - check for service:resource handling
- if ( strchr( file, ':' ) )
- {
- char *temp = strdup( file );
- char *service = temp;
- char *resource = strchr( temp, ':' );
- *resource ++ = '\0';
- result = mlt_factory_producer( profile, service, resource );
- free( temp );
- }
-
- // 2nd Line preferences
- if ( result == NULL )
- {
- int i = 0;
- char *lookup = strdup( file );
- char *p = lookup;
-
- // We only need to load the dictionary once
- if ( dictionary == NULL )
- {
- char temp[ 1024 ];
- sprintf( temp, "%s/fezzik.dict", mlt_environment( "MLT_DATA" ) );
- dictionary = mlt_properties_load( temp );
- mlt_factory_register_for_clean_up( dictionary, ( mlt_destructor )mlt_properties_close );
- }
-
- // Convert the lookup string to lower case
- while ( *p )
- {
- *p = tolower( *p );
- p ++;
- }
-
- // Iterate through the dictionary
- for ( i = 0; result == NULL && i < mlt_properties_count( dictionary ); i ++ )
- {
- char *name = mlt_properties_get_name( dictionary, i );
- if ( fnmatch( name, lookup, 0 ) == 0 )
- result = create_from( profile, file, mlt_properties_get_value( dictionary, i ) );
- }
-
- free( lookup );
- }
-
- // Finally, try just loading as service
- if ( result == NULL )
- result = mlt_factory_producer( profile, file, NULL );
-
- return result;
-}
-
-static void create_filter( mlt_profile profile, mlt_producer producer, char *effect, int *created )
-{
- // The swscale filter can not handle images with a width > 2048 and the
- // sdl_image producer does not scale on its own
- if ( strncmp( effect, "swscale", 7 ) == 0 &&
- mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "_real_width" ) > 2048 &&
- strcmp( mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "mlt_service" ), "sdl_image" ) == 0 )
- return;
-
- char *id = strdup( effect );
- char *arg = strchr( id, ':' );
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_filter filter = mlt_factory_filter( profile, id, arg );
- if ( filter != NULL )
- {
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_fezzik", 1 );
- mlt_producer_attach( producer, filter );
- mlt_filter_close( filter );
- *created = 1;
- }
- free( id );
-}
-
-static void attach_normalisers( mlt_profile profile, mlt_producer producer )
-{
- // Loop variable
- int i;
-
- // Tokeniser
- mlt_tokeniser tokeniser = mlt_tokeniser_init( );
-
- // We only need to load the normalising properties once
- if ( normalisers == NULL )
- {
- char temp[ 1024 ];
- sprintf( temp, "%s/fezzik.ini", mlt_environment( "MLT_DATA" ) );
- normalisers = mlt_properties_load( temp );
- mlt_factory_register_for_clean_up( normalisers, ( mlt_destructor )mlt_properties_close );
- }
-
- // Apply normalisers
- for ( i = 0; i < mlt_properties_count( normalisers ); i ++ )
- {
- int j = 0;
- int created = 0;
- char *value = mlt_properties_get_value( normalisers, i );
- mlt_tokeniser_parse_new( tokeniser, value, "," );
- for ( j = 0; !created && j < mlt_tokeniser_count( tokeniser ); j ++ )
- create_filter( profile, producer, mlt_tokeniser_get_string( tokeniser, j ), &created );
- }
-
- // Close the tokeniser
- mlt_tokeniser_close( tokeniser );
-}
-
-mlt_producer producer_fezzik_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the producer
- mlt_producer producer = NULL;
- mlt_properties properties = NULL;
-
- if ( arg != NULL )
- producer = create_producer( profile, arg );
-
- if ( producer != NULL )
- properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Attach filters if we have a producer and it isn't already westley'd :-)
- if ( producer != NULL && mlt_properties_get( properties, "westley" ) == NULL && \
- mlt_properties_get( properties, "_westley" ) == NULL && \
- mlt_properties_get( properties, "fezzik_normalised" ) == NULL )
- attach_normalisers( profile, producer );
-
- // Now make sure we don't lose our identity
- if ( properties != NULL )
- mlt_properties_set_int( properties, "_mlt_service_hidden", 1 );
-
- // Return the producer
- return producer;
-}
+++ /dev/null
-/*
- * producer_hold.c -- frame holding producer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <framework/mlt.h>
-
-// Forward references
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer this );
-
-/** Constructor for the frame holding producer. Basically, all this producer does is
- provide a producer wrapper for the requested producer, allows the specifcation of
- the frame required and will then repeatedly obtain that frame for each get_frame
- and get_image requested.
-*/
-
-mlt_producer producer_hold_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Construct a new holding producer
- mlt_producer this = mlt_producer_new( );
-
- // Construct the requested producer via fezzik
- mlt_producer producer = mlt_factory_producer( profile, "fezzik", arg );
-
- // Initialise the frame holding capabilities
- if ( this != NULL && producer != NULL )
- {
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Store the producer
- mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
-
- // Set frame, in, out and length for this producer
- mlt_properties_set_position( properties, "frame", 0 );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", 25 );
- mlt_properties_set_position( properties, "length", 15000 );
- mlt_properties_set( properties, "resource", arg );
- mlt_properties_set( properties, "method", "onefield" );
-
- // Override the get_frame method
- this->get_frame = producer_get_frame;
- this->close = ( mlt_destructor )producer_close;
- }
- else
- {
- // Clean up (not sure which one failed, can't be bothered to find out, so close both)
- if ( this )
- mlt_producer_close( this );
- if ( producer )
- mlt_producer_close( producer );
-
- // Make sure we return NULL
- this = NULL;
- }
-
- // Return this producer
- return this;
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the real frame
- mlt_frame real_frame = mlt_frame_pop_service( frame );
-
- // Get the image from the real frame
- int size = 0;
- *buffer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( real_frame ), "image", &size );
- *width = mlt_properties_get_int( MLT_FRAME_PROPERTIES( real_frame ), "width" );
- *height = mlt_properties_get_int( MLT_FRAME_PROPERTIES( real_frame ), "height" );
-
- // If this is the first time, get it from the producer
- if ( *buffer == NULL )
- {
- mlt_properties_pass( MLT_FRAME_PROPERTIES( real_frame ), properties, "" );
-
- // We'll deinterlace on the downstream deinterlacer
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( real_frame ), "consumer_deinterlace", 1 );
-
- // We want distorted to ensure we don't hit the resize filter twice
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( real_frame ), "distort", 1 );
-
- // Get the image
- mlt_frame_get_image( real_frame, buffer, format, width, height, writable );
-
- // Make sure we get the size
- *buffer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( real_frame ), "image", &size );
- }
-
- mlt_properties_pass( properties, MLT_FRAME_PROPERTIES( real_frame ), "" );
-
- // Set the values obtained on the frame
- if ( *buffer != NULL )
- {
- uint8_t *image = mlt_pool_alloc( size );
- memcpy( image, *buffer, size );
- *buffer = image;
- mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );
- }
- else
- {
- // Pass the current image as is
- mlt_properties_set_data( properties, "image", *buffer, size, NULL, NULL );
- }
-
- // Make sure that no further scaling is done
- mlt_properties_set( properties, "rescale.interps", "none" );
- mlt_properties_set( properties, "scale", "off" );
-
- // All done
- return 0;
-}
-
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Construct a new frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-
- // If we have a frame, then stack the producer itself and the get_image method
- if ( *frame != NULL )
- {
- // Define the real frame
- mlt_frame real_frame = mlt_properties_get_data( properties, "real_frame", NULL );
-
- // Obtain real frame if we don't have it
- if ( real_frame == NULL )
- {
- // Get the producer
- mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // Get the frame position requested
- mlt_position position = mlt_properties_get_position( properties, "frame" );
-
- // Seek the producer to the correct place
- mlt_producer_seek( producer, position );
-
- // Get the real frame
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &real_frame, index );
-
- // Ensure that the real frame gets wiped eventually
- mlt_properties_set_data( properties, "real_frame", real_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
- else
- {
- // Temporary fix - ensure that we aren't seen as a test frame
- int8_t *image = mlt_properties_get_data( MLT_FRAME_PROPERTIES( real_frame ), "image", NULL );
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( *frame ), "image", image, 0, NULL, NULL );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", 0 );
- }
-
- // Stack the real frame and method
- mlt_frame_push_service( *frame, real_frame );
- mlt_frame_push_service( *frame, producer_get_image );
-
- // Ensure that the consumer sees what the real frame has
- mlt_properties_pass( MLT_FRAME_PROPERTIES( *frame ), MLT_FRAME_PROPERTIES( real_frame ), "" );
-
- mlt_properties_set( MLT_FRAME_PROPERTIES( real_frame ), "deinterlace_method",
- mlt_properties_get( properties, "method" ) );
- }
-
- // Move to the next position
- mlt_producer_prepare_next( this );
-
- return 0;
-}
-
-static void producer_close( mlt_producer this )
-{
- this->close = NULL;
- mlt_producer_close( this );
- free( this );
-}
-
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltfrei0r$(LIBSUF)
-
-OBJS = factory.o \
- producer_frei0r.o \
- filter_frei0r.o \
- transition_frei0r.o \
- frei0r_helper.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += -lm
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#! /bin/sh
-
-if [ "$help" != "1" ]
-then
-
- echo "#include <frei0r.h> int main(){ f0r_plugin_info_t test; test.name;return 0;}"| gcc $CFLAGS -c -x c - >/dev/null 2>&1
-
- if [ "$?" = "1" ]
- then
- touch ../disable-frei0r
- echo "- frei0r plugin disabled. Install frei0r-plugins and make sure frei0r.h is available."
- fi
-
-fi
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-#include <frei0r.h>
-
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#define FREI0R_PLUGIN_PATH "/usr/lib/frei0r-1:/usr/local/lib/frei0r-1:/usr/lib64/frei0r-1:/opt/local/lib/frei0r-1"
-
-extern mlt_filter filter_frei0r_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_frame filter_process( mlt_filter this, mlt_frame frame );
-extern void filter_close( mlt_filter this );
-extern int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
-extern void producer_close( mlt_producer this );
-extern void transition_close( mlt_transition this );
-extern mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame );
-
-static mlt_properties fill_param_info ( mlt_service_type type, const char *service_name, char *name )
-{
- char file[ PATH_MAX ];
- char servicetype[ 1024 ]="";
- struct stat stat_buff;
-
- switch ( type ) {
- case producer_type:
- strcpy ( servicetype , "producer" );
- break;
- case filter_type:
- strcpy ( servicetype , "filter" );
- break;
- case transition_type:
- strcpy ( servicetype , "transition" ) ;
- break;
- default:
- strcpy ( servicetype , "" );
- };
-
- snprintf( file, PATH_MAX, "%s/frei0r/%s_%s.yml", mlt_environment( "MLT_DATA" ), servicetype, service_name );
- stat(file,&stat_buff);
-
- if (S_ISREG(stat_buff.st_mode)){
- return mlt_properties_parse_yaml( file );
- }
-
- void* handle=dlopen(name,RTLD_LAZY);
- if (!handle) return NULL;
- void (*plginfo)(f0r_plugin_info_t*)=dlsym(handle,"f0r_get_plugin_info");
- void (*param_info)(f0r_param_info_t*,int param_index)=dlsym(handle,"f0r_get_param_info");
- if (!plginfo || !param_info) {
- dlclose(handle);
- return NULL;
- }
- mlt_properties metadata = mlt_properties_new();
- f0r_plugin_info_t info;
- char string[48];
- int j=0;
-
- plginfo(&info);
- snprintf ( string, sizeof(string) , "%d.%d" , info.major_version , info.minor_version );
- mlt_properties_set ( metadata, "schema_version" , "0.1" );
- mlt_properties_set ( metadata, "title" , info.name );
- mlt_properties_set ( metadata, "version", string );
- mlt_properties_set ( metadata, "identifier" , service_name );
- mlt_properties_set ( metadata, "description" , info.explanation );
- mlt_properties_set ( metadata, "creator" , info.author );
- switch (type){
- case producer_type:
- mlt_properties_set ( metadata, "type" , "producer" );
- break;
- case filter_type:
- mlt_properties_set ( metadata, "type" , "filter" );
- break;
- case transition_type:
- mlt_properties_set ( metadata, "type" , "transition" );
- break;
- default:
- break;
- }
-
- mlt_properties parameter = mlt_properties_new ( );
- mlt_properties_set_data ( metadata , "parameters" , parameter , 0 , ( mlt_destructor )mlt_properties_close, NULL );
- mlt_properties tags = mlt_properties_new ( );
- mlt_properties_set_data ( metadata , "tags" , tags , 0 , ( mlt_destructor )mlt_properties_close, NULL );
- mlt_properties_set ( tags , "0" , "Video" );
-
- for (j=0;j<info.num_params;j++){
- snprintf ( string , sizeof(string), "%d" , j );
- mlt_properties pnum = mlt_properties_new ( );
- mlt_properties_set_data ( parameter , string , pnum , 0 , ( mlt_destructor )mlt_properties_close, NULL );
- f0r_param_info_t paraminfo;
- param_info(¶minfo,j);
- mlt_properties_set ( pnum , "identifier" , paraminfo.name );
- mlt_properties_set ( pnum , "title" , paraminfo.name );
- mlt_properties_set ( pnum , "description" , paraminfo.explanation);
- if ( paraminfo.type == F0R_PARAM_DOUBLE ){
- mlt_properties_set ( pnum , "type" , "float" );
- mlt_properties_set ( pnum , "minimum" , "0" );
- mlt_properties_set ( pnum , "maximum" , "1" );
- mlt_properties_set ( pnum , "readonly" , "no" );
- mlt_properties_set ( pnum , "widget" , "spinner" );
- }else
- if ( paraminfo.type == F0R_PARAM_BOOL ){
- mlt_properties_set ( pnum , "type" , "boolean" );
- mlt_properties_set ( pnum , "minimum" , "0" );
- mlt_properties_set ( pnum , "maximum" , "1" );
- mlt_properties_set ( pnum , "readonly" , "no" );
- }else
- if ( paraminfo.type == F0R_PARAM_COLOR ){
- mlt_properties_set ( pnum , "type" , "color" );
- mlt_properties_set ( pnum , "readonly" , "no" );
- }else
- if ( paraminfo.type == F0R_PARAM_STRING ){
- mlt_properties_set ( pnum , "type" , "string" );
- mlt_properties_set ( pnum , "readonly" , "no" );
- }
- }
- dlclose(handle);
- free(name);
-
- return metadata;
-}
-
-static void * load_lib( mlt_profile profile, mlt_service_type type , void* handle){
-
- int i=0;
- void (*f0r_get_plugin_info)(f0r_plugin_info_t*),
- *f0r_construct , *f0r_update , *f0r_destruct,
- (*f0r_get_param_info)(f0r_param_info_t* info, int param_index),
- (*f0r_init)(void) , *f0r_deinit ,
- (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index),
- (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index),
- (*f0r_update2) (f0r_instance_t instance, double time, const uint32_t* inframe1,
- const uint32_t* inframe2,const uint32_t* inframe3, uint32_t* outframe);
-
- if ( ( f0r_construct = dlsym(handle, "f0r_construct") ) &&
- (f0r_update = dlsym(handle,"f0r_update") ) &&
- (f0r_destruct = dlsym(handle,"f0r_destruct") ) &&
- (f0r_get_plugin_info = dlsym(handle,"f0r_get_plugin_info") ) &&
- (f0r_get_param_info = dlsym(handle,"f0r_get_param_info") ) &&
- (f0r_set_param_value= dlsym(handle,"f0r_set_param_value" ) ) &&
- (f0r_get_param_value= dlsym(handle,"f0r_get_param_value" ) ) &&
- (f0r_init= dlsym(handle,"f0r_init" ) ) &&
- (f0r_deinit= dlsym(handle,"f0r_deinit" ) )
- ){
-
- f0r_update2=dlsym(handle,"f0r_update2");
-
- f0r_plugin_info_t info;
- f0r_get_plugin_info(&info);
-
- void* ret=NULL;
- mlt_properties properties=NULL;
-
- if (type == producer_type && info.plugin_type == F0R_PLUGIN_TYPE_SOURCE ){
- mlt_producer this = mlt_producer_new( );
- if ( this != NULL )
- {
- this->get_frame = producer_get_frame;
- this->close = ( mlt_destructor )producer_close;
- f0r_init();
- properties=MLT_PRODUCER_PROPERTIES ( this );
-
- for (i=0;i<info.num_params;i++){
- f0r_param_info_t pinfo;
- f0r_get_param_info(&pinfo,i);
-
- }
-
- ret=this;
- }
- } else if (type == filter_type && info.plugin_type == F0R_PLUGIN_TYPE_FILTER ){
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- this->close = filter_close;
- f0r_init();
- properties=MLT_FILTER_PROPERTIES ( this );
-
- for (i=0;i<info.num_params;i++){
- f0r_param_info_t pinfo;
- f0r_get_param_info(&pinfo,i);
-
- }
-
- ret=this;
- }
- }else if (type == transition_type && info.plugin_type == F0R_PLUGIN_TYPE_MIXER2){
- mlt_transition transition = mlt_transition_new( );
- if ( transition != NULL )
- {
- transition->process = transition_process;
- transition->close = transition_close;
- properties=MLT_TRANSITION_PROPERTIES( transition );
- mlt_properties_set_int(properties, "_transition_type", 1 );
-
- ret=transition;
- }
- }
- mlt_properties_set_data(properties, "_dlclose_handle", handle , sizeof (void*) , NULL , NULL );
- mlt_properties_set_data(properties, "_dlclose", dlclose , sizeof (void*) , NULL , NULL );
- mlt_properties_set_data(properties, "f0r_construct", f0r_construct , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_update", f0r_update , sizeof(void*),NULL,NULL);
- if (f0r_update2)
- mlt_properties_set_data(properties, "f0r_update2", f0r_update2 , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_destruct", f0r_destruct , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_get_plugin_info", f0r_get_plugin_info , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_get_param_info", f0r_get_param_info , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_set_param_value", f0r_set_param_value , sizeof(void*),NULL,NULL);
- mlt_properties_set_data(properties, "f0r_get_param_value", f0r_get_param_value , sizeof(void*),NULL,NULL);
-
-
- return ret;
- }else{
- printf("some was wrong\n");
- dlerror();
- }
- return NULL;
-}
-
-static void * create_frei0r_item ( mlt_profile profile, mlt_service_type type, const char *id, void *arg){
-
- mlt_tokeniser tokeniser = mlt_tokeniser_init ( );
- int dircount=mlt_tokeniser_parse_new (
- tokeniser,
- getenv("MLT_FREI0R_PLUGIN_PATH") ? getenv("MLT_FREI0R_PLUGIN_PATH") : FREI0R_PLUGIN_PATH,
- ":"
- );
- void* ret=NULL;
- while (dircount--){
- char soname[1024]="";
-
- char *save_firstptr = NULL;
- char *firstname=strtok_r(strdup(id),".",&save_firstptr);
-
- firstname=strtok_r(NULL,".",&save_firstptr);
- sprintf(soname,"%s/%s.so", mlt_tokeniser_get_string( tokeniser , dircount ) , firstname );
-
- if (firstname){
-
- void* handle=dlopen(soname,RTLD_LAZY);
-
- if (handle ){
- ret=load_lib ( profile , type , handle );
- }else{
- dlerror();
- }
- }
- }
- mlt_tokeniser_close ( tokeniser );
- return ret;
-}
-
-
-MLT_REPOSITORY
-{
- int i=0;
- mlt_tokeniser tokeniser = mlt_tokeniser_init ( );
- int dircount=mlt_tokeniser_parse_new (
- tokeniser ,
- getenv("MLT_FREI0R_PLUGIN_PATH") ? getenv("MLT_FREI0R_PLUGIN_PATH") : FREI0R_PLUGIN_PATH,
- ":"
- );
-
- while (dircount--){
-
- mlt_properties direntries = mlt_properties_new();
- char* dirname = mlt_tokeniser_get_string ( tokeniser , dircount ) ;
- mlt_properties_dir_list(direntries, dirname ,"*.so",1);
-
- for (i=0;i<mlt_properties_count(direntries);i++){
- char* name=mlt_properties_get_value(direntries,i);
- char* shortname=name+strlen(dirname)+1;
- char fname[1024]="";
-
- strcat(fname,dirname);
- strcat(fname,shortname);
-
- char *save_firstptr = NULL;
- char pluginname[1024]="frei0r.";
- char* firstname = strtok_r ( shortname , "." , &save_firstptr );
- strcat(pluginname,firstname);
-
- void* handle=dlopen(strcat(name,".so"),RTLD_LAZY);
- if (handle){
- void (*plginfo)(f0r_plugin_info_t*)=dlsym(handle,"f0r_get_plugin_info");
-
- if (plginfo){
- f0r_plugin_info_t info;
- plginfo(&info);
- if (firstname && info.plugin_type==F0R_PLUGIN_TYPE_SOURCE){
- MLT_REGISTER( producer_type, pluginname, create_frei0r_item );
- MLT_REGISTER_METADATA( producer_type, pluginname, fill_param_info, strdup(name) );
- }
- else if (firstname && info.plugin_type==F0R_PLUGIN_TYPE_FILTER){
- MLT_REGISTER( filter_type, pluginname, create_frei0r_item );
- MLT_REGISTER_METADATA( filter_type, pluginname, fill_param_info, strdup(name) );
- }
- else if (firstname && info.plugin_type==F0R_PLUGIN_TYPE_MIXER2 ){
- MLT_REGISTER( transition_type, pluginname, create_frei0r_item );
- MLT_REGISTER_METADATA( transition_type, pluginname, fill_param_info, strdup(name) );
- }
- }
- dlclose(handle);
- }
- }
- mlt_properties_close(direntries);
- }
- mlt_tokeniser_close ( tokeniser );
-}
+++ /dev/null
-/*
- * filter_frei0r.c -- frei0r filter
- * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-
-#include "frei0r_helper.h"
-#include <string.h>
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- mlt_position in = mlt_filter_get_in( filter );
- mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
-
- process_frei0r_item( filter_type , position, MLT_FILTER_PROPERTIES ( filter ), this , image, format , width , height , writable );
-
- }
-
- return error;
-}
-
-
-mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-void filter_close( mlt_filter this ){
-
- destruct( MLT_FILTER_PROPERTIES ( this ) );
-
-}
+++ /dev/null
-/*
- * frei0r_helper.c -- frei0r helper
- * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "frei0r_helper.h"
-#include <frei0r.h>
-#include <string.h>
-#include <stdlib.h>
-
-static void parse_color( int color, f0r_param_color_t *fcolor )
-{
- fcolor->r = ( color >> 24 ) & 0xff;
- fcolor->r /= 255;
- fcolor->g = ( color >> 16 ) & 0xff;
- fcolor->g /= 255;
- fcolor->b = ( color >> 8 ) & 0xff;
- fcolor->b /= 255;
-}
-
-int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){
-
- int i=0;
- f0r_instance_t ( *f0r_construct ) ( unsigned int , unsigned int ) = mlt_properties_get_data( prop , "f0r_construct" ,NULL);
- void (*f0r_update)(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)=mlt_properties_get_data( prop , "f0r_update" ,NULL);
- void (*f0r_destruct)(f0r_instance_t instance)=mlt_properties_get_data( prop , "f0r_destruct" ,NULL);
-
- void (*f0r_get_plugin_info)(f0r_plugin_info_t*)=mlt_properties_get_data( prop, "f0r_get_plugin_info" ,NULL);
- void (*f0r_get_param_info)(f0r_param_info_t* info, int param_index)=mlt_properties_get_data( prop , "f0r_get_param_info" ,NULL);
- void (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index)=mlt_properties_get_data( prop , "f0r_set_param_value" ,NULL);
- void (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index)=mlt_properties_get_data( prop , "f0r_get_param_value" ,NULL);
- void (*f0r_update2) (f0r_instance_t instance, double time,
- const uint32_t* inframe1,const uint32_t* inframe2,const uint32_t* inframe3,
- uint32_t* outframe)=mlt_properties_get_data( prop , "f0r_update2" ,NULL);
-
-
- //use as name the width and height
- f0r_instance_t inst;
- char ctorname[1024]="";
- sprintf(ctorname,"ctor-%dx%d",*width,*height);
-
- void* neu=mlt_properties_get_data( prop , ctorname ,NULL );
- if (!f0r_construct){
- //printf("no ctor\n");
- return -1;
- }
- if ( neu == 0 ){
- inst= f0r_construct(*width,*height);
- mlt_properties_set_data( prop , ctorname , inst, sizeof(void*) , f0r_destruct , NULL );;
- }else{
- inst=mlt_properties_get_data( prop , ctorname , NULL );
- }
- if (f0r_get_plugin_info){
- f0r_plugin_info_t info;
- f0r_get_plugin_info(&info);
- for (i=0;i<info.num_params;i++){
- f0r_param_info_t pinfo;
- f0r_get_param_info(&pinfo,i);
- mlt_geometry geom=mlt_geometry_init();
- struct mlt_geometry_item_s item;
- //set param if found
-
- double t=0.0;
- f0r_get_param_value(inst,&t,i);
- char *val;
- if (mlt_properties_get( prop , pinfo.name ) !=NULL ){
- switch (pinfo.type) {
- case F0R_PARAM_DOUBLE:
- case F0R_PARAM_BOOL:
- val=mlt_properties_get(prop, pinfo.name );
- mlt_geometry_parse(geom,val,-1,-1,-1);
- mlt_geometry_fetch(geom,&item,position);
- t=item.x;
- f0r_set_param_value(inst,&t,i);
- break;
- case F0R_PARAM_COLOR:
- {
- f0r_param_color_t color;
- parse_color(mlt_properties_get_int(prop , pinfo.name), &color);
- f0r_set_param_value(inst, &color, i);
- break;
- }
- }
- }
-
- mlt_geometry_close(geom);
- }
- }
-
- int video_area = *width * *height;
- uint32_t *img_a;
-
- if ( type != producer_type )
- img_a = mlt_pool_alloc( video_area * sizeof(uint32_t) );
- uint32_t *img_b = mlt_pool_alloc( video_area * sizeof(uint32_t) );
-
- if (type==producer_type) {
- f0r_update ( inst , position , NULL , img_b );
- mlt_convert_rgb24a_to_yuv422((uint8_t *)img_b , *width, *height, *width * sizeof(uint32_t),*image, NULL);
- } else if (type==filter_type) {
- mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)img_a, video_area);
- f0r_update ( inst , position , img_a , img_b );
- mlt_convert_rgb24a_to_yuv422((uint8_t *)img_b , *width, *height, *width * sizeof(uint32_t),
- *image, NULL );
- } else if (type==transition_type && f0r_update2 ){
- uint32_t *result = mlt_pool_alloc( video_area * sizeof(uint32_t) );
-
- mlt_convert_yuv422_to_rgb24a ( image[0] , (uint8_t *)img_a , video_area );
- mlt_convert_yuv422_to_rgb24a ( image[1] , (uint8_t *)img_b , video_area );
- f0r_update2 ( inst , position , img_a , img_b , NULL , result );
-
- uint8_t * image_ptr=mlt_properties_get_data(MLT_FRAME_PROPERTIES(this), "image", NULL );
- if (image_ptr)
- mlt_convert_rgb24a_to_yuv422((uint8_t *)result, *width, *height, *width * sizeof(uint32_t), image_ptr , NULL );
-
- mlt_pool_release(result);
- }
- if ( type != producer_type ) mlt_pool_release(img_a);
- mlt_pool_release(img_b);
-
- return 0;
-}
-
-void destruct (mlt_properties prop ) {
-
- void (*f0r_destruct)(f0r_instance_t instance)=mlt_properties_get_data( prop , "f0r_destruct" , NULL );
- void (*f0r_deinit)(void)=mlt_properties_get_data ( prop , "f0r_deinit" , NULL);
- int i=0;
-
- if ( f0r_deinit != NULL )
- f0r_deinit();
-
- for ( i=0 ; i < mlt_properties_count ( prop ) ; i++ ){
- if ( strstr ( mlt_properties_get_name ( prop , i ) , "ctor-" ) != NULL ){
- void * inst=mlt_properties_get_data( prop , mlt_properties_get_name ( prop , i ) , NULL );
- if ( inst != NULL ){
- f0r_destruct( (f0r_instance_t) inst);
- }
- }
- }
- void (*dlclose)(void*)=mlt_properties_get_data ( prop , "_dlclose" , NULL);
- void *handle=mlt_properties_get_data ( prop , "_dlclose_handle" , NULL);
-
- if (handle && dlclose ){
- dlclose ( handle );
- }
-
-}
+++ /dev/null
-/*
- * frei0r_helper.h -- frei0r helper
- * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <framework/mlt.h>
-
-int process_frei0r_item( mlt_service_type type, double position , mlt_properties prop , mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable );
-void destruct (mlt_properties prop );
+++ /dev/null
-/*
- * producer_frei0r.c -- frei0r producer
- * Copyright (c) 2009 Jean-Baptiste Mardelle <jb@kdenlive.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-
-#include "frei0r_helper.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer for this frame
- mlt_producer producer = mlt_properties_get_data( properties, "producer_frei0r", NULL );
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Allocate the image
- int size = *width * ( *height + 1 ) * 2;
-
- // Allocate the image
- *buffer = mlt_pool_alloc( size );
-
- // Update the frame
- mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
-
- *format = mlt_image_yuv422;
- if ( *buffer != NULL )
- {
- mlt_position in = mlt_producer_get_in( producer );
- mlt_position out = mlt_producer_get_out( producer );
- mlt_position time = mlt_frame_get_position( frame );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- process_frei0r_item( producer_type , position, producer_props, frame , buffer, format , width , height , writable );
- }
-
- return 0;
-}
-
-int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- if ( *frame != NULL )
- {
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Set the producer on the frame properties
- mlt_properties_set_data( properties, "producer_frei0r", producer, 0, NULL, NULL );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-void producer_close( mlt_producer producer )
-{
- producer->close = NULL;
- mlt_producer_close( producer );
- free( producer );
-}
+++ /dev/null
-/*
- * transition_frei0r.c -- frei0r transition
- * Copyright (c) 2008 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-#include "frei0r_helper.h"
-#include <string.h>
-
-static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ){
-
- if (*format!=mlt_image_yuv422 ){
- return -1;
- }
-
- mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
- mlt_transition transition = mlt_frame_pop_service( a_frame );
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- int invert = mlt_properties_get_int( properties, "invert" );
-
- if ( mlt_properties_get( a_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) )
- mlt_properties_set( a_props, "rescale.interp", "nearest" );
-
- // set consumer_aspect_ratio for a and b frame
- if ( mlt_properties_get_double( a_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( a_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( b_props, "aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) );
-
- if ( mlt_properties_get( b_props, "rescale.interp" ) == NULL || !strcmp( mlt_properties_get( b_props, "rescale.interp" ), "none" ) )
- mlt_properties_set( b_props, "rescale.interp", "nearest" );
-
- uint8_t *images[]={NULL,NULL,NULL};
-
- mlt_frame_get_image( a_frame, &images[0], format, width, height, 1 );
- mlt_frame_get_image( b_frame, &images[1], format, width, height, 1 );
-
- mlt_position in = mlt_transition_get_in( transition );
- mlt_position out = mlt_transition_get_out( transition );
-
- // Get the position of the frame
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
- mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( a_frame ), name );
-
- float pos=( float )( position - in ) / ( float )( out - in + 1 );
-
- process_frei0r_item( transition_type , pos , properties, !invert ? a_frame : b_frame , images , format, width,height, writable );
-
- *width = mlt_properties_get_int( !invert ? a_props : b_props, "width" );
- *height = mlt_properties_get_int( !invert ? a_props : b_props, "height" );
- *image = mlt_properties_get_data( !invert ? a_props : b_props , "image", NULL );
- return 0;
-}
-
-mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
-{
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
- mlt_properties_set_position( MLT_FRAME_PROPERTIES( a_frame ), name, mlt_frame_get_position( a_frame ) );
- mlt_frame_push_service( a_frame, transition );
- mlt_frame_push_frame( a_frame, b_frame );
- mlt_frame_push_get_image( a_frame, transition_get_image );
- return a_frame;
-}
-
-void transition_close( mlt_transition this ){
- destruct ( MLT_TRANSITION_PROPERTIES ( this ) );
-}
+++ /dev/null
-include ../../../config.mak
-include config.mak
-
-TARGET = ../libmltgtk2$(LIBSUF)
-
-OBJS = factory.o
-
-CFLAGS += -I../..
-LDFLAGS += -L../../framework -lmlt
-
-ifdef USE_GTK2
-OBJS += consumer_gtk2.o
-CFLAGS += `pkg-config gtk+-2.0 --cflags`
-LDFLAGS += `pkg-config gtk+-2.0 --libs`
-endif
-
-ifdef USE_PIXBUF
-OBJS += producer_pixbuf.o pixops.o filter_rescale.o
-CFLAGS += `pkg-config gdk-pixbuf-2.0 --cflags`
-LDFLAGS += `pkg-config gdk-pixbuf-2.0 --libs`
-endif
-
-ifdef MMX_FLAGS
-ifndef ARCH_X86_64
-ASM_OBJS = have_mmx.o scale_line_22_yuv_mmx.o
-endif
-endif
-
-ifdef USE_PANGO
-OBJS += producer_pango.o
-CFLAGS += `pkg-config pangoft2 --cflags`
-LDFLAGS += `pkg-config pangoft2 --libs`
-endif
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS) $(ASM_OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(ASM_OBJS) $(LDFLAGS)
-
-have_mmx.o:
- $(CC) -o $@ -c have_mmx.S
-
-scale_line_22_yuv_mmx.o: scale_line_22_yuv_mmx.S
- $(CC) -o $@ -c scale_line_22_yuv_mmx.S
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(ASM_OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- pkg-config gtk+-2.0 2> /dev/null
- disable_gtk2=$?
-
- pkg-config gdk-pixbuf-2.0 2> /dev/null
- disable_pixbuf=$?
-
- pkg-config pangoft2 2> /dev/null
- disable_pango=$?
-
- if [ "$disable_gtk2" != "0" -a "$disable_pixbuf" != 0 -a "$disable_pango" != "0" ]
- then
- echo "- GTK2 components not found: disabling"
- touch ../disable-gtk2
- exit 0
- fi
-
- [ "$disable_gtk2" != "0" ] && echo "- gtk2 not found: gtk2 preview disabled"
- [ "$disable_pixbuf" != "0" ] && echo "- pixbuf not found: pixbuf loader and rescaler disabled"
- [ "$disable_pango" != "0" ] && echo "- pango not found: pango titler disabled"
-
- echo > config.h
- [ "$disable_gtk2" = "0" ] && echo "#define USE_GTK2" >> config.h
- [ "$disable_pixbuf" = "0" ] && echo "#define USE_PIXBUF" >> config.h
- [ "$disable_pango" = "0" ] && echo "#define USE_PANGO" >> config.h
-
- echo > config.mak
- [ "$disable_gtk2" = "0" ] && echo "USE_GTK2=1" >> config.mak
- [ "$disable_pixbuf" = "0" ] && echo "USE_PIXBUF=1" >> config.mak
- [ "$disable_pango" = "0" ] && echo "USE_PANGO=1" >> config.mak
-
- exit 0
-fi
-
+++ /dev/null
-/*
- * consumer_gtk2.c -- A consumer for GTK2 apps
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdlib.h>
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_factory.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-
-mlt_consumer consumer_gtk2_preview_init( mlt_profile profile, GtkWidget *widget )
-{
- // Create an sdl preview consumer
- mlt_consumer consumer = NULL;
-
- // This is a nasty little hack which is required by SDL
- if ( widget != NULL )
- {
- Window xwin = GDK_WINDOW_XWINDOW( widget->window );
- char windowhack[ 32 ];
- sprintf( windowhack, "%ld", xwin );
- setenv( "SDL_WINDOWID", windowhack, 1 );
- }
-
- // Create an sdl preview consumer
- consumer = mlt_factory_consumer( profile, "sdl_preview", NULL );
-
- // Now assign the lock/unlock callbacks
- if ( consumer != NULL )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
- mlt_properties_set_int( properties, "app_locked", 1 );
- mlt_properties_set_data( properties, "app_lock", gdk_threads_enter, 0, NULL, NULL );
- mlt_properties_set_data( properties, "app_unlock", gdk_threads_leave, 0, NULL, NULL );
- }
-
- return consumer;
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "config.h"
-#include <string.h>
-#include <framework/mlt.h>
-#include <gdk/gdk.h>
-
-#ifdef USE_PIXBUF
-extern mlt_producer producer_pixbuf_init( char *filename );
-extern mlt_filter filter_rescale_init( mlt_profile profile, char *arg );
-#endif
-
-#ifdef USE_GTK2
-extern mlt_consumer consumer_gtk2_preview_init( mlt_profile profile, void *widget );
-#endif
-
-#ifdef USE_PANGO
-extern mlt_producer producer_pango_init( const char *filename );
-#endif
-
-static void initialise( )
-{
- static int init = 0;
- if ( init == 0 )
- {
- init = 1;
- g_type_init( );
- }
-}
-
-void *create_service( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- initialise( );
-
-#ifdef USE_PIXBUF
- if ( !strcmp( id, "pixbuf" ) )
- return producer_pixbuf_init( arg );
-#endif
-
-#ifdef USE_PANGO
- if ( !strcmp( id, "pango" ) )
- return producer_pango_init( arg );
-#endif
-
-#ifdef USE_PIXBUF
- if ( !strcmp( id, "gtkrescale" ) )
- return filter_rescale_init( profile, arg );
-#endif
-
-#ifdef USE_GTK2
- if ( !strcmp( id, "gtk2_preview" ) )
- return consumer_gtk2_preview_init( profile, arg );
-#endif
-
- return NULL;
-}
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "gtk2_preview", create_service );
- MLT_REGISTER( filter_type, "gtkrescale", create_service );
- MLT_REGISTER( producer_type, "pango", create_service );
- MLT_REGISTER( producer_type, "pixbuf", create_service );
-}
+++ /dev/null
-/*
- * filter_rescale.c -- scale the producer video frame size to match the consumer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "pixops.h"
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_factory.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format iformat, mlt_image_format oformat, int iwidth, int iheight, int owidth, int oheight )
-{
- // Get the properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Get the requested interpolation method
- char *interps = mlt_properties_get( properties, "rescale.interp" );
-
- // Convert to the GTK flag
- int interp = PIXOPS_INTERP_BILINEAR;
-
- if ( strcmp( interps, "nearest" ) == 0 )
- interp = PIXOPS_INTERP_NEAREST;
- else if ( strcmp( interps, "tiles" ) == 0 )
- interp = PIXOPS_INTERP_TILES;
- else if ( strcmp( interps, "hyper" ) == 0 )
- interp = PIXOPS_INTERP_HYPER;
-
- // Carry out the rescaling
- if ( iformat == mlt_image_yuv422 && oformat == mlt_image_yuv422 )
- {
- // Create the output image
- uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- // Calculate strides
- int istride = iwidth * 2;
- int ostride = owidth * 2;
-
- yuv422_scale_simple( output, owidth, oheight, ostride, *image, iwidth, iheight, istride, interp );
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- // Return the output
- *image = output;
- }
- else if ( iformat == mlt_image_rgb24 || iformat == mlt_image_rgb24a )
- {
- int bpp = (iformat == mlt_image_rgb24a ? 4 : 3 );
-
- // Create the yuv image
- uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
-
- if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
- {
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( *image, GDK_COLORSPACE_RGB,
- ( iformat == mlt_image_rgb24a ), 8, iwidth, iheight,
- iwidth * bpp, NULL, NULL );
-
- GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf, owidth, oheight, interp );
- g_object_unref( pixbuf );
-
- // Extract YUV422 and alpha
- if ( bpp == 4 )
- {
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) );
-
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( scaled ), owidth, oheight, gdk_pixbuf_get_rowstride( scaled ), output, alpha );
-
- mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
- }
- else
- {
- // No alpha to extract
- mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( scaled ), owidth, oheight, gdk_pixbuf_get_rowstride( scaled ), output );
- }
- g_object_unref( scaled );
- }
- else
- {
- // Extract YUV422 and alpha
- if ( bpp == 4 )
- {
- // Allocate the alpha mask
- uint8_t *alpha = mlt_pool_alloc( owidth * ( oheight + 1 ) );
-
- // Convert the image and extract alpha
- mlt_convert_rgb24a_to_yuv422( *image, owidth, oheight, owidth * 4, output, alpha );
-
- mlt_properties_set_data( properties, "alpha", alpha, owidth * ( oheight + 1 ), ( mlt_destructor )mlt_pool_release, NULL );
- }
- else
- {
- // No alpha to extract
- mlt_convert_rgb24_to_yuv422( *image, owidth, oheight, owidth * 3, output );
- }
- }
-
- // Now update the frame
- mlt_properties_set_data( properties, "image", output, owidth * ( oheight + 1 ) * 2, ( mlt_destructor )mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", owidth );
- mlt_properties_set_int( properties, "height", oheight );
-
- *image = output;
- }
-
- return 0;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_rescale_init( mlt_profile profile, char *arg )
-{
- // Create a new scaler
- mlt_filter this = mlt_factory_filter( profile, "rescale", arg );
-
- // If successful, then initialise it
- if ( this != NULL )
- {
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Set the inerpolation
- mlt_properties_set( properties, "interpolation", arg == NULL ? "bilinear" : arg );
-
- // Set the method
- mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
- }
-
- return this;
-}
-
+++ /dev/null
- .file "have_mmx.S"
- .version "01.01"
-gcc2_compiled.:
-.text
- .align 16
-
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-
-.globl pixops_have_mmx
- .type pixops_have_mmx,@function
-pixops_have_mmx:
-
-#else
-
-.globl _pixops_have_mmx
-_pixops_have_mmx:
-
-#endif
-
- push %ebx
-
-# Check if bit 21 in flags word is writeable
-
- pushfl
- popl %eax
- movl %eax,%ebx
- xorl $0x00200000, %eax
- pushl %eax
- popfl
- pushfl
- popl %eax
-
- cmpl %eax, %ebx
-
- je .notfound
-
-# OK, we have CPUID
-
- movl $1, %eax
- cpuid
-
- test $0x00800000, %edx
- jz .notfound
-
- movl $1, %eax
- jmp .out
-
-.notfound:
- movl $0, %eax
-.out:
- popl %ebx
- ret
-
+++ /dev/null
-/* GdkPixbuf library - Scaling and compositing functions
- *
- * Original:
- * Copyright (C) 2000 Red Hat, Inc
- * Author: Owen Taylor <otaylor@redhat.com>
- *
- * Modification for MLT:
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <math.h>
-#include <glib.h>
-#include <stdio.h>
-
-#include "pixops.h"
-
-#define SUBSAMPLE_BITS 4
-#define SUBSAMPLE (1 << SUBSAMPLE_BITS)
-#define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS)-1)
-#define SCALE_SHIFT 16
-
-typedef struct _PixopsFilter PixopsFilter;
-typedef struct _PixopsFilterDimension PixopsFilterDimension;
-
-struct _PixopsFilterDimension
-{
- int n;
- double offset;
- double *weights;
-};
-
-struct _PixopsFilter
-{
- PixopsFilterDimension x;
- PixopsFilterDimension y;
- double overall_alpha;
-};
-
-typedef guchar *( *PixopsLineFunc ) ( int *weights, int n_x, int n_y,
- guchar *dest, int dest_x, guchar *dest_end,
- guchar **src,
- int x_init, int x_step, int src_width );
-
-typedef void ( *PixopsPixelFunc ) ( guchar *dest, guint y1, guint cr, guint y2, guint cb );
-
-
-/* mmx function declarations */
-#if defined(USE_MMX) && !defined(ARCH_X86_64)
-guchar *pixops_scale_line_22_yuv_mmx ( guint32 weights[ 16 ][ 8 ], guchar *p, guchar *q1, guchar *q2, int x_step, guchar *p_stop, int x_init, int destx );
-int pixops_have_mmx ( void );
-#endif
-
-static inline int
-get_check_shift ( int check_size )
-{
- int check_shift = 0;
- g_return_val_if_fail ( check_size >= 0, 4 );
-
- while ( !( check_size & 1 ) )
- {
- check_shift++;
- check_size >>= 1;
- }
-
- return check_shift;
-}
-
-static inline void
-pixops_scale_nearest ( guchar *dest_buf,
- int render_x0,
- int render_y0,
- int render_x1,
- int render_y1,
- int dest_rowstride,
- const guchar *src_buf,
- int src_width,
- int src_height,
- int src_rowstride,
- double scale_x,
- double scale_y )
-{
- register int i, j;
- register int x_step = ( 1 << SCALE_SHIFT ) / scale_x;
- register int y_step = ( 1 << SCALE_SHIFT ) / scale_y;
- register int x, x_scaled;
-
- for ( i = 0; i < ( render_y1 - render_y0 ); i++ )
- {
- const guchar *src = src_buf + ( ( ( i + render_y0 ) * y_step + ( y_step >> 1 ) ) >> SCALE_SHIFT ) * src_rowstride;
- guchar *dest = dest_buf + i * dest_rowstride;
- x = render_x0 * x_step + ( x_step >> 1 );
-
- for ( j = 0; j < ( render_x1 - render_x0 ); j++ )
- {
- x_scaled = x >> SCALE_SHIFT;
- *dest++ = src[ x_scaled << 1 ];
- *dest++ = src[ ( ( x_scaled >> 1 ) << 2 ) + ( ( j & 1 ) << 1 ) + 1 ];
- x += x_step;
- }
- }
-}
-
-
-static inline guchar *
-scale_line ( int *weights, int n_x, int n_y,
- guchar *dest, int dest_x, guchar *dest_end,
- guchar **src,
- int x_init, int x_step, int src_width )
-{
- register int x = x_init;
- register int i, j, x_scaled, y_index, uv_index;
-
- while ( dest < dest_end )
- {
- unsigned int y = 0, uv = 0;
- int *pixel_weights = weights + ( ( x >> ( SCALE_SHIFT - SUBSAMPLE_BITS ) ) & SUBSAMPLE_MASK ) * n_x * n_y;
-
- x_scaled = x >> SCALE_SHIFT;
- y_index = x_scaled << 1;
- uv_index = ( ( x_scaled >> 1 ) << 2 ) + ( ( dest_x & 1 ) << 1 ) + 1;
-
- for ( i = 0; i < n_y; i++ )
- {
- int *line_weights = pixel_weights + n_x * i;
- guchar *q = src[ i ];
-
- for ( j = 0; j < n_x; j ++ )
- {
- unsigned int ta = line_weights[ j ];
-
- y += ta * q[ y_index ];
- uv += ta * q[ uv_index ];
- }
- }
-
- *dest++ = ( y + 0xffff ) >> SCALE_SHIFT;
- *dest++ = ( uv + 0xffff ) >> SCALE_SHIFT;
-
- x += x_step;
- dest_x++;
- }
-
- return dest;
-}
-
-#if defined(USE_MMX) && !defined(ARCH_X86_64)
-static inline guchar *
-scale_line_22_yuv_mmx_stub ( int *weights, int n_x, int n_y,
- guchar *dest, int dest_x, guchar *dest_end,
- guchar **src,
- int x_init, int x_step, int src_width )
-{
- guint32 mmx_weights[ 16 ][ 8 ];
- int j;
-
- for ( j = 0; j < 16; j++ )
- {
- mmx_weights[ j ][ 0 ] = 0x00010001 * ( weights[ 4 * j ] >> 8 );
- mmx_weights[ j ][ 1 ] = 0x00010001 * ( weights[ 4 * j ] >> 8 );
- mmx_weights[ j ][ 2 ] = 0x00010001 * ( weights[ 4 * j + 1 ] >> 8 );
- mmx_weights[ j ][ 3 ] = 0x00010001 * ( weights[ 4 * j + 1 ] >> 8 );
- mmx_weights[ j ][ 4 ] = 0x00010001 * ( weights[ 4 * j + 2 ] >> 8 );
- mmx_weights[ j ][ 5 ] = 0x00010001 * ( weights[ 4 * j + 2 ] >> 8 );
- mmx_weights[ j ][ 6 ] = 0x00010001 * ( weights[ 4 * j + 3 ] >> 8 );
- mmx_weights[ j ][ 7 ] = 0x00010001 * ( weights[ 4 * j + 3 ] >> 8 );
- }
-
- return pixops_scale_line_22_yuv_mmx ( mmx_weights, dest, src[ 0 ], src[ 1 ], x_step, dest_end, x_init, dest_x );
-}
-#endif /* USE_MMX */
-
-static inline guchar *
-scale_line_22_yuv ( int *weights, int n_x, int n_y,
- guchar *dest, int dest_x, guchar *dest_end,
- guchar **src,
- int x_init, int x_step, int src_width )
-{
- register int x = x_init;
- register guchar *src0 = src[ 0 ];
- register guchar *src1 = src[ 1 ];
- register unsigned int p;
- register guchar *q0, *q1;
- register int w1, w2, w3, w4;
- register int x_scaled, x_aligned, uv_index;
-
- while ( dest < dest_end )
- {
- int *pixel_weights = weights + ( ( x >> ( SCALE_SHIFT - SUBSAMPLE_BITS ) ) & SUBSAMPLE_MASK ) * 4;
-
- x_scaled = x >> SCALE_SHIFT;
-
- w1 = pixel_weights[ 0 ];
- w2 = pixel_weights[ 1 ];
- w3 = pixel_weights[ 2 ];
- w4 = pixel_weights[ 3 ];
-
- /* process Y */
- q0 = src0 + ( x_scaled << 1 );
- q1 = src1 + ( x_scaled << 1 );
- p = w1 * q0[ 0 ];
- p += w2 * q0[ 2 ];
- p += w3 * q1[ 0 ];
- p += w4 * q1[ 2 ];
- *dest++ = ( p + 0x8000 ) >> SCALE_SHIFT;
-
- /* process U/V */
- x_aligned = ( ( x_scaled >> 1 ) << 2 );
- uv_index = ( ( dest_x & 1 ) << 1 ) + 1;
-
- q0 = src0 + x_aligned;
- q1 = src1 + x_aligned;
- p = w1 * q0[ uv_index ];
- p += w3 * q1[ uv_index ];
- p += w2 * q0[ uv_index ];
- p += w4 * q1[ uv_index ];
-
- x += x_step;
- dest_x ++;
-
- *dest++ = ( p + 0x8000 ) >> SCALE_SHIFT;
- }
-
- return dest;
-}
-
-
-static inline void
-process_pixel ( int *weights, int n_x, int n_y,
- guchar *dest, int dest_x, int dest_channels,
- guchar **src, int src_channels,
- int x_start, int src_width )
-{
- register unsigned int y = 0, uv = 0;
- register int i, j;
- int uv_index = ( ( dest_x & 1 ) << 1 ) + 1;
-
- for ( i = 0; i < n_y; i++ )
- {
- int *line_weights = weights + n_x * i;
-
- for ( j = 0; j < n_x; j++ )
- {
- unsigned int ta = 0xff * line_weights[ j ];
-
- if ( x_start + j < 0 )
- {
- y += ta * src[ i ][ 0 ];
- uv += ta * src[ i ][ uv_index ];
- }
- else if ( x_start + j < src_width )
- {
- y += ta * src[ i ][ ( x_start + j ) << 1 ];
- uv += ta * src[ i ][ ( ( ( x_start + j ) >> 1 ) << 2) + uv_index ];
- }
- else
- {
- y += ta * src[ i ][ ( src_width - 1 ) << 1 ];
- uv += ta * src[ i ][ ( ( ( src_width - 1 ) >> 1 ) << 2) + uv_index ];
- }
- }
- }
-
- *dest++ = ( y + 0xffffff ) >> 24;
- *dest++ = ( uv + 0xffffff ) >> 24;
-}
-
-
-static inline void
-correct_total ( int *weights,
- int n_x,
- int n_y,
- int total,
- double overall_alpha )
-{
- int correction = ( int ) ( 0.5 + 65536 * overall_alpha ) - total;
- int remaining, c, d, i;
-
- if ( correction != 0 )
- {
- remaining = correction;
- for ( d = 1, c = correction; c != 0 && remaining != 0; d++, c = correction / d )
- for ( i = n_x * n_y - 1; i >= 0 && c != 0 && remaining != 0; i-- )
- if ( *( weights + i ) + c >= 0 )
- {
- *( weights + i ) += c;
- remaining -= c;
- if ( ( 0 < remaining && remaining < c ) ||
- ( 0 > remaining && remaining > c ) )
- c = remaining;
- }
- }
-}
-
-
-static inline int *
-make_filter_table ( PixopsFilter *filter )
-{
- int i_offset, j_offset;
- int n_x = filter->x.n;
- int n_y = filter->y.n;
- int *weights = g_new ( int, SUBSAMPLE * SUBSAMPLE * n_x * n_y );
-
- for ( i_offset = 0; i_offset < SUBSAMPLE; i_offset++ )
- for ( j_offset = 0; j_offset < SUBSAMPLE; j_offset++ )
- {
- double weight;
- int *pixel_weights = weights + ( ( i_offset * SUBSAMPLE ) + j_offset ) * n_x * n_y;
- int total = 0;
- int i, j;
-
- for ( i = 0; i < n_y; i++ )
- for ( j = 0; j < n_x; j++ )
- {
- weight = filter->x.weights[ ( j_offset * n_x ) + j ] *
- filter->y.weights[ ( i_offset * n_y ) + i ] *
- filter->overall_alpha * 65536 + 0.5;
-
- total += ( int ) weight;
-
- *( pixel_weights + n_x * i + j ) = weight;
- }
-
- correct_total ( pixel_weights, n_x, n_y, total, filter->overall_alpha );
- }
-
- return weights;
-}
-
-
-static inline void
-pixops_process ( guchar *dest_buf,
- int render_x0,
- int render_y0,
- int render_x1,
- int render_y1,
- int dest_rowstride,
- int dest_channels,
- gboolean dest_has_alpha,
- const guchar *src_buf,
- int src_width,
- int src_height,
- int src_rowstride,
- int src_channels,
- gboolean src_has_alpha,
- double scale_x,
- double scale_y,
- int check_x,
- int check_y,
- int check_size,
- guint32 color1,
- guint32 color2,
- PixopsFilter *filter,
- PixopsLineFunc line_func )
-{
- int i, j;
- int x, y; /* X and Y position in source (fixed_point) */
-
- guchar **line_bufs = g_new ( guchar *, filter->y.n );
- int *filter_weights = make_filter_table ( filter );
-
- int x_step = ( 1 << SCALE_SHIFT ) / scale_x; /* X step in source (fixed point) */
- int y_step = ( 1 << SCALE_SHIFT ) / scale_y; /* Y step in source (fixed point) */
-
- int check_shift = check_size ? get_check_shift ( check_size ) : 0;
-
- int scaled_x_offset = floor ( filter->x.offset * ( 1 << SCALE_SHIFT ) );
-
- /* Compute the index where we run off the end of the source buffer. The furthest
- * source pixel we access at index i is:
- *
- * ((render_x0 + i) * x_step + scaled_x_offset) >> SCALE_SHIFT + filter->x.n - 1
- *
- * So, run_end_index is the smallest i for which this pixel is src_width, i.e, for which:
- *
- * (i + render_x0) * x_step >= ((src_width - filter->x.n + 1) << SCALE_SHIFT) - scaled_x_offset
- *
- */
-#define MYDIV(a,b) ((a) > 0 ? (a) / (b) : ((a) - (b) + 1) / (b)) /* Division so that -1/5 = -1 */
-
- int run_end_x = ( ( ( src_width - filter->x.n + 1 ) << SCALE_SHIFT ) - scaled_x_offset );
- int run_end_index = MYDIV ( run_end_x + x_step - 1, x_step ) - render_x0;
- run_end_index = MIN ( run_end_index, render_x1 - render_x0 );
-
- y = render_y0 * y_step + floor ( filter->y.offset * ( 1 << SCALE_SHIFT ) );
- for ( i = 0; i < ( render_y1 - render_y0 ); i++ )
- {
- int dest_x;
- int y_start = y >> SCALE_SHIFT;
- int x_start;
- int *run_weights = filter_weights +
- ( ( y >> ( SCALE_SHIFT - SUBSAMPLE_BITS ) ) & SUBSAMPLE_MASK ) *
- filter->x.n * filter->y.n * SUBSAMPLE;
- guchar *new_outbuf;
- guint32 tcolor1, tcolor2;
-
- guchar *outbuf = dest_buf + dest_rowstride * i;
- guchar *outbuf_end = outbuf + dest_channels * ( render_x1 - render_x0 );
-
- if ( ( ( i + check_y ) >> check_shift ) & 1 )
- {
- tcolor1 = color2;
- tcolor2 = color1;
- }
- else
- {
- tcolor1 = color1;
- tcolor2 = color2;
- }
-
- for ( j = 0; j < filter->y.n; j++ )
- {
- if ( y_start < 0 )
- line_bufs[ j ] = ( guchar * ) src_buf;
- else if ( y_start < src_height )
- line_bufs[ j ] = ( guchar * ) src_buf + src_rowstride * y_start;
- else
- line_bufs[ j ] = ( guchar * ) src_buf + src_rowstride * ( src_height - 1 );
-
- y_start++;
- }
-
- dest_x = check_x;
- x = render_x0 * x_step + scaled_x_offset;
- x_start = x >> SCALE_SHIFT;
-
- while ( x_start < 0 && outbuf < outbuf_end )
- {
- process_pixel ( run_weights + ( ( x >> ( SCALE_SHIFT - SUBSAMPLE_BITS ) ) & SUBSAMPLE_MASK ) * ( filter->x.n * filter->y.n ),
- filter->x.n, filter->y.n,
- outbuf, dest_x, dest_channels,
- line_bufs, src_channels,
- x >> SCALE_SHIFT, src_width );
-
- x += x_step;
- x_start = x >> SCALE_SHIFT;
- dest_x++;
- outbuf += dest_channels;
- }
-
- new_outbuf = ( *line_func ) ( run_weights, filter->x.n, filter->y.n,
- outbuf, dest_x,
- dest_buf + dest_rowstride * i + run_end_index * dest_channels,
- line_bufs,
- x, x_step, src_width );
-
- dest_x += ( new_outbuf - outbuf ) / dest_channels;
-
- x = ( dest_x - check_x + render_x0 ) * x_step + scaled_x_offset;
- outbuf = new_outbuf;
-
- while ( outbuf < outbuf_end )
- {
- process_pixel ( run_weights + ( ( x >> ( SCALE_SHIFT - SUBSAMPLE_BITS ) ) & SUBSAMPLE_MASK ) * ( filter->x.n * filter->y.n ),
- filter->x.n, filter->y.n,
- outbuf, dest_x, dest_channels,
- line_bufs, src_channels,
- x >> SCALE_SHIFT, src_width );
-
- x += x_step;
- dest_x++;
- outbuf += dest_channels;
- }
-
- y += y_step;
- }
-
- g_free ( line_bufs );
- g_free ( filter_weights );
-}
-
-
-/* Compute weights for reconstruction by replication followed by
- * sampling with a box filter
- */
-static inline void
-tile_make_weights ( PixopsFilterDimension *dim,
- double scale )
-{
- int n = ceil ( 1 / scale + 1 );
- double *pixel_weights = g_new ( double, SUBSAMPLE * n );
- int offset;
- int i;
-
- dim->n = n;
- dim->offset = 0;
- dim->weights = pixel_weights;
-
- for ( offset = 0; offset < SUBSAMPLE; offset++ )
- {
- double x = ( double ) offset / SUBSAMPLE;
- double a = x + 1 / scale;
-
- for ( i = 0; i < n; i++ )
- {
- if ( i < x )
- {
- if ( i + 1 > x )
- * ( pixel_weights++ ) = ( MIN ( i + 1, a ) - x ) * scale;
- else
- *( pixel_weights++ ) = 0;
- }
- else
- {
- if ( a > i )
- * ( pixel_weights++ ) = ( MIN ( i + 1, a ) - i ) * scale;
- else
- *( pixel_weights++ ) = 0;
- }
- }
- }
-}
-
-/* Compute weights for a filter that, for minification
- * is the same as 'tiles', and for magnification, is bilinear
- * reconstruction followed by a sampling with a delta function.
- */
-static inline void
-bilinear_magnify_make_weights ( PixopsFilterDimension *dim,
- double scale )
-{
- double * pixel_weights;
- int n;
- int offset;
- int i;
-
- if ( scale > 1.0 ) /* Linear */
- {
- n = 2;
- dim->offset = 0.5 * ( 1 / scale - 1 );
- }
- else /* Tile */
- {
- n = ceil ( 1.0 + 1.0 / scale );
- dim->offset = 0.0;
- }
-
- dim->n = n;
- dim->weights = g_new ( double, SUBSAMPLE * n );
-
- pixel_weights = dim->weights;
-
- for ( offset = 0; offset < SUBSAMPLE; offset++ )
- {
- double x = ( double ) offset / SUBSAMPLE;
-
- if ( scale > 1.0 ) /* Linear */
- {
- for ( i = 0; i < n; i++ )
- *( pixel_weights++ ) = ( ( ( i == 0 ) ? ( 1 - x ) : x ) / scale ) * scale;
- }
- else /* Tile */
- {
- double a = x + 1 / scale;
-
- /* x
- * ---------|--.-|----|--.-|------- SRC
- * ------------|---------|--------- DEST
- */
- for ( i = 0; i < n; i++ )
- {
- if ( i < x )
- {
- if ( i + 1 > x )
- * ( pixel_weights++ ) = ( MIN ( i + 1, a ) - x ) * scale;
- else
- *( pixel_weights++ ) = 0;
- }
- else
- {
- if ( a > i )
- * ( pixel_weights++ ) = ( MIN ( i + 1, a ) - i ) * scale;
- else
- *( pixel_weights++ ) = 0;
- }
- }
- }
- }
-}
-
-/* Computes the integral from b0 to b1 of
- *
- * f(x) = x; 0 <= x < 1
- * f(x) = 0; otherwise
- *
- * We combine two of these to compute the convolution of
- * a box filter with a triangular spike.
- */
-static inline double
-linear_box_half ( double b0, double b1 )
-{
- double a0, a1;
- double x0, x1;
-
- a0 = 0.;
- a1 = 1.;
-
- if ( a0 < b0 )
- {
- if ( a1 > b0 )
- {
- x0 = b0;
- x1 = MIN ( a1, b1 );
- }
- else
- return 0;
- }
- else
- {
- if ( b1 > a0 )
- {
- x0 = a0;
- x1 = MIN ( a1, b1 );
- }
- else
- return 0;
- }
-
- return 0.5 * ( x1 * x1 - x0 * x0 );
-}
-
-/* Compute weights for reconstructing with bilinear
- * interpolation, then sampling with a box filter
- */
-static inline void
-bilinear_box_make_weights ( PixopsFilterDimension *dim,
- double scale )
-{
- int n = ceil ( 1 / scale + 2.0 );
- double *pixel_weights = g_new ( double, SUBSAMPLE * n );
- double w;
- int offset, i;
-
- dim->offset = -1.0;
- dim->n = n;
- dim->weights = pixel_weights;
-
- for ( offset = 0 ; offset < SUBSAMPLE; offset++ )
- {
- double x = ( double ) offset / SUBSAMPLE;
- double a = x + 1 / scale;
-
- for ( i = 0; i < n; i++ )
- {
- w = linear_box_half ( 0.5 + i - a, 0.5 + i - x );
- w += linear_box_half ( 1.5 + x - i, 1.5 + a - i );
-
- *( pixel_weights++ ) = w * scale;
- }
- }
-}
-
-
-static inline void
-make_weights ( PixopsFilter *filter,
- PixopsInterpType interp_type,
- double scale_x,
- double scale_y )
-{
- switch ( interp_type )
- {
- case PIXOPS_INTERP_NEAREST:
- g_assert_not_reached ();
- break;
-
- case PIXOPS_INTERP_TILES:
- tile_make_weights ( &filter->x, scale_x );
- tile_make_weights ( &filter->y, scale_y );
- break;
-
- case PIXOPS_INTERP_BILINEAR:
- bilinear_magnify_make_weights ( &filter->x, scale_x );
- bilinear_magnify_make_weights ( &filter->y, scale_y );
- break;
-
- case PIXOPS_INTERP_HYPER:
- bilinear_box_make_weights ( &filter->x, scale_x );
- bilinear_box_make_weights ( &filter->y, scale_y );
- break;
- }
-}
-
-
-void
-yuv422_scale ( guchar *dest_buf,
- int render_x0,
- int render_y0,
- int render_x1,
- int render_y1,
- int dest_rowstride,
- int dest_channels,
- gboolean dest_has_alpha,
- const guchar *src_buf,
- int src_width,
- int src_height,
- int src_rowstride,
- int src_channels,
- gboolean src_has_alpha,
- double scale_x,
- double scale_y,
- PixopsInterpType interp_type )
-{
- PixopsFilter filter = { { 0, 0, 0}, { 0, 0, 0 }, 0 };
- PixopsLineFunc line_func;
-
-#if defined(USE_MMX) && !defined(ARCH_X86_64)
- gboolean found_mmx = pixops_have_mmx();
-#endif
-
- //g_return_if_fail ( !( dest_channels == 3 && dest_has_alpha ) );
- //g_return_if_fail ( !( src_channels == 3 && src_has_alpha ) );
- //g_return_if_fail ( !( src_has_alpha && !dest_has_alpha ) );
-
- if ( scale_x == 0 || scale_y == 0 )
- return ;
-
- if ( interp_type == PIXOPS_INTERP_NEAREST )
- {
- pixops_scale_nearest ( dest_buf, render_x0, render_y0, render_x1, render_y1,
- dest_rowstride,
- src_buf, src_width, src_height, src_rowstride,
- scale_x, scale_y );
- return;
- }
-
- filter.overall_alpha = 1.0;
- make_weights ( &filter, interp_type, scale_x, scale_y );
-
- if ( filter.x.n == 2 && filter.y.n == 2 )
- {
-#if defined(USE_MMX) && !defined(ARCH_X86_64)
- if ( found_mmx )
- {
- //fprintf( stderr, "rescale: using mmx\n" );
- line_func = scale_line_22_yuv_mmx_stub;
- }
- else
-#endif
-
- line_func = scale_line_22_yuv;
- }
- else
- line_func = scale_line;
-
- pixops_process ( dest_buf, render_x0, render_y0, render_x1, render_y1,
- dest_rowstride, dest_channels, dest_has_alpha,
- src_buf, src_width, src_height, src_rowstride, src_channels,
- src_has_alpha, scale_x, scale_y, 0, 0, 0, 0, 0,
- &filter, line_func );
-
- g_free ( filter.x.weights );
- g_free ( filter.y.weights );
-}
-
+++ /dev/null
-/* GdkPixbuf library - Scaling and compositing functions
- *
- * Original:
- * Copyright (C) 2000 Red Hat, Inc
- * Author: Owen Taylor <otaylor@redhat.com>
- *
- * Modification for MLT:
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef PIXOPS_H
-#define PIXOPS_H
-
-#include <glib.h>
-
-/* Interpolation modes; must match GdkInterpType */
-typedef enum {
- PIXOPS_INTERP_NEAREST,
- PIXOPS_INTERP_TILES,
- PIXOPS_INTERP_BILINEAR,
- PIXOPS_INTERP_HYPER
-} PixopsInterpType;
-
-/* Scale src_buf from src_width / src_height by factors scale_x, scale_y
- * and composite the portion corresponding to
- * render_x, render_y, render_width, render_height in the new
- * coordinate system into dest_buf starting at 0, 0
- */
-void yuv422_scale (guchar *dest_buf,
- int render_x0,
- int render_y0,
- int render_x1,
- int render_y1,
- int dest_rowstride,
- int dest_channels,
- int dest_has_alpha,
- const guchar *src_buf,
- int src_width,
- int src_height,
- int src_rowstride,
- int src_channels,
- int src_has_alpha,
- double scale_x,
- double scale_y,
- PixopsInterpType interp_type);
-
-#define yuv422_scale_simple( dest_buf, dest_width, dest_height, dest_rowstride, src_buf, src_width, src_height, src_rowstride, interp_type ) \
- yuv422_scale( (dest_buf), 0, 0, \
- (dest_width), (dest_height), \
- (dest_rowstride), 2, 0, \
- (src_buf), (src_width), (src_height), \
- (src_rowstride), 2, 0, \
- (double) (dest_width) / (src_width), (double) (dest_height) / (src_height), \
- (PixopsInterpType) interp_type );
-
-#endif
+++ /dev/null
-/*
- * producer_pango.c -- a pango-based titler
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_geometry.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <pango/pangoft2.h>
-#include <freetype/freetype.h>
-#include <iconv.h>
-#include <pthread.h>
-#include <ctype.h>
-
-typedef struct producer_pango_s *producer_pango;
-
-typedef enum
-{
- pango_align_left = 0,
- pango_align_center,
- pango_align_right
-} pango_align;
-
-static pthread_mutex_t pango_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-struct producer_pango_s
-{
- struct mlt_producer_s parent;
- int width;
- int height;
- uint8_t *image;
- uint8_t *alpha;
- char *fgcolor;
- char *bgcolor;
- int align;
- int pad;
- char *markup;
- char *text;
- char *font;
- int weight;
-};
-
-// special color type used by internal pango routines
-typedef struct
-{
- uint8_t r, g, b, a;
-} rgba_color;
-
-// Forward declarations
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg );
-static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font,
- rgba_color fg, rgba_color bg, int pad, int align, int weight, int size );
-
-/** Return nonzero if the two strings are equal, ignoring case, up to
- the first n characters.
-*/
-int strncaseeq(const char *s1, const char *s2, size_t n)
-{
- for ( ; n > 0; n--)
- {
- if (tolower(*s1++) != tolower(*s2++))
- return 0;
- }
- return 1;
-}
-
-/** Parse the alignment property.
-*/
-
-static int alignment_parse( char* align )
-{
- int ret = pango_align_left;
-
- if ( align == NULL );
- else if ( isdigit( align[ 0 ] ) )
- ret = atoi( align );
- else if ( align[ 0 ] == 'c' || align[ 0 ] == 'm' )
- ret = pango_align_center;
- else if ( align[ 0 ] == 'r' )
- ret = pango_align_right;
-
- return ret;
-}
-
-static PangoFT2FontMap *fontmap = NULL;
-
-mlt_producer producer_pango_init( const char *filename )
-{
- producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
- if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- mlt_producer producer = &this->parent;
-
- pthread_mutex_lock( &pango_mutex );
- if ( fontmap == NULL )
- fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
- g_type_init();
- pthread_mutex_unlock( &pango_mutex );
-
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- // Get the properties interface
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
-
- // Set the default properties
- mlt_properties_set( properties, "fgcolour", "0xffffffff" );
- mlt_properties_set( properties, "bgcolour", "0x00000000" );
- mlt_properties_set_int( properties, "align", pango_align_left );
- mlt_properties_set_int( properties, "pad", 0 );
- mlt_properties_set( properties, "text", "" );
- mlt_properties_set( properties, "font", "Sans 48" );
- mlt_properties_set( properties, "encoding", "UTF-8" );
- mlt_properties_set_int( properties, "weight", PANGO_WEIGHT_NORMAL );
-
- if ( filename == NULL )
- {
- mlt_properties_set( properties, "markup", "" );
- }
- else if ( filename[ 0 ] == '+' || strstr( filename, "/+" ) )
- {
- char *copy = strdup( filename + 1 );
- char *markup = copy;
- if ( strstr( markup, "/+" ) )
- markup = strstr( markup, "/+" ) + 2;
- ( *strrchr( markup, '.' ) ) = '\0';
- while ( strchr( markup, '~' ) )
- ( *strchr( markup, '~' ) ) = '\n';
- mlt_properties_set( properties, "resource", filename );
- mlt_properties_set( properties, "markup", markup );
- free( copy );
- }
- else if ( strstr( filename, ".mpl" ) )
- {
- int i = 0;
- mlt_properties contents = mlt_properties_load( filename );
- mlt_geometry key_frames = mlt_geometry_init( );
- struct mlt_geometry_item_s item;
- mlt_properties_set( properties, "resource", filename );
- mlt_properties_set_data( properties, "contents", contents, 0, ( mlt_destructor )mlt_properties_close, NULL );
- mlt_properties_set_data( properties, "key_frames", key_frames, 0, ( mlt_destructor )mlt_geometry_close, NULL );
-
- // Make sure we have at least one entry
- if ( mlt_properties_get( contents, "0" ) == NULL )
- mlt_properties_set( contents, "0", "" );
-
- for ( i = 0; i < mlt_properties_count( contents ); i ++ )
- {
- char *name = mlt_properties_get_name( contents, i );
- char *value = mlt_properties_get_value( contents, i );
- while ( value != NULL && strchr( value, '~' ) )
- ( *strchr( value, '~' ) ) = '\n';
- item.frame = atoi( name );
- mlt_geometry_insert( key_frames, &item );
- }
- }
- else
- {
- FILE *f = fopen( filename, "r" );
- if ( f != NULL )
- {
- char line[81];
- char *markup = NULL;
- size_t size = 0;
- line[80] = '\0';
-
- while ( fgets( line, 80, f ) )
- {
- size += strlen( line ) + 1;
- if ( markup )
- {
- markup = realloc( markup, size );
- strcat( markup, line );
- }
- else
- {
- markup = strdup( line );
- }
- }
- fclose( f );
-
- if ( markup[ strlen( markup ) - 1 ] == '\n' )
- markup[ strlen( markup ) - 1 ] = '\0';
-
- mlt_properties_set( properties, "resource", filename );
- mlt_properties_set( properties, "markup", ( markup == NULL ? "" : markup ) );
- free( markup );
- }
- else
- {
- mlt_properties_set( properties, "markup", "" );
- }
- }
-
- return producer;
- }
- free( this );
- return NULL;
-}
-
-static void set_string( char **string, const char *value, const char *fallback )
-{
- if ( value != NULL )
- {
- free( *string );
- *string = strdup( value );
- }
- else if ( *string == NULL && fallback != NULL )
- {
- *string = strdup( fallback );
- }
- else if ( *string != NULL && fallback == NULL )
- {
- free( *string );
- *string = NULL;
- }
-}
-
-rgba_color parse_color( char *color )
-{
- rgba_color result = { 0xff, 0xff, 0xff, 0xff };
-
- if ( !strncmp( color, "0x", 2 ) )
- {
- unsigned int temp = 0;
- sscanf( color + 2, "%x", &temp );
- result.r = ( temp >> 24 ) & 0xff;
- result.g = ( temp >> 16 ) & 0xff;
- result.b = ( temp >> 8 ) & 0xff;
- result.a = ( temp ) & 0xff;
- }
- else if ( !strcmp( color, "red" ) )
- {
- result.r = 0xff;
- result.g = 0x00;
- result.b = 0x00;
- }
- else if ( !strcmp( color, "green" ) )
- {
- result.r = 0x00;
- result.g = 0xff;
- result.b = 0x00;
- }
- else if ( !strcmp( color, "blue" ) )
- {
- result.r = 0x00;
- result.g = 0x00;
- result.b = 0xff;
- }
- else
- {
- unsigned int temp = 0;
- sscanf( color, "%d", &temp );
- result.r = ( temp >> 24 ) & 0xff;
- result.g = ( temp >> 16 ) & 0xff;
- result.b = ( temp >> 8 ) & 0xff;
- result.a = ( temp ) & 0xff;
- }
-
- return result;
-}
-
-/** Convert a string property to UTF-8
-*/
-static int iconv_utf8( mlt_properties properties, const char *prop_name, const char* encoding )
-{
- char *text = mlt_properties_get( properties, prop_name );
- int result = -1;
-
- iconv_t cd = iconv_open( "UTF-8", encoding );
- if ( cd != ( iconv_t )-1 )
- {
- char *inbuf_p = text;
- size_t inbuf_n = strlen( text );
- size_t outbuf_n = inbuf_n * 6;
- char *outbuf = mlt_pool_alloc( outbuf_n );
- char *outbuf_p = outbuf;
-
- memset( outbuf, 0, outbuf_n );
-
- if ( text != NULL && strcmp( text, "" ) && iconv( cd, &inbuf_p, &inbuf_n, &outbuf_p, &outbuf_n ) != -1 )
- mlt_properties_set( properties, prop_name, outbuf );
- else
- mlt_properties_set( properties, prop_name, "" );
-
- mlt_pool_release( outbuf );
- iconv_close( cd );
- result = 0;
- }
- return result;
-}
-
-static void refresh_image( mlt_frame frame, int width, int height )
-{
- // Pixbuf
- GdkPixbuf *pixbuf = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "pixbuf", NULL );
-
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer pango for this frame
- producer_pango this = mlt_properties_get_data( properties, "producer_pango", NULL );
-
- // Obtain the producer
- mlt_producer producer = &this->parent;
-
- // Obtain the producer properties
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Get producer properties
- char *fg = mlt_properties_get( producer_props, "fgcolour" );
- char *bg = mlt_properties_get( producer_props, "bgcolour" );
- int align = alignment_parse( mlt_properties_get( producer_props, "align" ) );
- int pad = mlt_properties_get_int( producer_props, "pad" );
- char *markup = mlt_properties_get( producer_props, "markup" );
- char *text = mlt_properties_get( producer_props, "text" );
- char *font = mlt_properties_get( producer_props, "font" );
- char *encoding = mlt_properties_get( producer_props, "encoding" );
- int weight = mlt_properties_get_int( producer_props, "weight" );
- int size = mlt_properties_get_int( producer_props, "size" );
- int property_changed = 0;
-
- if ( pixbuf == NULL )
- {
- // Check for file support
- int position = mlt_properties_get_position( properties, "pango_position" );
- mlt_properties contents = mlt_properties_get_data( producer_props, "contents", NULL );
- mlt_geometry key_frames = mlt_properties_get_data( producer_props, "key_frames", NULL );
- struct mlt_geometry_item_s item;
- if ( contents != NULL )
- {
- char temp[ 20 ];
- mlt_geometry_prev_key( key_frames, &item, position );
- sprintf( temp, "%d", item.frame );
- markup = mlt_properties_get( contents, temp );
- }
-
- // See if any properties changed
- property_changed = ( align != this->align );
- property_changed = property_changed || ( this->fgcolor == NULL || ( fg && strcmp( fg, this->fgcolor ) ) );
- property_changed = property_changed || ( this->bgcolor == NULL || ( bg && strcmp( bg, this->bgcolor ) ) );
- property_changed = property_changed || ( pad != this->pad );
- property_changed = property_changed || ( markup && this->markup && strcmp( markup, this->markup ) );
- property_changed = property_changed || ( text && this->text && strcmp( text, this->text ) );
- property_changed = property_changed || ( font && this->font && strcmp( font, this->font ) );
- property_changed = property_changed || ( weight != this->weight );
-
- // Save the properties for next comparison
- this->align = align;
- this->pad = pad;
- set_string( &this->fgcolor, fg, "0xffffffff" );
- set_string( &this->bgcolor, bg, "0x00000000" );
- set_string( &this->markup, markup, NULL );
- set_string( &this->text, text, NULL );
- set_string( &this->font, font, "Sans 48" );
- this->weight = weight;
- }
-
- if ( pixbuf == NULL && property_changed )
- {
- rgba_color fgcolor = parse_color( this->fgcolor );
- rgba_color bgcolor = parse_color( this->bgcolor );
-
- mlt_pool_release( this->image );
- mlt_pool_release( this->alpha );
- this->image = NULL;
- this->alpha = NULL;
-
- // Convert from specified encoding to UTF-8
- if ( encoding != NULL && !strncaseeq( encoding, "utf-8", 5 ) && !strncaseeq( encoding, "utf8", 4 ) )
- {
- if ( markup != NULL && iconv_utf8( producer_props, "markup", encoding ) != -1 )
- {
- markup = mlt_properties_get( producer_props, "markup" );
- set_string( &this->markup, markup, NULL );
- }
- if ( text != NULL && iconv_utf8( producer_props, "text", encoding ) != -1 )
- {
- text = mlt_properties_get( producer_props, "text" );
- set_string( &this->text, text, NULL );
- }
- }
-
- // Render the title
- pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align, weight, size );
-
- if ( pixbuf != NULL )
- {
- // Register this pixbuf for destruction and reuse
- mlt_properties_set_data( producer_props, "pixbuf", pixbuf, 0, ( mlt_destructor )g_object_unref, NULL );
- g_object_ref( pixbuf );
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "pixbuf", pixbuf, 0, ( mlt_destructor )g_object_unref, NULL );
-
- mlt_properties_set_int( producer_props, "real_width", gdk_pixbuf_get_width( pixbuf ) );
- mlt_properties_set_int( producer_props, "real_height", gdk_pixbuf_get_height( pixbuf ) );
-
- // Store the width/height of the pixbuf temporarily
- this->width = gdk_pixbuf_get_width( pixbuf );
- this->height = gdk_pixbuf_get_height( pixbuf );
- }
- }
- else if ( pixbuf == NULL && ( width > 0 && ( this->image == NULL || width != this->width || height != this->height ) ) )
- {
- mlt_pool_release( this->image );
- mlt_pool_release( this->alpha );
- this->image = NULL;
- this->alpha = NULL;
-
- pixbuf = mlt_properties_get_data( producer_props, "pixbuf", NULL );
- }
-
- // If we have a pixbuf and a valid width
- if ( pixbuf && width > 0 )
- {
- char *interps = mlt_properties_get( properties, "rescale.interp" );
- int interp = GDK_INTERP_BILINEAR;
-
- if ( strcmp( interps, "nearest" ) == 0 )
- interp = GDK_INTERP_NEAREST;
- else if ( strcmp( interps, "tiles" ) == 0 )
- interp = GDK_INTERP_TILES;
- else if ( strcmp( interps, "hyper" ) == 0 )
- interp = GDK_INTERP_HYPER;
-
-// fprintf(stderr,"%s: scaling from %dx%d to %dx%d\n", __FILE__, this->width, this->height, width, height);
-
- // Note - the original pixbuf is already safe and ready for destruction
- pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp );
-
- // Store width and height
- this->width = width;
- this->height = height;
-
- // Allocate/define image
- this->image = mlt_pool_alloc( width * ( height + 1 ) * 2 );
- this->alpha = mlt_pool_alloc( this->width * this->height );
-
- // Convert the image
- mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
- this->width, this->height,
- gdk_pixbuf_get_rowstride( pixbuf ),
- this->image, this->alpha );
-
- // Finished with pixbuf now
- g_object_unref( pixbuf );
- }
-
- // Set width/height
- mlt_properties_set_int( properties, "width", this->width );
- mlt_properties_set_int( properties, "height", this->height );
- mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "real_width" ) );
- mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "real_height" ) );
-
- // pass the image data without destructor
- mlt_properties_set_data( properties, "image", this->image, this->width * ( this->height + 1 ) * 2, NULL, NULL );
- mlt_properties_set_data( properties, "alpha", this->alpha, this->width * this->height, NULL, NULL );
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // We need to know the size of the image to clone it
- int image_size = 0;
- int alpha_size = 0;
-
- // Alpha channel
- uint8_t *alpha = NULL;
-
- *width = mlt_properties_get_int( properties, "rescale_width" );
- *height = mlt_properties_get_int( properties, "rescale_height" );
-
- // Refresh the image
- pthread_mutex_lock( &pango_mutex );
- refresh_image( frame, *width, *height );
-
- // Get the image
- *buffer = mlt_properties_get_data( properties, "image", &image_size );
- alpha = mlt_properties_get_data( properties, "alpha", &alpha_size );
-
- // Get width and height
- *width = mlt_properties_get_int( properties, "width" );
- *height = mlt_properties_get_int( properties, "height" );
-
- // Always clone here to allow 'animated' text
- if ( *buffer != NULL )
- {
- // Clone the image and the alpha
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- uint8_t *alpha_copy = mlt_pool_alloc( alpha_size );
-
- memcpy( image_copy, *buffer, image_size );
-
- // Copy or default the alpha
- if ( alpha != NULL )
- memcpy( alpha_copy, alpha, alpha_size );
- else
- memset( alpha_copy, 255, alpha_size );
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL );
-
- // We're going to pass the copy on
- *buffer = image_copy;
- }
- else
- {
- // TODO: Review all cases of invalid images
- *buffer = mlt_pool_alloc( 50 * 50 * 2 );
- mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL );
- *width = 50;
- *height = 50;
- }
-
- pthread_mutex_unlock( &pango_mutex );
-
- return 0;
-}
-
-static uint8_t *producer_get_alpha_mask( mlt_frame this )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Return the alpha mask
- return mlt_properties_get_data( properties, "alpha", NULL );
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- producer_pango this = producer->child;
-
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Set the producer on the frame properties
- mlt_properties_set_data( properties, "producer_pango", this, 0, NULL, NULL );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
- mlt_properties_set_position( properties, "pango_position", mlt_producer_frame( producer ) );
-
- // Refresh the pango image
- pthread_mutex_lock( &pango_mutex );
- refresh_image( *frame, 0, 0 );
- pthread_mutex_unlock( &pango_mutex );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", 1 );
-
- // Set alpha call back
- ( *frame )->get_alpha_mask = producer_get_alpha_mask;
-
- // Stack the get image callback
- mlt_frame_push_get_image( *frame, producer_get_image );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- producer_pango this = parent->child;
- mlt_pool_release( this->image );
- mlt_pool_release( this->alpha );
- free( this->fgcolor );
- free( this->bgcolor );
- free( this->markup );
- free( this->text );
- free( this->font );
- parent->close = NULL;
- mlt_producer_close( parent );
- free( this );
-}
-
-static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg )
-{
- int ww = gdk_pixbuf_get_width( pixbuf );
- int hh = gdk_pixbuf_get_height( pixbuf );
- uint8_t *p = gdk_pixbuf_get_pixels( pixbuf );
- int i, j;
-
- for ( j = 0; j < hh; j++ )
- {
- for ( i = 0; i < ww; i++ )
- {
- *p++ = bg.r;
- *p++ = bg.g;
- *p++ = bg.b;
- *p++ = bg.a;
- }
- }
-}
-
-static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font, rgba_color fg, rgba_color bg, int pad, int align, int weight, int size )
-{
- PangoContext *context = pango_ft2_font_map_create_context( fontmap );
- PangoLayout *layout = pango_layout_new( context );
- int w, h, x;
- int i, j;
- GdkPixbuf *pixbuf = NULL;
- FT_Bitmap bitmap;
- uint8_t *src = NULL;
- uint8_t* dest = NULL;
- uint8_t *d, *s, a;
- int stride;
- PangoFontDescription *desc = pango_font_description_from_string( font );
-
- pango_ft2_font_map_set_resolution( fontmap, 72, 72 );
- pango_layout_set_width( layout, -1 ); // set wrapping constraints
- pango_font_description_set_weight( desc, ( PangoWeight ) weight );
- if ( size != 0 )
- pango_font_description_set_absolute_size( desc, PANGO_SCALE * size );
- pango_layout_set_font_description( layout, desc );
-// pango_layout_set_spacing( layout, space );
- pango_layout_set_alignment( layout, ( PangoAlignment ) align );
- if ( markup != NULL && strcmp( markup, "" ) != 0 )
- {
- pango_layout_set_markup( layout, markup, strlen( markup ) );
- }
- else if ( text != NULL && strcmp( text, "" ) != 0 )
- {
- // Replace all ~'s with a line feed (silly convention, but handy)
- char *copy = strdup( text );
- while ( strchr( copy, '~' ) )
- ( *strchr( copy, '~' ) ) = '\n';
- pango_layout_set_text( layout, copy, strlen( copy ) );
- free( copy );
- }
- else
- {
- // Pango doesn't like empty strings
- pango_layout_set_text( layout, " ", 2 );
- }
- pango_layout_get_pixel_size( layout, &w, &h );
-
- // Interpret size property as an absolute pixel height and compensate for
- // freetype's "interpretation" of our absolute size request. This gives
- // precise control over compositing and better quality by reducing scaling
- // artifacts with composite geometries that constrain the dimensions.
- // If you do not want this, then put the size in the font property or in
- // the pango markup.
- if ( size != 0 )
- {
- pango_font_description_set_absolute_size( desc, PANGO_SCALE * size * size/h );
- pango_layout_set_font_description( layout, desc );
- pango_layout_get_pixel_size( layout, &w, &h );
- }
-
- pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad );
- pango_draw_background( pixbuf, bg );
-
- stride = gdk_pixbuf_get_rowstride( pixbuf );
-
- bitmap.width = w;
- bitmap.pitch = 32 * ( ( w + 31 ) / 31 );
- bitmap.rows = h;
- bitmap.buffer = mlt_pool_alloc( h * bitmap.pitch );
- bitmap.num_grays = 256;
- bitmap.pixel_mode = ft_pixel_mode_grays;
-
- memset( bitmap.buffer, 0, h * bitmap.pitch );
-
- pango_ft2_render_layout( &bitmap, layout, 0, 0 );
-
- src = bitmap.buffer;
- x = ( gdk_pixbuf_get_width( pixbuf ) - w - 2 * pad ) * align / 2 + pad;
- dest = gdk_pixbuf_get_pixels( pixbuf ) + 4 * x + pad * stride;
- j = h;
-
- while( j -- )
- {
- d = dest;
- s = src;
- i = w;
- while( i -- )
- {
- a = *s ++;
- *d++ = ( a * fg.r + ( 255 - a ) * bg.r ) >> 8;
- *d++ = ( a * fg.g + ( 255 - a ) * bg.g ) >> 8;
- *d++ = ( a * fg.b + ( 255 - a ) * bg.b ) >> 8;
- *d++ = ( a * fg.a + ( 255 - a ) * bg.a ) >> 8;
- }
- dest += stride;
- src += bitmap.pitch;
- }
- mlt_pool_release( bitmap.buffer );
- pango_font_description_free( desc );
- g_object_unref( layout );
- g_object_unref( context );
-
- return pixbuf;
-}
+++ /dev/null
-/*
- * producer_pixbuf.c -- raster image loader based upon gdk-pixbuf
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_cache.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-
-static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-typedef struct producer_pixbuf_s *producer_pixbuf;
-
-struct producer_pixbuf_s
-{
- struct mlt_producer_s parent;
-
- // File name list
- mlt_properties filenames;
- int count;
- int image_idx;
-
- int width;
- int height;
- uint8_t *image;
- uint8_t *alpha;
- mlt_cache_item image_cache;
- mlt_cache_item alpha_cache;
- pthread_mutex_t mutex;
-};
-
-static void load_filenames( producer_pixbuf this, mlt_properties producer_properties );
-static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int height );
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_pixbuf_init( char *filename )
-{
- producer_pixbuf this = calloc( sizeof( struct producer_pixbuf_s ), 1 );
- if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- mlt_producer producer = &this->parent;
-
- // Get the properties interface
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
-
- // Callback registration
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- // Set the default properties
- mlt_properties_set( properties, "resource", filename );
- mlt_properties_set_int( properties, "ttl", 25 );
- mlt_properties_set_int( properties, "aspect_ratio", 1 );
- mlt_properties_set_int( properties, "progressive", 1 );
-
- // Validate the resource
- if ( filename )
- load_filenames( this, properties );
- if ( this->count )
- {
- mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
- if ( frame )
- {
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
- pthread_mutex_init( &this->mutex, NULL );
- mlt_properties_set_data( frame_properties, "producer_pixbuf", this, 0, NULL, NULL );
- mlt_frame_set_position( frame, mlt_producer_position( producer ) );
- mlt_properties_set_position( frame_properties, "pixbuf_position", mlt_producer_position( producer ) );
- refresh_image( this, frame, 0, 0 );
- mlt_frame_close( frame );
- }
- }
- if ( this->width == 0 )
- {
- producer_close( producer );
- producer = NULL;
- }
- return producer;
- }
- free( this );
- return NULL;
-}
-
-static void load_filenames( producer_pixbuf this, mlt_properties producer_properties )
-{
- char *filename = mlt_properties_get( producer_properties, "resource" );
- this->filenames = mlt_properties_new( );
-
- // Read xml string
- if ( strstr( filename, "<svg" ) )
- {
- // Generate a temporary file for the svg
- char fullname[ 1024 ] = "/tmp/mlt.XXXXXX";
- int fd = mkstemp( fullname );
-
- if ( fd > -1 )
- {
- // Write the svg into the temp file
- ssize_t remaining_bytes;
- char *xml = filename;
-
- // Strip leading crap
- while ( xml[0] != '<' )
- xml++;
-
- remaining_bytes = strlen( xml );
- while ( remaining_bytes > 0 )
- remaining_bytes -= write( fd, xml + strlen( xml ) - remaining_bytes, remaining_bytes );
- close( fd );
-
- mlt_properties_set( this->filenames, "0", fullname );
-
- // Teehe - when the producer closes, delete the temp file and the space allo
- mlt_properties_set_data( producer_properties, "__temporary_file__", fullname, 0, ( mlt_destructor )unlink, NULL );
- }
- }
- // Obtain filenames
- else if ( strchr( filename, '%' ) != NULL )
- {
- // handle picture sequences
- int i = mlt_properties_get_int( producer_properties, "begin" );
- int gap = 0;
- char full[1024];
- int keyvalue = 0;
- char key[ 50 ];
-
- while ( gap < 100 )
- {
- struct stat buf;
- snprintf( full, 1023, filename, i ++ );
- if ( stat( full, &buf ) == 0 )
- {
- sprintf( key, "%d", keyvalue ++ );
- mlt_properties_set( this->filenames, key, full );
- gap = 0;
- }
- else
- {
- gap ++;
- }
- }
- }
- else if ( strstr( filename, "/.all." ) != NULL )
- {
- char wildcard[ 1024 ];
- char *dir_name = strdup( filename );
- char *extension = strrchr( dir_name, '.' );
-
- *( strstr( dir_name, "/.all." ) + 1 ) = '\0';
- sprintf( wildcard, "*%s", extension );
-
- mlt_properties_dir_list( this->filenames, dir_name, wildcard, 1 );
-
- free( dir_name );
- }
- else
- {
- mlt_properties_set( this->filenames, "0", filename );
- }
-
- this->count = mlt_properties_count( this->filenames );
-}
-
-static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int height )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer
- mlt_producer producer = &this->parent;
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Obtain the cache flag and structure
- int use_cache = mlt_properties_get_int( producer_props, "cache" );
- mlt_properties cache = mlt_properties_get_data( producer_props, "_cache", NULL );
- int update_cache = 0;
-
- // restore GdkPixbuf
- pthread_mutex_lock( &this->mutex );
- mlt_cache_item pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
- GdkPixbuf *pixbuf = mlt_cache_item_data( pixbuf_cache, NULL );
- GError *error = NULL;
-
- // restore scaled image
- this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
- this->image = mlt_cache_item_data( this->image_cache, NULL );
-
- // restore alpha channel
- this->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
- this->alpha = mlt_cache_item_data( this->alpha_cache, NULL );
-
- // Check if user wants us to reload the image
- if ( mlt_properties_get_int( producer_props, "force_reload" ) )
- {
- pixbuf = NULL;
- this->image = NULL;
- mlt_properties_set_int( producer_props, "force_reload", 0 );
- }
-
- // Get the time to live for each frame
- double ttl = mlt_properties_get_int( producer_props, "ttl" );
-
- // Get the original position of this frame
- mlt_position position = mlt_properties_get_position( properties, "pixbuf_position" );
- position += mlt_producer_get_in( producer );
-
- // Image index
- int image_idx = ( int )floor( ( double )position / ttl ) % this->count;
-
- // Key for the cache
- char image_key[ 10 ];
- sprintf( image_key, "%d", image_idx );
-
- pthread_mutex_lock( &g_mutex );
-
- // Check if the frame is already loaded
- if ( use_cache )
- {
- if ( cache == NULL )
- {
- cache = mlt_properties_new( );
- mlt_properties_set_data( producer_props, "_cache", cache, 0, ( mlt_destructor )mlt_properties_close, NULL );
- }
-
- mlt_frame cached = mlt_properties_get_data( cache, image_key, NULL );
-
- if ( cached )
- {
- this->image_idx = image_idx;
- mlt_properties cached_props = MLT_FRAME_PROPERTIES( cached );
- this->width = mlt_properties_get_int( cached_props, "width" );
- this->height = mlt_properties_get_int( cached_props, "height" );
- mlt_properties_set_int( producer_props, "_real_width", mlt_properties_get_int( cached_props, "real_width" ) );
- mlt_properties_set_int( producer_props, "_real_height", mlt_properties_get_int( cached_props, "real_height" ) );
- this->image = mlt_properties_get_data( cached_props, "image", NULL );
- this->alpha = mlt_properties_get_data( cached_props, "alpha", NULL );
-
- if ( width != 0 && ( width != this->width || height != this->height ) )
- this->image = NULL;
- }
- }
-
- // optimization for subsequent iterations on single picture
- if ( width != 0 && ( image_idx != this->image_idx || width != this->width || height != this->height ) )
- this->image = NULL;
- if ( image_idx != this->image_idx )
- pixbuf = NULL;
- if ( pixbuf == NULL && ( width == 0 || this->image == NULL ) )
- {
- this->image = NULL;
- this->image_idx = image_idx;
- pixbuf = gdk_pixbuf_new_from_file( mlt_properties_get_value( this->filenames, image_idx ), &error );
-
- if ( pixbuf )
- {
- // Register this pixbuf for destruction and reuse
- mlt_cache_item_close( pixbuf_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf", pixbuf, 0, ( mlt_destructor )g_object_unref );
- pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
-
- mlt_events_block( producer_props, NULL );
- mlt_properties_set_int( producer_props, "_real_width", gdk_pixbuf_get_width( pixbuf ) );
- mlt_properties_set_int( producer_props, "_real_height", gdk_pixbuf_get_height( pixbuf ) );
- mlt_events_unblock( producer_props, NULL );
-
- // Store the width/height of the pixbuf temporarily
- this->width = gdk_pixbuf_get_width( pixbuf );
- this->height = gdk_pixbuf_get_height( pixbuf );
- }
- }
-
- // If we have a pixbuf and we need an image
- if ( pixbuf && width > 0 && this->image == NULL )
- {
- char *interps = mlt_properties_get( properties, "rescale.interp" );
- int interp = GDK_INTERP_BILINEAR;
-
- if ( strcmp( interps, "nearest" ) == 0 )
- interp = GDK_INTERP_NEAREST;
- else if ( strcmp( interps, "tiles" ) == 0 )
- interp = GDK_INTERP_TILES;
- else if ( strcmp( interps, "hyper" ) == 0 )
- interp = GDK_INTERP_HYPER;
-
- // Note - the original pixbuf is already safe and ready for destruction
- pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp );
-
- // Store width and height
- this->width = width;
- this->height = height;
-
- // Allocate/define image
- this->image = mlt_pool_alloc( width * ( height + 1 ) * 2 );
- if ( !use_cache )
- mlt_cache_item_close( this->image_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", this->image, width * ( height + 1 ) * 2, mlt_pool_release );
- this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
-
- // Extract YUV422 and alpha
- if ( gdk_pixbuf_get_has_alpha( pixbuf ) )
- {
- // Allocate the alpha mask
- this->alpha = mlt_pool_alloc( this->width * this->height );
- if ( !use_cache )
- mlt_cache_item_close( this->alpha_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", this->alpha, width * height, mlt_pool_release );
- this->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
-
- // Convert the image
- mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
- this->width, this->height,
- gdk_pixbuf_get_rowstride( pixbuf ),
- this->image, this->alpha );
- }
- else
- {
- // No alpha to extract
- mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
- this->width, this->height,
- gdk_pixbuf_get_rowstride( pixbuf ),
- this->image );
- }
-
- // Finished with pixbuf now
- g_object_unref( pixbuf );
-
- // Ensure we update the cache when we need to
- update_cache = use_cache;
- }
-
- // release references no longer needed
- mlt_cache_item_close( pixbuf_cache );
- if ( width == 0 )
- {
- pthread_mutex_unlock( &this->mutex );
- mlt_cache_item_close( this->image_cache );
- mlt_cache_item_close( this->alpha_cache );
- }
-
- // Set width/height of frame
- mlt_properties_set_int( properties, "width", this->width );
- mlt_properties_set_int( properties, "height", this->height );
- mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) );
- mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) );
-
- if ( update_cache )
- {
- mlt_frame cached = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
- mlt_properties cached_props = MLT_FRAME_PROPERTIES( cached );
- mlt_properties_set_int( cached_props, "width", this->width );
- mlt_properties_set_int( cached_props, "height", this->height );
- mlt_properties_set_int( cached_props, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) );
- mlt_properties_set_int( cached_props, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) );
- mlt_properties_set_data( cached_props, "image", this->image, this->width * ( this->height + 1 ) * 2, mlt_pool_release, NULL );
- mlt_properties_set_data( cached_props, "alpha", this->alpha, this->width * this->height, mlt_pool_release, NULL );
- mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
-
- pthread_mutex_unlock( &g_mutex );
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer for this frame
- producer_pixbuf this = mlt_properties_get_data( properties, "producer_pixbuf", NULL );
-
- *width = mlt_properties_get_int( properties, "rescale_width" );
- *height = mlt_properties_get_int( properties, "rescale_height" );
-
- // Refresh the image
- refresh_image( this, frame, *width, *height );
-
- // Get the image size
- int image_size = this->width * ( this->height + 1 ) * 2;
- int alpha_size = this->width * this->height;
-
- // Get width and height (may have changed during the refresh)
- *width = mlt_properties_get_int( properties, "width" );
- *height = mlt_properties_get_int( properties, "height" );
-
- // NB: Cloning is necessary with this producer (due to processing of images ahead of use)
- // The fault is not in the design of mlt, but in the implementation of the pixbuf producer...
- if ( this->image )
- {
- if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p )
- {
- // Clone the image and the alpha
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- uint8_t *alpha_copy = mlt_pool_alloc( alpha_size );
-
- memcpy( image_copy, this->image, image_size );
-
- // Copy or default the alpha
- if ( this->alpha != NULL )
- memcpy( alpha_copy, this->alpha, alpha_size );
- else
- memset( alpha_copy, 255, alpha_size );
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL );
-
- // We're going to pass the copy on
- *buffer = image_copy;
- }
- else if ( *format == mlt_image_rgb24a )
- {
- // Clone the image and the alpha
- image_size = *width * ( *height + 1 ) * 4;
- alpha_size = *width * ( *height + 1 );
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- uint8_t *alpha_copy = mlt_pool_alloc( alpha_size );
-
- mlt_convert_yuv422_to_rgb24a( this->image, image_copy, (*width)*(*height) );
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL );
-
- // We're going to pass the copy on
- *buffer = image_copy;
- }
-
- }
- else
- {
- // TODO: Review all cases of invalid images
- *buffer = mlt_pool_alloc( 50 * 50 * 2 );
- mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL );
- *width = 50;
- *height = 50;
- }
-
- // Release references and locks
- pthread_mutex_unlock( &this->mutex );
- mlt_cache_item_close( this->image_cache );
- mlt_cache_item_close( this->alpha_cache );
-
- return 0;
-}
-
-static uint8_t *producer_get_alpha_mask( mlt_frame this )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Return the alpha mask
- return mlt_properties_get_data( properties, "alpha", NULL );
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Get the real structure for this producer
- producer_pixbuf this = producer->child;
-
- // Fetch the producers properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- if ( this->filenames == NULL && mlt_properties_get( producer_properties, "resource" ) != NULL )
- load_filenames( this, producer_properties );
-
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- if ( *frame != NULL && this->count > 0 )
- {
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Set the producer on the frame properties
- mlt_properties_set_data( properties, "producer_pixbuf", this, 0, NULL, NULL );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Ensure that we have a way to obtain the position in the get_image
- mlt_properties_set_position( properties, "pixbuf_position", mlt_producer_position( producer ) );
-
- // Refresh the image
- refresh_image( this, *frame, 0, 0 );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_properties, "aspect_ratio" ) );
-
- // Set alpha call back
- ( *frame )->get_alpha_mask = producer_get_alpha_mask;
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- producer_pixbuf this = parent->child;
- pthread_mutex_destroy( &this->mutex );
- parent->close = NULL;
- mlt_producer_close( parent );
- mlt_properties_close( this->filenames );
- free( this );
-}
+++ /dev/null
-/*
- * scale_line_22_yuv_mmx.S -- scale line in YUY2 format
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- .file "scale_line_22_yuv_mmx.S"
- .version "01.01"
-
-.extern printf
-
-gcc2_compiled.:
-.data
-MSG: .ascii "scale_line_22_yuv_mmx: %d %d\n"
-
-.text
- .align 16
-
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-
-.globl pixops_scale_line_22_yuv_mmx
- .type pixops_scale_line_22_yuv_mmx,@function
-pixops_scale_line_22_yuv_mmx:
-
-#else
-
-.globl _pixops_scale_line_22_yuv_mmx
-_pixops_scale_line_22_yuv_mmx:
-
-#endif
-/*
- * Arguments
- *
- * weights: 8(%ebp)
- * p (dest): 12(%ebp) %esi
- * q1 (src0): 16(%ebp)
- * q2 (src1): 20(%ebp)
- * xstep: 24(%ebp)
- * p_end: 28(%ebp)
- * xinit: 32(%ebp)
- * dest_x: 36(%ebp)
- *
- */
-
-/*
- * Function call entry
- */
- pushl %ebp
- movl %esp,%ebp
- subl $28,%esp
- pushl %edi
- pushl %esi
- pushl %ebx
-/* Locals:
- * int x %ebx
- * int x_scaled -24(%ebp)
- * int dest_x 36(%ebp)
- */
-
-/*
- * Setup
- */
-/* Initialize variables */
- movl 36(%ebp),%eax # destx
- movl %eax,36(%ebp)
- movl 32(%ebp),%ebx # x
- movl 12(%ebp),%esi # dest
-
- cmpl 28(%ebp),%esi # dest == dest_end ?
- jnb .out
-
-/* For the body of this loop, %mm0, %mm1, %mm2, %mm3 hold the 4 adjoining
- * points we are interpolating between, as:
- *
- * 00VV00Y200UU00Y1
- */
-
- pxor %mm4, %mm4
-/*
- * Load next component values into mm1 (src0) and mm3 (src1)
- */
- movl %ebx, %eax # x_scaled
- sarl $15, %eax
- andl $0xfffffffe, %eax
- movl %eax, %edx # x_aligned
- andl $0xfffffffc, %edx
-
- movl 16(%ebp), %edi # get src0
- movl (%edi,%eax), %ecx # get y
- andl $0x00ff00ff, %ecx # mask off y
- movl (%edi,%edx), %eax # get uv
- andl $0xff00ff00, %eax # mask off uv
- orl %eax, %ecx # composite y, uv
- movd %ecx, %mm1 # move to mmx1
- punpcklbw %mm4, %mm1
-
- movl 20(%ebp), %edi # get src1
- movl (%edi,%edx), %ecx # get y
- andl $0x00ff00ff, %ecx # mask off y
- movl (%edi,%edx), %eax # get uv
- andl $0xff00ff00, %eax # mask off uv
- orl %eax, %ecx # composite y, uv
- movd %ecx, %mm3 # move to mmx3
- punpcklbw %mm4, %mm3
-
- jmp .newx
-
- .p2align 4,,7
-.loop:
-
-/* short *pixel_weights = weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_x * n_y
- * 16 4 0xf 2 2
- */
- movl 8(%ebp), %edi # get weights pointer
- movl %ebx, %eax
- andl $0xf000, %eax
- shrl $7, %eax
-
-/* At this point, %edi holds weights. Load the 4 weights into
- * %mm4,%mm5,%mm6,%mm7, multiply and accumulate.
- */
- movq (%edi,%eax), %mm4
- pmullw %mm0, %mm4
- movq 8(%edi,%eax), %mm5
- pmullw %mm1, %mm5
- movq 16(%edi,%eax), %mm6
- pmullw %mm2,%mm6
- movq 24(%edi,%eax), %mm7
- pmullw %mm3,%mm7
-
- paddw %mm4, %mm5
- paddw %mm6, %mm7
- paddw %mm5, %mm7
-
-/* %mm7 holds the accumulated sum. Compute (C + 0x80) / 256
- */
- pxor %mm4, %mm4
- movl $0x80808080, %eax
- movd %eax, %mm6
- punpcklbw %mm4, %mm6
- paddw %mm6, %mm7
- psrlw $8, %mm7
-
-/* Pack into %eax and store result
- */
- packuswb %mm7, %mm7
- movd %mm7, %eax
-
- movb %al, (%esi) # *dest = y
-
- movl 36(%ebp), %ecx # get dest_x
- andl $1, %ecx # select u or v
- sall $1, %ecx # determine offset
- addl $1, %ecx # relative to x_aligned
- sall $3, %ecx # offset * 8 bits/byte
-
- movd %mm7, %eax
- shrl %cl, %eax
- movb %al, 1(%esi) # *dest = uv
-
- addl $2, %esi # dest += 2
- cmpl %esi,28(%ebp) # if dest == dest_end
- je .out # then exit
-
- addl $1, 36(%ebp) # dest_x++
-
-.newx:
-
- addl 24(%ebp), %ebx # x += x_step
-/*
- * Load current component values into mm0 (src0) and mm2 (src1)
- */
- movq %mm1, %mm0
- movq %mm3, %mm2
-
-/*
- * Load next component values into mm1 (src0) and mm3 (src1)
- */
- movl %ebx, %eax # x_scaled
- sarl $15, %eax
- andl $0xfffffffe, %eax
- movl %eax, %edx # x_aligned
- andl $0xfffffffc, %edx
-
- movl 16(%ebp), %edi # get src0
- movl (%edi,%eax), %ecx # get y
- andl $0x00ff00ff, %ecx # mask off y
- movl (%edi,%edx), %eax # get uv
- andl $0xff00ff00, %eax # mask off uv
- orl %eax, %ecx # composite y, uv
- movd %ecx, %mm1 # move to mmx1
- punpcklbw %mm4, %mm1
-
- movl 20(%ebp), %edi # get src1
- movl (%edi,%edx), %ecx # get y
- andl $0x00ff00ff, %ecx # mask off y
- movl (%edi,%edx), %eax # get uv
- andl $0xff00ff00, %eax # mask off uv
- orl %eax, %ecx # composite y, uv
- movd %ecx, %mm3 # move to mmx3
- punpcklbw %mm4, %mm3
-
- jmp .loop
-
-.out:
- movl %esi,%eax
- emms
- leal -40(%ebp),%esp
- popl %ebx
- popl %esi
- popl %edi
- movl %ebp,%esp
- popl %ebp
- ret
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltinigo$(LIBSUF)
-
-OBJS = factory.o \
- producer_inigo.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_producer producer_inigo_file_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_inigo_init( mlt_profile profile, mlt_service_type type, const char *id, char **argv );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( producer_type, "inigo", producer_inigo_init );
- MLT_REGISTER( producer_type, "inigo_file", producer_inigo_file_init );
-}
+++ /dev/null
-/*
- * producer_inigo.c -- simple inigo test case
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <framework/mlt.h>
-
-mlt_producer producer_inigo_init( mlt_profile profile, mlt_service_type type, const char *id, char **argv );
-
-mlt_producer producer_inigo_file_init( mlt_profile profile, mlt_service_type type, const char *id, char *file )
-{
- FILE *input = fopen( file, "r" );
- char **args = calloc( sizeof( char * ), 1000 );
- int count = 0;
- char temp[ 2048 ];
-
- if ( input != NULL )
- {
- while( fgets( temp, 2048, input ) )
- {
- temp[ strlen( temp ) - 1 ] = '\0';
- if ( strcmp( temp, "" ) )
- args[ count ++ ] = strdup( temp );
- }
- }
-
- mlt_producer result = producer_inigo_init( profile, type, id, args );
-
- if ( result != NULL )
- {
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( result );
- mlt_properties_set( properties, "resource", file );
- }
-
- while( count -- )
- free( args[ count ] );
- free( args );
-
- return result;
-}
-
-static void track_service( mlt_field field, void *service, mlt_destructor destructor )
-{
- mlt_properties properties = mlt_field_properties( field );
- int registered = mlt_properties_get_int( properties, "registered" );
- char *key = mlt_properties_get( properties, "registered" );
- mlt_properties_set_data( properties, key, service, 0, destructor, NULL );
- mlt_properties_set_int( properties, "registered", ++ registered );
-}
-
-static mlt_producer create_producer( mlt_profile profile, mlt_field field, char *file )
-{
- mlt_producer result = mlt_factory_producer( profile, "fezzik", file );
-
- if ( result != NULL )
- track_service( field, result, ( mlt_destructor )mlt_producer_close );
-
- return result;
-}
-
-static mlt_filter create_attach( mlt_profile profile, mlt_field field, char *id, int track )
-{
- char *temp = strdup( id );
- char *arg = strchr( temp, ':' );
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_filter filter = mlt_factory_filter( profile, temp, arg );
- if ( filter != NULL )
- track_service( field, filter, ( mlt_destructor )mlt_filter_close );
- free( temp );
- return filter;
-}
-
-static mlt_filter create_filter( mlt_profile profile, mlt_field field, char *id, int track )
-{
- char *temp = strdup( id );
- char *arg = strchr( temp, ':' );
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_filter filter = mlt_factory_filter( profile, temp, arg );
- if ( filter != NULL )
- {
- mlt_field_plant_filter( field, filter, track );
- track_service( field, filter, ( mlt_destructor )mlt_filter_close );
- }
- free( temp );
- return filter;
-}
-
-static mlt_transition create_transition( mlt_profile profile, mlt_field field, char *id, int track )
-{
- char *arg = strchr( id, ':' );
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_transition transition = mlt_factory_transition( profile, id, arg );
- if ( transition != NULL )
- {
- mlt_field_plant_transition( field, transition, track, track + 1 );
- track_service( field, transition, ( mlt_destructor )mlt_transition_close );
- }
- return transition;
-}
-
-mlt_producer producer_inigo_init( mlt_profile profile, mlt_service_type type, const char *id, char **argv )
-{
- int i;
- int track = 0;
- mlt_producer producer = NULL;
- mlt_tractor mix = NULL;
- mlt_playlist playlist = mlt_playlist_init( );
- mlt_properties group = mlt_properties_new( );
- mlt_tractor tractor = mlt_tractor_new( );
- mlt_properties properties = MLT_TRACTOR_PROPERTIES( tractor );
- mlt_field field = mlt_tractor_field( tractor );
- mlt_properties field_properties = mlt_field_properties( field );
- mlt_multitrack multitrack = mlt_tractor_multitrack( tractor );
- char *title = NULL;
-
- // Assistance for template construction (allows -track usage to specify the first track)
- mlt_properties_set_int( MLT_PLAYLIST_PROPERTIES( playlist ), "_inigo_first", 1 );
-
- // We need to track the number of registered filters
- mlt_properties_set_int( field_properties, "registered", 0 );
-
- // Parse the arguments
- if ( argv )
- for ( i = 0; argv[ i ] != NULL; i ++ )
- {
- if ( !strcmp( argv[ i ], "-group" ) )
- {
- if ( mlt_properties_count( group ) != 0 )
- {
- mlt_properties_close( group );
- group = mlt_properties_new( );
- }
- if ( group != NULL )
- properties = group;
- }
- else if ( !strcmp( argv[ i ], "-attach" ) ||
- !strcmp( argv[ i ], "-attach-cut" ) ||
- !strcmp( argv[ i ], "-attach-track" ) ||
- !strcmp( argv[ i ], "-attach-clip" ) )
- {
- int type = !strcmp( argv[ i ], "-attach" ) ? 0 :
- !strcmp( argv[ i ], "-attach-cut" ) ? 1 :
- !strcmp( argv[ i ], "-attach-track" ) ? 2 : 3;
- mlt_filter filter = create_attach( profile, field, argv[ ++ i ], track );
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_append( playlist, producer );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- }
-
- if ( type == 1 || type == 2 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- }
-
- if ( filter != NULL && mlt_playlist_count( playlist ) > 0 )
- {
- if ( type == 0 )
- mlt_service_attach( ( mlt_service )properties, filter );
- else if ( type == 1 )
- mlt_service_attach( ( mlt_service )producer, filter );
- else if ( type == 2 )
- mlt_service_attach( ( mlt_service )playlist, filter );
- else if ( type == 3 )
- mlt_service_attach( ( mlt_service )mlt_producer_cut_parent( producer ), filter );
-
- properties = MLT_FILTER_PROPERTIES( filter );
- mlt_properties_inherit( properties, group );
- }
- else if ( filter != NULL )
- {
- mlt_service_attach( ( mlt_service )playlist, filter );
- properties = MLT_FILTER_PROPERTIES( filter );
- mlt_properties_inherit( properties, group );
- }
- }
- else if ( !strcmp( argv[ i ], "-repeat" ) )
- {
- int repeat = atoi( argv[ ++ i ] );
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) > 0 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_repeat_clip( playlist, mlt_playlist_count( playlist ) - 1, repeat );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- }
- else if ( !strcmp( argv[ i ], "-split" ) )
- {
- int split = atoi( argv[ ++ i ] );
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) > 0 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- split = split < 0 ? info.frame_out + split : split;
- mlt_playlist_split( playlist, mlt_playlist_count( playlist ) - 1, split );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- }
- else if ( !strcmp( argv[ i ], "-swap" ) )
- {
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) >= 2 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_move( playlist, mlt_playlist_count( playlist ) - 2, mlt_playlist_count( playlist ) - 1 );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- }
- else if ( !strcmp( argv[ i ], "-join" ) )
- {
- int clips = atoi( argv[ ++ i ] );
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) > 0 )
- {
- mlt_playlist_clip_info info;
- int clip = clips <= 0 ? 0 : mlt_playlist_count( playlist ) - clips - 1;
- if ( clip < 0 ) clip = 0;
- if ( clip >= mlt_playlist_count( playlist ) ) clip = mlt_playlist_count( playlist ) - 2;
- if ( clips < 0 ) clips = mlt_playlist_count( playlist ) - 1;
- mlt_playlist_join( playlist, clip, clips, 0 );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- }
- else if ( !strcmp( argv[ i ], "-remove" ) )
- {
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) > 0 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_remove( playlist, mlt_playlist_count( playlist ) - 1 );
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- producer = info.cut;
- properties = MLT_PRODUCER_PROPERTIES( producer );
- }
- }
- else if ( !strcmp( argv[ i ], "-mix" ) )
- {
- int length = atoi( argv[ ++ i ] );
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( mlt_playlist_count( playlist ) >= 2 )
- {
- if ( mlt_playlist_mix( playlist, mlt_playlist_count( playlist ) - 2, length, NULL ) == 0 )
- {
- mlt_playlist_clip_info info;
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 1 );
- if ( mlt_properties_get_data( ( mlt_properties )info.producer, "mlt_mix", NULL ) == NULL )
- mlt_playlist_get_clip_info( playlist, &info, mlt_playlist_count( playlist ) - 2 );
- mix = ( mlt_tractor )mlt_properties_get_data( ( mlt_properties )info.producer, "mlt_mix", NULL );
- properties = NULL;
- }
- else
- {
- fprintf( stderr, "Mix failed?\n" );
- }
- }
- else
- {
- fprintf( stderr, "Invalid position for a mix...\n" );
- }
- }
- else if ( !strcmp( argv[ i ], "-mixer" ) )
- {
- if ( mix != NULL )
- {
- char *id = strdup( argv[ ++ i ] );
- char *arg = strchr( id, ':' );
- mlt_field field = mlt_tractor_field( mix );
- mlt_transition transition = NULL;
- if ( arg != NULL )
- *arg ++ = '\0';
- transition = mlt_factory_transition( profile, id, arg );
- if ( transition != NULL )
- {
- properties = MLT_TRANSITION_PROPERTIES( transition );
- mlt_properties_inherit( properties, group );
- mlt_field_plant_transition( field, transition, 0, 1 );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", mlt_producer_get_out( ( mlt_producer )mix ) );
- mlt_transition_close( transition );
- }
- free( id );
- }
- else
- {
- fprintf( stderr, "Invalid mixer...\n" );
- }
- }
- else if ( !strcmp( argv[ i ], "-filter" ) )
- {
- mlt_filter filter = create_filter( profile, field, argv[ ++ i ], track );
- if ( filter != NULL )
- {
- properties = MLT_FILTER_PROPERTIES( filter );
- mlt_properties_inherit( properties, group );
- }
- }
- else if ( !strcmp( argv[ i ], "-transition" ) )
- {
- mlt_transition transition = create_transition( profile, field, argv[ ++ i ], track - 1 );
- if ( transition != NULL )
- {
- properties = MLT_TRANSITION_PROPERTIES( transition );
- mlt_properties_inherit( properties, group );
- }
- }
- else if ( !strcmp( argv[ i ], "-blank" ) )
- {
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- mlt_playlist_blank( playlist, atof( argv[ ++ i ] ) );
- }
- else if ( !strcmp( argv[ i ], "-track" ) ||
- !strcmp( argv[ i ], "-null-track" ) ||
- !strcmp( argv[ i ], "-video-track" ) ||
- !strcmp( argv[ i ], "-audio-track" ) ||
- !strcmp( argv[ i ], "-hide-track" ) ||
- !strcmp( argv[ i ], "-hide-video" ) ||
- !strcmp( argv[ i ], "-hide-audio" ) )
- {
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- producer = NULL;
- if ( !mlt_properties_get_int( MLT_PLAYLIST_PROPERTIES( playlist ), "_inigo_first" ) ||
- mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( playlist ) ) > 0 )
- {
- mlt_multitrack_connect( multitrack, MLT_PLAYLIST_PRODUCER( playlist ), track ++ );
- track_service( field, playlist, ( mlt_destructor )mlt_playlist_close );
- playlist = mlt_playlist_init( );
- }
- if ( playlist != NULL )
- {
- properties = MLT_PLAYLIST_PROPERTIES( playlist );
- if ( !strcmp( argv[ i ], "-null-track" ) || !strcmp( argv[ i ], "-hide-track" ) )
- mlt_properties_set_int( properties, "hide", 3 );
- else if ( !strcmp( argv[ i ], "-audio-track" ) || !strcmp( argv[ i ], "-hide-video" ) )
- mlt_properties_set_int( properties, "hide", 1 );
- else if ( !strcmp( argv[ i ], "-video-track" ) || !strcmp( argv[ i ], "-hide-audio" ) )
- mlt_properties_set_int( properties, "hide", 2 );
- }
- }
- else if ( strchr( argv[ i ], '=' ) && strstr( argv[ i ], "<?xml" ) != argv[ i ] )
- {
- mlt_properties_parse( properties, argv[ i ] );
- }
- else if ( argv[ i ][ 0 ] != '-' )
- {
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
- if ( title == NULL && strstr( argv[ i ], "<?xml" ) != argv[ i ] )
- title = argv[ i ];
- producer = create_producer( profile, field, argv[ i ] );
- if ( producer != NULL )
- {
- properties = MLT_PRODUCER_PROPERTIES( producer );
- mlt_properties_inherit( properties, group );
- }
- else
- {
- fprintf( stderr, "Failed to load \"%s\"\n", argv[ i ] );
- }
- }
- else
- {
- int backtrack = 0;
- if ( !strcmp( argv[ i ], "-serialise" ) ||
- !strcmp( argv[ i ], "-consumer" ) ||
- !strcmp( argv[ i ], "-profile" ) )
- {
- i += 2;
- backtrack = 1;
- }
-
- while ( argv[ i ] != NULL && strchr( argv[ i ], '=' ) )
- {
- i ++;
- backtrack = 1;
- }
- if ( backtrack )
- i --;
- }
- }
-
- // Connect last producer to playlist
- if ( producer != NULL && !mlt_producer_is_cut( producer ) )
- mlt_playlist_append( playlist, producer );
-
- // Track the last playlist too
- track_service( field, playlist, ( mlt_destructor )mlt_playlist_close );
-
- // We must have a playlist to connect
- if ( !mlt_properties_get_int( MLT_PLAYLIST_PROPERTIES( playlist ), "_inigo_first" ) ||
- mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( playlist ) ) > 0 )
- mlt_multitrack_connect( multitrack, MLT_PLAYLIST_PRODUCER( playlist ), track );
-
- mlt_producer prod = MLT_TRACTOR_PRODUCER( tractor );
- mlt_producer_optimise( prod );
- mlt_properties props = MLT_TRACTOR_PROPERTIES( tractor );
- mlt_properties_set_data( props, "group", group, 0, ( mlt_destructor )mlt_properties_close, NULL );
- mlt_properties_set_position( props, "length", mlt_producer_get_out( MLT_MULTITRACK_PRODUCER( multitrack ) ) + 1 );
- mlt_producer_set_in_and_out( prod, 0, mlt_producer_get_out( MLT_MULTITRACK_PRODUCER( multitrack ) ) );
- if ( title != NULL )
- mlt_properties_set( props, "title", strchr( title, '/' ) ? strrchr( title, '/' ) + 1 : title );
-
- return prod;
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltjackrack$(LIBSUF)
-
-OBJS = factory.o \
- jack_rack.o \
- lock_free_fifo.o \
- plugin.o \
- plugin_desc.o \
- plugin_mgr.o \
- plugin_settings.o \
- process.o \
- filter_jackrack.o \
- filter_ladspa.o
-
-CFLAGS += -I../..
-CFLAGS += `pkg-config --cflags jack`
-CFLAGS += `xml2-config --cflags`
-CFLAGS += `pkg-config glib-2.0 --cflags`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `pkg-config --libs jack`
-LDFLAGS += `xml2-config --libs`
-LDFLAGS += `pkg-config glib-2.0 --libs`
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- pkg-config jack
- disable_jack=$?
-
- which xml2-config > /dev/null 2>&1
- disable_xml2=$?
-
- disable_ladspa=1
- ladspa_prefix=`which listplugins 2> /dev/null`
- if [ "$ladspa_prefix" != "" ]
- then
- ladspa_prefix=`dirname "$ladspa_prefix"`
- disable_ladspa=`[ -f "$ladspa_prefix/include/ladspa.h" ] && echo 1 || echo 0`
- fi
-
- if [ "$disable_jack" = "1" -o "$disable_xml2" = "1" -o "$disable_ladspa" = "1" ]
- then
- [ "$disable_jack" = "1" ] && echo "- jackrack not found: disabling"
- [ "$disable_xml2" = "1" ] && echo "- xml2 not found: disabling jackrack"
- [ "$disable_ladspa" = "1" ] && echo "- ladspa not found; disabling"
- touch ../disable-jackrack
- fi
- exit 0
-fi
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_jackrack_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_ladspa_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "jackrack", filter_jackrack_init );
- MLT_REGISTER( filter_type, "ladspa", filter_ladspa_init );
-}
+++ /dev/null
-/*
- * filter_jackrack.c -- filter audio through Jack and/or LADSPA plugins
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <jack/jack.h>
-#include <jack/ringbuffer.h>
-#include <pthread.h>
-#include <string.h>
-
-#include "jack_rack.h"
-
-#define BUFFER_LEN 204800 * 3
-
-static void initialise_jack_ports( mlt_properties properties )
-{
- int i;
- char mlt_name[20], rack_name[30];
- jack_port_t **port = NULL;
- jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
- jack_nframes_t jack_buffer_size = jack_get_buffer_size( jack_client );
-
- // Propogate these for the Jack processing callback
- int channels = mlt_properties_get_int( properties, "channels" );
-
- // Start JackRack
- if ( mlt_properties_get( properties, "src" ) )
- {
- snprintf( rack_name, sizeof( rack_name ), "jackrack%d", getpid() );
- jack_rack_t *jackrack = jack_rack_new( rack_name, mlt_properties_get_int( properties, "channels" ) );
- jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );
-
- mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
- mlt_properties_set( properties, "_rack_client_name", rack_name );
- }
-
- // Allocate buffers and ports
- jack_ringbuffer_t **output_buffers = mlt_pool_alloc( sizeof( jack_ringbuffer_t *) * channels );
- jack_ringbuffer_t **input_buffers = mlt_pool_alloc( sizeof( jack_ringbuffer_t *) * channels );
- jack_port_t **jack_output_ports = mlt_pool_alloc( sizeof(jack_port_t *) * channels );
- jack_port_t **jack_input_ports = mlt_pool_alloc( sizeof(jack_port_t *) * channels );
- float **jack_output_buffers = mlt_pool_alloc( sizeof(float *) * jack_buffer_size );
- float **jack_input_buffers = mlt_pool_alloc( sizeof(float *) * jack_buffer_size );
-
- // Set properties - released inside filter_close
- mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_output_ports", jack_output_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_input_ports", jack_input_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_output_buffers", jack_output_buffers, sizeof( float *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers, sizeof( float *) * channels, NULL, NULL );
-
- // Start Jack processing - required before registering ports
- jack_activate( jack_client );
-
- // Register Jack ports
- for ( i = 0; i < channels; i++ )
- {
- int in;
-
- output_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
- input_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
-
- for ( in = 0; in < 2; in++ )
- {
- snprintf( mlt_name, sizeof( mlt_name ), "%s_%d", in ? "in" : "out", i + 1);
- port = ( in ? &jack_input_ports[i] : &jack_output_ports[i] );
-
- *port = jack_port_register( jack_client, mlt_name, JACK_DEFAULT_AUDIO_TYPE,
- ( in ? JackPortIsInput : JackPortIsOutput ) | JackPortIsTerminal, 0 );
- }
- }
-
- // Establish connections
- for ( i = 0; i < channels; i++ )
- {
- int in;
- for ( in = 0; in < 2; in++ )
- {
- port = ( in ? &jack_input_ports[i] : &jack_output_ports[i] );
- snprintf( mlt_name, sizeof( mlt_name ), "%s", jack_port_name( *port ) );
-
- snprintf( rack_name, sizeof( rack_name ), "%s_%d", in ? "in" : "out", i + 1 );
- if ( mlt_properties_get( properties, "_rack_client_name" ) )
- snprintf( rack_name, sizeof( rack_name ), "%s:%s_%d", mlt_properties_get( properties, "_rack_client_name" ), in ? "out" : "in", i + 1);
- else if ( mlt_properties_get( properties, rack_name ) )
- snprintf( rack_name, sizeof( rack_name ), "%s", mlt_properties_get( properties, rack_name ) );
- else
- snprintf( rack_name, sizeof( rack_name ), "%s:%s_%d", mlt_properties_get( properties, "_client_name" ), in ? "out" : "in", i + 1);
-
- if ( in )
- {
- fprintf( stderr, "jack connect %s to %s\n", rack_name, mlt_name );
- jack_connect( jack_client, rack_name, mlt_name );
- }
- else
- {
- fprintf( stderr, "jack connect %s to %s\n", mlt_name, rack_name );
- jack_connect( jack_client, mlt_name, rack_name );
- }
- }
- }
-}
-
-static int jack_process (jack_nframes_t frames, void * data)
-{
- mlt_filter filter = (mlt_filter) data;
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
- int channels = mlt_properties_get_int( properties, "channels" );
- int frame_size = mlt_properties_get_int( properties, "_samples" ) * sizeof(float);
- int sync = mlt_properties_get_int( properties, "_sync" );
- int err = 0;
- int i;
- static int total_size = 0;
-
- jack_ringbuffer_t **output_buffers = mlt_properties_get_data( properties, "output_buffers", NULL );
- if ( output_buffers == NULL )
- return 0;
- jack_ringbuffer_t **input_buffers = mlt_properties_get_data( properties, "input_buffers", NULL );
- jack_port_t **jack_output_ports = mlt_properties_get_data( properties, "jack_output_ports", NULL );
- jack_port_t **jack_input_ports = mlt_properties_get_data( properties, "jack_input_ports", NULL );
- float **jack_output_buffers = mlt_properties_get_data( properties, "jack_output_buffers", NULL );
- float **jack_input_buffers = mlt_properties_get_data( properties, "jack_input_buffers", NULL );
- pthread_mutex_t *output_lock = mlt_properties_get_data( properties, "output_lock", NULL );
- pthread_cond_t *output_ready = mlt_properties_get_data( properties, "output_ready", NULL );
-
- for ( i = 0; i < channels; i++ )
- {
- size_t jack_size = ( frames * sizeof(float) );
- size_t ring_size;
-
- // Send audio through out port
- jack_output_buffers[i] = jack_port_get_buffer( jack_output_ports[i], frames );
- if ( ! jack_output_buffers[i] )
- {
- fprintf( stderr, "%s: no jack buffer for output port %d\n", __FUNCTION__, i );
- err = 1;
- break;
- }
- ring_size = jack_ringbuffer_read_space( output_buffers[i] );
- jack_ringbuffer_read( output_buffers[i], ( char * )jack_output_buffers[i], ring_size < jack_size ? ring_size : jack_size );
-
- // Return audio through in port
- jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
- if ( ! jack_input_buffers[i] )
- {
- fprintf( stderr, "%s: no jack buffer for input port %d\n", __FUNCTION__, i );
- err = 1;
- break;
- }
-
- // Do not start returning audio until we have sent first mlt frame
- if ( sync && i == 0 && frame_size > 0 )
- total_size += ring_size;
- //fprintf(stderr, "sync %d frame_size %d ring_size %d jack_size %d\n", sync, frame_size, ring_size, jack_size );
-
- if ( ! sync || ( frame_size > 0 && total_size >= frame_size ) )
- {
- ring_size = jack_ringbuffer_write_space( input_buffers[i] );
- jack_ringbuffer_write( input_buffers[i], ( char * )jack_input_buffers[i], ring_size < jack_size ? ring_size : jack_size );
-
- if ( sync )
- {
- // Tell mlt that audio is available
- pthread_mutex_lock( output_lock);
- pthread_cond_signal( output_ready );
- pthread_mutex_unlock( output_lock);
-
- // Clear sync phase
- mlt_properties_set_int( properties, "_sync", 0 );
- }
- }
- }
-
- return err;
-}
-
-
-/** Get the audio.
-*/
-
-static int jackrack_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_audio( frame );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- int jack_frequency = mlt_properties_get_int( filter_properties, "_sample_rate" );
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, &jack_frequency, channels, samples );
-
- // TODO: Deal with sample rate differences
- if ( *frequency != jack_frequency )
- fprintf( stderr, "mismatching frequencies in filter jackrack\n" );
- *frequency = jack_frequency;
-
- // Initialise Jack ports and connections if needed
- if ( mlt_properties_get_int( filter_properties, "_samples" ) == 0 )
- mlt_properties_set_int( filter_properties, "_samples", *samples );
-
- // Get the filter-specific properties
- jack_ringbuffer_t **output_buffers = mlt_properties_get_data( filter_properties, "output_buffers", NULL );
- jack_ringbuffer_t **input_buffers = mlt_properties_get_data( filter_properties, "input_buffers", NULL );
-// pthread_mutex_t *output_lock = mlt_properties_get_data( filter_properties, "output_lock", NULL );
-// pthread_cond_t *output_ready = mlt_properties_get_data( filter_properties, "output_ready", NULL );
-
- // Process the audio
- int16_t *q = *buffer;
- float sample[ 2 ][ 10000 ];
- int i, j;
-// struct timespec tm = { 0, 0 };
-
- // Convert to floats and write into output ringbuffer
- if ( jack_ringbuffer_write_space( output_buffers[0] ) >= ( *samples * sizeof(float) ) )
- {
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- sample[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
- for ( j = 0; j < *channels; j++ )
- jack_ringbuffer_write( output_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
- }
-
- // Synchronization phase - wait for signal from Jack process
- while ( jack_ringbuffer_read_space( input_buffers[ *channels - 1 ] ) < ( *samples * sizeof(float) ) ) ;
- //pthread_cond_wait( output_ready, output_lock );
-
- // Read from input ringbuffer and convert from floats
- if ( jack_ringbuffer_read_space( input_buffers[0] ) >= ( *samples * sizeof(float) ) )
- {
- // Initialise to silence, but repeat last frame if available in case of
- // buffer underrun
- for ( j = 0; j < *channels; j++ )
- jack_ringbuffer_read( input_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
-
- q = *buffer;
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- {
- if ( sample[ j ][ i ] > 1.0 )
- sample[ j ][ i ] = 1.0;
- else if ( sample[ j ][ i ] < -1.0 )
- sample[ j ][ i ] = -1.0;
-
- if ( sample[ j ][ i ] > 0 )
- *q ++ = 32767 * sample[ j ][ i ];
- else
- *q ++ = 32768 * sample[ j ][ i ];
- }
- }
-
- return 0;
-}
-
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- mlt_frame_push_audio( frame, this );
- mlt_frame_push_audio( frame, jackrack_get_audio );
-
- if ( mlt_properties_get_int( properties, "_sync" ) )
- initialise_jack_ports( properties );
- }
-
- return frame;
-}
-
-
-static void filter_close( mlt_filter this )
-{
- int i;
- char mlt_name[20];
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
-
- jack_deactivate( jack_client );
- jack_client_close( jack_client );
- for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
- {
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
- }
- mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_output_ports", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_input_ports", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_input_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "output_lock", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "output_ready", NULL ) );
-
- jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
- jack_rack_destroy( jackrack );
-
- this->parent.close = NULL;
- mlt_service_close( &this->parent );
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_jackrack_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- char name[14];
-
- snprintf( name, sizeof( name ), "mlt%d", getpid() );
- jack_client_t *jack_client = jack_client_new( name );
- if ( jack_client )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- pthread_mutex_t *output_lock = mlt_pool_alloc( sizeof( pthread_mutex_t ) );
- pthread_cond_t *output_ready = mlt_pool_alloc( sizeof( pthread_cond_t ) );
-
- jack_set_process_callback( jack_client, jack_process, this );
- //TODO: jack_on_shutdown( jack_client, jack_shutdown_cb, this );
- this->process = filter_process;
- this->close = filter_close;
- pthread_mutex_init( output_lock, NULL );
- pthread_cond_init( output_ready, NULL );
-
- mlt_properties_set( properties, "src", arg );
- mlt_properties_set( properties, "_client_name", name );
- mlt_properties_set_data( properties, "jack_client", jack_client, 0, NULL, NULL );
- mlt_properties_set_int( properties, "_sample_rate", jack_get_sample_rate( jack_client ) );
- mlt_properties_set_data( properties, "output_lock", output_lock, 0, NULL, NULL );
- mlt_properties_set_data( properties, "output_ready", output_ready, 0, NULL, NULL );
- mlt_properties_set_int( properties, "_sync", 1 );
- mlt_properties_set_int( properties, "channels", 2 );
- }
- }
- return this;
-}
+++ /dev/null
-/*
- * filter_ladspa.c -- filter audio through LADSPA plugins
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <pthread.h>
-#include <string.h>
-
-#include "jack_rack.h"
-
-#define BUFFER_LEN 10000
-
-static void initialise_jack_rack( mlt_properties properties, int channels )
-{
- int i;
- char mlt_name[20];
-
- // Propogate these for the Jack processing callback
- mlt_properties_set_int( properties, "channels", channels );
-
- // Start JackRack
- if ( mlt_properties_get( properties, "src" ) )
- {
- // Create JackRack without Jack client name so that it only uses LADSPA
- jack_rack_t *jackrack = jack_rack_new( NULL, channels );
- mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
- jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );
- }
-
- // Allocate buffers
- LADSPA_Data **input_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
- LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
-
- // Set properties - released inside filter_close
- mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
-
- // Register Jack ports
- for ( i = 0; i < channels; i++ )
- {
- input_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
-
- output_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
- }
-}
-
-
-/** Get the audio.
-*/
-
-static int ladspa_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_audio( frame );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
-
- // Initialise LADSPA if needed
- jack_rack_t *jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
- if ( jackrack == NULL )
- {
- sample_rate = *frequency;
- initialise_jack_rack( filter_properties, *channels );
- jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
- }
-
- // Get the filter-specific properties
- LADSPA_Data **input_buffers = mlt_properties_get_data( filter_properties, "input_buffers", NULL );
- LADSPA_Data **output_buffers = mlt_properties_get_data( filter_properties, "output_buffers", NULL );
-
- // Process the audio
- int16_t *q = *buffer;
- int i, j;
-
- // Convert to floats and write into output ringbuffer
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- input_buffers[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
- // Do LADSPA processing
- if ( jackrack && process_ladspa( jackrack->procinfo, *samples, input_buffers, output_buffers) == 0 )
- {
- // Read from output buffer and convert from floats
- q = *buffer;
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- {
- if ( output_buffers[ j ][ i ] > 1.0 )
- output_buffers[ j ][ i ] = 1.0;
- else if ( output_buffers[ j ][ i ] < -1.0 )
- output_buffers[ j ][ i ] = -1.0;
-
- if ( output_buffers[ j ][ i ] > 0 )
- *q ++ = 32767 * output_buffers[ j ][ i ];
- else
- *q ++ = 32768 * output_buffers[ j ][ i ];
- }
- }
-
- return 0;
-}
-
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- {
- mlt_frame_push_audio( frame, this );
- mlt_frame_push_audio( frame, ladspa_get_audio );
- }
-
- return frame;
-}
-
-
-static void filter_close( mlt_filter this )
-{
- int i;
- char mlt_name[20];
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- if ( mlt_properties_get_data( properties, "jackrack", NULL ) != NULL )
- {
- for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
- {
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
- }
- mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
-
- jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
- jack_rack_destroy( jackrack );
- }
- this->parent.close = NULL;
- mlt_service_close( &this->parent );
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_ladspa_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- this->process = filter_process;
- this->close = filter_close;
-
- mlt_properties_set( properties, "src", arg );
- }
- return this;
-}
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <ladspa.h>
-#include <libxml/tree.h>
-
-#include "jack_rack.h"
-#include "lock_free_fifo.h"
-#include "plugin_settings.h"
-
-#ifndef _
-#define _(x) x
-#endif
-#define _x (const xmlChar*)
-#define _s (const char*)
-
-jack_rack_t *
-jack_rack_new (const char * client_name, unsigned long channels)
-{
- jack_rack_t *rack;
-
- rack = g_malloc (sizeof (jack_rack_t));
- rack->saved_plugins = NULL;
- rack->channels = channels;
- rack->procinfo = process_info_new (client_name, channels, FALSE, FALSE);
- if (!rack->procinfo) {
- g_free (rack);
- return NULL;
- }
- rack->plugin_mgr = plugin_mgr_new ();
- plugin_mgr_set_plugins (rack->plugin_mgr, channels);
-
- return rack;
-}
-
-
-void
-jack_rack_destroy (jack_rack_t * jack_rack)
-{
- process_quit (jack_rack->procinfo);
- plugin_mgr_destroy (jack_rack->plugin_mgr);
- process_info_destroy (jack_rack->procinfo);
- g_slist_free (jack_rack->saved_plugins);
- g_free (jack_rack);
-}
-
-plugin_t *
-jack_rack_instantiate_plugin (jack_rack_t * jack_rack, plugin_desc_t * desc)
-{
- plugin_t * plugin;
-
- /* check whether or not the plugin is RT capable and confirm with the user if it isn't */
- if (!LADSPA_IS_HARD_RT_CAPABLE(desc->properties)) {
- fprintf (stderr, "Plugin not RT capable. The plugin '%s' does not describe itself as being capable of real-time operation. You may experience drop outs or jack may even kick us out if you use it.\n",
- desc->name);
- }
-
- /* create the plugin */
- plugin = plugin_new (desc, jack_rack);
-
- if (!plugin) {
- fprintf (stderr, "Error loading file plugin '%s' from file '%s'\n",
- desc->name, desc->object_file);
- }
-
- return plugin;
-}
-
-
-void
-jack_rack_add_saved_plugin (jack_rack_t * jack_rack, saved_plugin_t * saved_plugin)
-{
- plugin_t * plugin = jack_rack_instantiate_plugin (jack_rack, saved_plugin->settings->desc);
- if (!plugin)
- return;
- jack_rack->saved_plugins = g_slist_append (jack_rack->saved_plugins, saved_plugin);
- process_add_plugin (jack_rack->procinfo, plugin);
- jack_rack_add_plugin (jack_rack, plugin);
-}
-
-
-void
-jack_rack_add_plugin (jack_rack_t * jack_rack, plugin_t * plugin)
-{
- saved_plugin_t * saved_plugin = NULL;
- GSList * list;
- unsigned long control, channel;
- LADSPA_Data value;
- guint copy;
-
- /* see if there's any saved settings that match the plugin id */
- for (list = jack_rack->saved_plugins; list; list = g_slist_next (list))
- {
- saved_plugin = list->data;
-
- if (saved_plugin->settings->desc->id == plugin->desc->id)
- {
- /* process the settings! */
- jack_rack->saved_plugins = g_slist_remove (jack_rack->saved_plugins, saved_plugin);
- break;
- }
- saved_plugin = NULL;
- }
-
- /* initialize plugin parameters */
- plugin->enabled = settings_get_enabled (saved_plugin->settings);
- plugin->wet_dry_enabled = settings_get_wet_dry_enabled (saved_plugin->settings);
-
- for (control = 0; control < saved_plugin->settings->desc->control_port_count; control++)
- for (copy = 0; copy < plugin->copies; copy++)
- {
- value = settings_get_control_value (saved_plugin->settings, copy, control);
- plugin->holders[copy].control_memory[control] = value;
-//printf("setting control value %s (%d) = %f\n", saved_plugin->settings->desc->port_names[control], copy, value);
-// lff_write (plugin->holders[copy].ui_control_fifos + control, &value);
- }
- if (plugin->wet_dry_enabled)
- for (channel = 0; channel < jack_rack->channels; channel++)
- {
- value = settings_get_wet_dry_value (saved_plugin->settings, channel);
- plugin->wet_dry_values[channel] = value;
-//printf("setting wet/dry value %d = %f\n", channel, value);
-// lff_write (plugin->wet_dry_fifos + channel, &value);
- }
-}
-
-
-static void
-saved_rack_parse_plugin (jack_rack_t * jack_rack, saved_rack_t * saved_rack, saved_plugin_t * saved_plugin,
- const char * filename, xmlNodePtr plugin)
-{
- plugin_desc_t * desc;
- settings_t * settings = NULL;
- xmlNodePtr node;
- xmlNodePtr sub_node;
- xmlChar *content;
- unsigned long num;
- unsigned long control = 0;
-
- for (node = plugin->children; node; node = node->next)
- {
- if (xmlStrcmp (node->name, _x("id")) == 0)
- {
- content = xmlNodeGetContent (node);
- num = strtoul (_s(content), NULL, 10);
- xmlFree (content);
-
- desc = plugin_mgr_get_any_desc (jack_rack->plugin_mgr, num);
- if (!desc)
- {
- fprintf (stderr, _("The file '%s' contains an unknown plugin with ID '%ld'; skipping\n"), filename, num);
- return;
- }
-
- settings = settings_new (desc, saved_rack->channels, saved_rack->sample_rate);
- }
- else if (xmlStrcmp (node->name, _x("enabled")) == 0)
- {
- content = xmlNodeGetContent (node);
- settings_set_enabled (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("wet_dry_enabled")) == 0)
- {
- content = xmlNodeGetContent (node);
- settings_set_wet_dry_enabled (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("wet_dry_locked")) == 0)
- {
- content = xmlNodeGetContent (node);
- settings_set_wet_dry_locked (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("wet_dry_values")) == 0)
- {
- unsigned long channel = 0;
-
- for (sub_node = node->children; sub_node; sub_node = sub_node->next)
- {
- if (xmlStrcmp (sub_node->name, _x("value")) == 0)
- {
- content = xmlNodeGetContent (sub_node);
- settings_set_wet_dry_value (settings, channel, strtod (_s(content), NULL));
- xmlFree (content);
-
- channel++;
- }
- }
- }
- else if (xmlStrcmp (node->name, _x("lockall")) == 0)
- {
- content = xmlNodeGetContent (node);
- settings_set_lock_all (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("controlrow")) == 0)
- {
- gint copy = 0;
-
- for (sub_node = node->children; sub_node; sub_node = sub_node->next)
- {
- if (xmlStrcmp (sub_node->name, _x("lock")) == 0)
- {
- content = xmlNodeGetContent (sub_node);
- settings_set_lock (settings, control, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
- xmlFree (content);
- }
- else if (xmlStrcmp (sub_node->name, _x("value")) == 0)
- {
- content = xmlNodeGetContent (sub_node);
- settings_set_control_value (settings, copy, control, strtod (_s(content), NULL));
- xmlFree (content);
- copy++;
- }
- }
-
- control++;
- }
- }
-
- if (settings)
- saved_plugin->settings = settings;
-}
-
-static void
-saved_rack_parse_jackrack (jack_rack_t * jack_rack, saved_rack_t * saved_rack, const char * filename, xmlNodePtr jackrack)
-{
- xmlNodePtr node;
- xmlChar *content;
- saved_plugin_t * saved_plugin;
-
- for (node = jackrack->children; node; node = node->next)
- {
- if (xmlStrcmp (node->name, _x("channels")) == 0)
- {
- content = xmlNodeGetContent (node);
- saved_rack->channels = strtoul (_s(content), NULL, 10);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("samplerate")) == 0)
- {
- content = xmlNodeGetContent (node);
- saved_rack->sample_rate = strtoul (_s(content), NULL, 10);
- xmlFree (content);
- }
- else if (xmlStrcmp (node->name, _x("plugin")) == 0)
- {
- saved_plugin = g_malloc0 (sizeof (saved_plugin_t));
- saved_rack->plugins = g_slist_append (saved_rack->plugins, saved_plugin);
- saved_rack_parse_plugin (jack_rack, saved_rack, saved_plugin, filename, node);
- }
- }
-}
-
-static saved_rack_t *
-saved_rack_new (jack_rack_t * jack_rack, const char * filename, xmlDocPtr doc)
-{
- xmlNodePtr node;
- saved_rack_t *saved_rack;
-
- /* create the saved rack */
- saved_rack = g_malloc (sizeof (saved_rack_t));
- saved_rack->plugins = NULL;
- saved_rack->sample_rate = 48000;
- saved_rack->channels = 2;
-
- for (node = doc->children; node; node = node->next)
- {
- if (xmlStrcmp (node->name, _x("jackrack")) == 0)
- saved_rack_parse_jackrack (jack_rack, saved_rack, filename, node);
- }
-
- return saved_rack;
-}
-
-static void
-saved_rack_destroy (saved_rack_t * saved_rack)
-{
- GSList * list;
-
- for (list = saved_rack->plugins; list; list = g_slist_next (list))
- settings_destroy (((saved_plugin_t *) list->data)->settings);
- g_slist_free (saved_rack->plugins);
- g_free (saved_rack);
-}
-
-
-int
-jack_rack_open_file (jack_rack_t * jack_rack, const char * filename)
-{
- xmlDocPtr doc;
- saved_rack_t * saved_rack;
- GSList * list;
- saved_plugin_t * saved_plugin;
-
- doc = xmlParseFile (filename);
- if (!doc)
- {
- fprintf (stderr, _("Could not parse file '%s'\n"), filename);
- return 1;
- }
-
- if (xmlStrcmp ( ((xmlDtdPtr)doc->children)->name, _x("jackrack")) != 0)
- {
- fprintf (stderr, _("The file '%s' is not a JACK Rack settings file\n"), filename);
- return 1;
- }
-
- saved_rack = saved_rack_new (jack_rack, filename, doc);
- xmlFreeDoc (doc);
-
- if (!saved_rack)
- return 1;
-
- for (list = saved_rack->plugins; list; list = g_slist_next (list))
- {
- saved_plugin = list->data;
-
- settings_set_sample_rate (saved_plugin->settings, sample_rate);
-
- jack_rack_add_saved_plugin (jack_rack, saved_plugin);
- }
-
- saved_rack_destroy (saved_rack);
-
- return 0;
-}
-
-
-/* EOF */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JR_JACK_RACK_H__
-#define __JR_JACK_RACK_H__
-
-#include <glib.h>
-#include <ladspa.h>
-
-#include "plugin.h"
-#include "plugin_mgr.h"
-#include "plugin_settings.h"
-#include "process.h"
-
-typedef struct _saved_plugin saved_plugin_t;
-
-struct _saved_plugin
-{
- settings_t *settings;
-};
-
-typedef struct _saved_rack saved_rack_t;
-
-struct _saved_rack
-{
- unsigned long channels;
- jack_nframes_t sample_rate;
- GSList * plugins;
-};
-
-typedef struct _jack_rack jack_rack_t;
-
-struct _jack_rack
-{
- plugin_mgr_t * plugin_mgr;
- process_info_t * procinfo;
- unsigned long channels;
- GSList * saved_plugins;
-};
-
-jack_rack_t * jack_rack_new (const char * client_name, unsigned long channels);
-void jack_rack_destroy (jack_rack_t * jack_rack);
-
-int jack_rack_open_file (jack_rack_t * jack_rack, const char * filename);
-void jack_rack_add_plugin (jack_rack_t * jack_rack, plugin_t * plugin);
-void jack_rack_add_saved_plugin (jack_rack_t * jack_rack, struct _saved_plugin * saved_plugin);
-
-plugin_t * jack_rack_instantiate_plugin (jack_rack_t * jack_rack, plugin_desc_t * desc);
-
-#endif /* __JR_JACK_RACK_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "lock_free_fifo.h"
-
-/** initialise a lock free fifo */
-
-void
-lff_init (lff_t * lff, unsigned int size, size_t object_size)
-{
- lff->size = size;
- lff->object_size = object_size;
- lff->read_index = 0;
- lff->write_index = 0;
- lff->data = g_malloc (object_size * size);
-}
-
-lff_t *
-lff_new (unsigned int size, size_t object_size)
-{
- lff_t * lff;
-
- lff = g_malloc (sizeof (lff_t));
-
- lff_init (lff, size, object_size);
-
- return lff;
-}
-
-void
-lff_free (lff_t * lff)
-{
- g_free (lff->data);
-}
-
-void
-lff_destroy (lff_t * lff)
-{
- lff_free (lff);
- g_free (lff);
-}
-
-/** read an element from the fifo into data.
-returns 0 on success, non-zero if there were no elements to read */
-int lff_read (lff_t * lff, void * data) {
- if (lff->read_index == lff->write_index) {
- return -1;
- } else {
- memcpy (data, ((char *)lff->data) + (lff->read_index * lff->object_size),
- lff->object_size);
- lff->read_index++;
- if (lff->read_index >= lff->size) {
- lff->read_index = 0;
- }
- return 0;
- }
-}
-
-/** write an element from data to the fifo.
-returns 0 on success, non-zero if there was no space */
-int lff_write (lff_t * lff, void * data) {
- static unsigned int ri;
-
- /* got to read read_index only once for safety */
- ri = lff->read_index;
-
- /* lots of logic for when we're allowed to write to the fifo which basically
- boils down to "don't write if we're one element behind the read index" */
- if ((ri > lff->write_index && ri - lff->write_index > 1) ||
- (lff->write_index >= ri && lff->write_index != lff->size - 1) ||
- (lff->write_index >= ri && lff->write_index == lff->size - 1 && ri != 0)) {
-
-/* if ((ri > lff->write_index && ri - lff->write_index > 1) ||
- (lff->write_index >= ri && (lff->write_index != lff->size - 1 || ri != 0))) { */
-
- memcpy (((char *)lff->data) + (lff->write_index * lff->object_size),
- data, lff->object_size);
-
- /* FIXME: is this safe? */
- lff->write_index++;
- if (lff->write_index >= lff->size) {
- lff->write_index = 0;
- }
-
- return 0;
- } else {
- return -1;
- }
-}
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JLH_LOCK_FREE_FIFO_H__
-#define __JLH_LOCK_FREE_FIFO_H__
-
-/** lock free fifo ring buffer structure */
-typedef struct lock_free_fifo {
- /** Size of the ringbuffer (in elements) */
- unsigned int size;
- /** the memory containing the ringbuffer */
- void * data;
- /** the size of an element */
- size_t object_size;
- /** the current position of the reader */
- unsigned int read_index;
- /** the current position of the writer */
- unsigned int write_index;
-} lff_t;
-
-void lff_init (lff_t * lff, unsigned int size, size_t object_size);
-void lff_free (lff_t * lff);
-
-lff_t * lff_new (unsigned int size, size_t object_size);
-void lff_destroy (lff_t * lock_free_fifo);
-
-int lff_read (lff_t * lock_free_fifo, void * data);
-int lff_write (lff_t * lock_free_fifo, void * data);
-
-
-#endif /* __JLH_LOCK_FREE_FIFO_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ladspa.h>
-#include <dlfcn.h>
-#include <ctype.h>
-
-#include <glib.h>
-
-#include "plugin.h"
-#include "jack_rack.h"
-#include "process.h"
-
-#define CONTROL_FIFO_SIZE 128
-
-
-
-/* swap over the jack ports in two plugins */
-static void
-plugin_swap_aux_ports (plugin_t * plugin, plugin_t * other)
-{
- guint copy;
- jack_port_t ** aux_ports_tmp;
-
- for (copy = 0; copy < plugin->copies; copy++)
- {
- aux_ports_tmp = other->holders[copy].aux_ports;
- other->holders[copy].aux_ports = plugin->holders[copy].aux_ports;
- plugin->holders[copy].aux_ports = aux_ports_tmp;
- }
-}
-
-/** connect up the ladspa instance's input buffers to the previous
- plugin's audio memory. make sure to check that plugin->prev
- exists. */
-void
-plugin_connect_input_ports (plugin_t * plugin, LADSPA_Data ** inputs)
-{
- gint copy;
- unsigned long channel;
- unsigned long rack_channel;
-
- if (!plugin || !inputs)
- return;
-
- rack_channel = 0;
- for (copy = 0; copy < plugin->copies; copy++)
- {
- for (channel = 0; channel < plugin->desc->channels; channel++)
- {
- plugin->descriptor->
- connect_port (plugin->holders[copy].instance,
- plugin->desc->audio_input_port_indicies[channel],
- inputs[rack_channel]);
- rack_channel++;
- }
- }
-
- plugin->audio_input_memory = inputs;
-}
-
-/** connect up a plugin's output ports to its own audio_output_memory output memory */
-void
-plugin_connect_output_ports (plugin_t * plugin)
-{
- gint copy;
- unsigned long channel;
- unsigned long rack_channel = 0;
-
- if (!plugin)
- return;
-
-
- for (copy = 0; copy < plugin->copies; copy++)
- {
- for (channel = 0; channel < plugin->desc->channels; channel++)
- {
- plugin->descriptor->
- connect_port (plugin->holders[copy].instance,
- plugin->desc->audio_output_port_indicies[channel],
- plugin->audio_output_memory[rack_channel]);
- rack_channel++;
- }
- }
-}
-
-void
-process_add_plugin (process_info_t * procinfo, plugin_t * plugin)
-{
-
- /* sort out list pointers */
- plugin->next = NULL;
- plugin->prev = procinfo->chain_end;
-
- if (procinfo->chain_end)
- procinfo->chain_end->next = plugin;
- else
- procinfo->chain = plugin;
-
- procinfo->chain_end = plugin;
-
-}
-
-
-/** remove a plugin from the chain */
-plugin_t *
-process_remove_plugin (process_info_t * procinfo, plugin_t *plugin)
-{
- /* sort out chain pointers */
- if (plugin->prev)
- plugin->prev->next = plugin->next;
- else
- procinfo->chain = plugin->next;
-
- if (plugin->next)
- plugin->next->prev = plugin->prev;
- else
- procinfo->chain_end = plugin->prev;
-
- /* sort out the aux ports */
- if (procinfo->jack_client && plugin->desc->aux_channels > 0)
- {
- plugin_t * other;
-
- for (other = plugin->next; other; other = other->next)
- if (other->desc->id == plugin->desc->id)
- plugin_swap_aux_ports (plugin, other);
- }
-
- return plugin;
-}
-
-/** enable/disable a plugin */
-void
-process_ablise_plugin (process_info_t * procinfo, plugin_t *plugin, gboolean enable)
-{
- plugin->enabled = enable;
-}
-
-/** enable/disable a plugin */
-void
-process_ablise_plugin_wet_dry (process_info_t * procinfo, plugin_t *plugin, gboolean enable)
-{
- plugin->wet_dry_enabled = enable;
-}
-
-/** move a plugin up or down one place in the chain */
-void
-process_move_plugin (process_info_t * procinfo, plugin_t *plugin, gint up)
-{
- /* other plugins in the chain */
- plugin_t *pp = NULL, *p, *n, *nn = NULL;
-
- /* note that we should never recieve an illogical move request
- ie, there will always be at least 1 plugin before for an up
- request or 1 plugin after for a down request */
-
- /* these are pointers to the plugins surrounding the specified one:
- { pp, p, plugin, n, nn } which makes things much clearer than
- tptr, tptr2 etc */
- p = plugin->prev;
- if (p) pp = p->prev;
- n = plugin->next;
- if (n) nn = n->next;
-
- if (up)
- {
- if (!p)
- return;
-
- if (pp)
- pp->next = plugin;
- else
- procinfo->chain = plugin;
-
- p->next = n;
- p->prev = plugin;
-
- plugin->prev = pp;
- plugin->next = p;
-
- if (n)
- n->prev = p;
- else
- procinfo->chain_end = p;
-
- }
- else
- {
- if (!n)
- return;
-
- if (p)
- p->next = n;
- else
- procinfo->chain = n;
-
- n->prev = p;
- n->next = plugin;
-
- plugin->prev = n;
- plugin->next = nn;
-
- if (nn)
- nn->prev = plugin;
- else
- procinfo->chain_end = plugin;
- }
-
- if (procinfo->jack_client && plugin->desc->aux_channels > 0)
- {
- plugin_t * other;
- other = up ? plugin->next : plugin->prev;
-
- /* swap around the jack ports */
- if (other->desc->id == plugin->desc->id)
- plugin_swap_aux_ports (plugin, other);
- }
-}
-
-/** exchange an existing plugin for a newly created one */
-plugin_t *
-process_change_plugin (process_info_t * procinfo,
- plugin_t *plugin, plugin_t * new_plugin)
-{
- new_plugin->next = plugin->next;
- new_plugin->prev = plugin->prev;
-
- if (plugin->prev)
- plugin->prev->next = new_plugin;
- else
- procinfo->chain = new_plugin;
-
- if (plugin->next)
- plugin->next->prev = new_plugin;
- else
- procinfo->chain_end = new_plugin;
-
- /* sort out the aux ports */
- if (procinfo->jack_client && plugin->desc->aux_channels > 0)
- {
- plugin_t * other;
-
- for (other = plugin->next; other; other = other->next)
- if (other->desc->id == plugin->desc->id)
- plugin_swap_aux_ports (plugin, other);
- }
-
- return plugin;
-}
-
-
-/******************************************
- ************* non RT stuff ***************
- ******************************************/
-
-
-static int
-plugin_open_plugin (plugin_desc_t * desc,
- void ** dl_handle_ptr,
- const LADSPA_Descriptor ** descriptor_ptr)
-{
- void * dl_handle;
- const char * dlerr;
- LADSPA_Descriptor_Function get_descriptor;
-
- /* open the object file */
- dl_handle = dlopen (desc->object_file, RTLD_NOW|RTLD_GLOBAL);
- if (!dl_handle)
- {
- fprintf (stderr, "%s: error opening shared object file '%s': %s\n",
- __FUNCTION__, desc->object_file, dlerror());
- return 1;
- }
-
-
- /* get the get_descriptor function */
- dlerror (); /* clear the error report */
-
- get_descriptor = (LADSPA_Descriptor_Function)
- dlsym (dl_handle, "ladspa_descriptor");
-
- dlerr = dlerror();
- if (dlerr)
- {
- fprintf (stderr, "%s: error finding descriptor symbol in object file '%s': %s\n",
- __FUNCTION__, desc->object_file, dlerr);
- dlclose (dl_handle);
- return 1;
- }
-
- *descriptor_ptr = get_descriptor (desc->index);
- *dl_handle_ptr = dl_handle;
-
- return 0;
-}
-
-static int
-plugin_instantiate (const LADSPA_Descriptor * descriptor,
- unsigned long plugin_index,
- gint copies,
- LADSPA_Handle * instances)
-{
- gint i;
-
- for (i = 0; i < copies; i++)
- {
- instances[i] = descriptor->instantiate (descriptor, sample_rate);
-
- if (!instances[i])
- {
- unsigned long d;
-
- for (d = 0; d < i; d++)
- descriptor->cleanup (instances[d]);
-
- return 1;
- }
- }
-
- return 0;
-}
-
-static void
-plugin_create_aux_ports (plugin_t * plugin, guint copy, jack_rack_t * jack_rack)
-{
- plugin_desc_t * desc;
-// plugin_slot_t * slot;
- unsigned long aux_channel = 1;
- unsigned long plugin_index = 1;
- unsigned long i;
- char port_name[64];
- char * plugin_name;
- char * ptr;
-// GList * list;
- ladspa_holder_t * holder;
-
- desc = plugin->desc;
- holder = plugin->holders + copy;
-
- holder->aux_ports = g_malloc (sizeof (jack_port_t *) * desc->aux_channels);
-
- /* make the plugin name jack worthy */
- ptr = plugin_name = g_strndup (plugin->desc->name, 7);
- while (*ptr != '\0')
- {
- if (*ptr == ' ')
- *ptr = '_';
- else
- *ptr = tolower (*ptr);
-
- ptr++;
- }
-
-/*
- for (list = jack_rack->slots; list; list = g_list_next (list))
- {
- slot = (plugin_slot_t *) list->data;
-
- if (slot->plugin->desc->id == plugin->desc->id)
- plugin_index++;
- }
-*/
-
- for (i = 0; i < desc->aux_channels; i++, aux_channel++)
- {
- sprintf (port_name, "%s_%ld-%d_%c%ld",
- plugin_name,
- plugin_index,
- copy + 1,
- desc->aux_are_input ? 'i' : 'o',
- aux_channel);
-
- holder->aux_ports[i] =
- jack_port_register (jack_rack->procinfo->jack_client,
- port_name,
- JACK_DEFAULT_AUDIO_TYPE,
- desc->aux_are_input ? JackPortIsInput : JackPortIsOutput,
- 0);
-
- if (!holder->aux_ports[i])
- {
- fprintf (stderr, "Could not register jack port '%s'; aborting\n", port_name);
- abort ();
- }
- }
-
- g_free (plugin_name);
-}
-
-static LADSPA_Data unused_control_port_output;
-
-static void
-plugin_init_holder (plugin_t * plugin,
- guint copy,
- LADSPA_Handle instance,
- jack_rack_t * jack_rack)
-{
- unsigned long i;
- plugin_desc_t * desc;
- ladspa_holder_t * holder;
-
- desc = plugin->desc;
- holder = plugin->holders + copy;
-
- holder->instance = instance;
-
- if (desc->control_port_count > 0)
- {
- holder->ui_control_fifos = g_malloc (sizeof (lff_t) * desc->control_port_count);
- holder->control_memory = g_malloc (sizeof (LADSPA_Data) * desc->control_port_count);
- }
- else
- {
- holder->ui_control_fifos = NULL;
- holder->control_memory = NULL;
- }
-
- for (i = 0; i < desc->control_port_count; i++)
- {
- lff_init (holder->ui_control_fifos + i, CONTROL_FIFO_SIZE, sizeof (LADSPA_Data));
- holder->control_memory[i] =
- plugin_desc_get_default_control_value (desc, desc->control_port_indicies[i], sample_rate);
-
- plugin->descriptor->
- connect_port (instance, desc->control_port_indicies[i], holder->control_memory + i);
- }
-
- for (i = 0; i < desc->port_count; i++)
- {
- if (!LADSPA_IS_PORT_CONTROL (desc->port_descriptors[i]))
- continue;
-
- if (LADSPA_IS_PORT_OUTPUT (desc->port_descriptors[i]))
- plugin->descriptor-> connect_port (instance, i, &unused_control_port_output);
- }
-
- if (jack_rack->procinfo->jack_client && plugin->desc->aux_channels > 0)
- plugin_create_aux_ports (plugin, copy, jack_rack);
-
- if (plugin->descriptor->activate)
- plugin->descriptor->activate (instance);
-}
-
-
-plugin_t *
-plugin_new (plugin_desc_t * desc, jack_rack_t * jack_rack)
-{
- void * dl_handle;
- const LADSPA_Descriptor * descriptor;
- LADSPA_Handle * instances;
- gint copies;
- unsigned long i;
- int err;
- plugin_t * plugin;
-
- /* open the plugin */
- err = plugin_open_plugin (desc, &dl_handle, &descriptor);
- if (err)
- return NULL;
-
- /* create the instances */
- copies = plugin_desc_get_copies (desc, jack_rack->channels);
- instances = g_malloc (sizeof (LADSPA_Handle) * copies);
-
- err = plugin_instantiate (descriptor, desc->index, copies, instances);
- if (err)
- {
- g_free (instances);
- dlclose (dl_handle);
- return NULL;
- }
-
-
- plugin = g_malloc (sizeof (plugin_t));
-
- plugin->descriptor = descriptor;
- plugin->dl_handle = dl_handle;
- plugin->desc = desc;
- plugin->copies = copies;
- plugin->enabled = FALSE;
- plugin->next = NULL;
- plugin->prev = NULL;
- plugin->wet_dry_enabled = FALSE;
- plugin->jack_rack = jack_rack;
-
- /* create audio memory and wet/dry stuff */
- plugin->audio_output_memory = g_malloc (sizeof (LADSPA_Data *) * jack_rack->channels);
- plugin->wet_dry_fifos = g_malloc (sizeof (lff_t) * jack_rack->channels);
- plugin->wet_dry_values = g_malloc (sizeof (LADSPA_Data) * jack_rack->channels);
-
- for (i = 0; i < jack_rack->channels; i++)
- {
- plugin->audio_output_memory[i] = g_malloc (sizeof (LADSPA_Data) * buffer_size);
- lff_init (plugin->wet_dry_fifos + i, CONTROL_FIFO_SIZE, sizeof (LADSPA_Data));
- plugin->wet_dry_values[i] = 1.0;
- }
-
- /* create holders and fill them out */
- plugin->holders = g_malloc (sizeof (ladspa_holder_t) * copies);
- for (i = 0; i < copies; i++)
- plugin_init_holder (plugin, i, instances[i], jack_rack);
-
- return plugin;
-}
-
-
-void
-plugin_destroy (plugin_t * plugin)
-{
- unsigned long i, j;
- int err;
-
- /* destroy holders */
- for (i = 0; i < plugin->copies; i++)
- {
- if (plugin->descriptor->deactivate)
- plugin->descriptor->deactivate (plugin->holders[i].instance);
-
-/* if (plugin->descriptor->cleanup)
- plugin->descriptor->cleanup (plugin->holders[i].instance); */
-
- if (plugin->desc->control_port_count > 0)
- {
- for (j = 0; j < plugin->desc->control_port_count; j++)
- {
- lff_free (plugin->holders[i].ui_control_fifos + j);
- }
- g_free (plugin->holders[i].ui_control_fifos);
- g_free (plugin->holders[i].control_memory);
- }
-
- /* aux ports */
- if (plugin->jack_rack->procinfo->jack_client && plugin->desc->aux_channels > 0)
- {
- for (j = 0; j < plugin->desc->aux_channels; j++)
- {
- err = jack_port_unregister (plugin->jack_rack->procinfo->jack_client,
- plugin->holders[i].aux_ports[j]);
-
- if (err)
- fprintf (stderr, "%s: could not unregister jack port\n", __FUNCTION__);
- }
-
- g_free (plugin->holders[i].aux_ports);
- }
- }
-
- g_free (plugin->holders);
-
- for (i = 0; i < plugin->jack_rack->channels; i++)
- {
- g_free (plugin->audio_output_memory[i]);
- lff_free (plugin->wet_dry_fifos + i);
- }
-
- g_free (plugin->audio_output_memory);
- g_free (plugin->wet_dry_fifos);
- g_free (plugin->wet_dry_values);
-
- err = dlclose (plugin->dl_handle);
- if (err)
- {
- fprintf (stderr, "%s: error closing shared object '%s': %s\n",
- __FUNCTION__, plugin->desc->object_file, dlerror ());
- }
-
- g_free (plugin);
-}
-
-
-/* EOF */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JR_PLUGIN_H__
-#define __JR_PLUGIN_H__
-
-#include <glib.h>
-#include <ladspa.h>
-#include <jack/jack.h>
-
-#include "process.h"
-#include "plugin_desc.h"
-
-typedef struct _ladspa_holder ladspa_holder_t;
-typedef struct _plugin plugin_t;
-
-struct _ladspa_holder
-{
- LADSPA_Handle instance;
- lff_t * ui_control_fifos;
- LADSPA_Data * control_memory;
-
- jack_port_t ** aux_ports;
-};
-
-struct _plugin
-{
- plugin_desc_t * desc;
- gint enabled;
-
- gint copies;
- ladspa_holder_t * holders;
- LADSPA_Data ** audio_input_memory;
- LADSPA_Data ** audio_output_memory;
-
- gboolean wet_dry_enabled;
- /* 1.0 = all wet, 0.0 = all dry, 0.5 = 50% wet/50% dry */
- LADSPA_Data * wet_dry_values;
- lff_t * wet_dry_fifos;
-
- plugin_t * next;
- plugin_t * prev;
-
- const LADSPA_Descriptor * descriptor;
- void * dl_handle;
- struct _jack_rack * jack_rack;
-
-};
-
-void process_add_plugin (process_info_t *, plugin_t *plugin);
-plugin_t * process_remove_plugin (process_info_t *, plugin_t *plugin);
-void process_ablise_plugin (process_info_t *, plugin_t *plugin, gboolean able);
-void process_ablise_plugin_wet_dry (process_info_t *, plugin_t *plugin, gboolean enable);
-void process_move_plugin (process_info_t *, plugin_t *plugin, gint up);
-plugin_t * process_change_plugin (process_info_t *, plugin_t *plugin, plugin_t * new_plugin);
-
-struct _jack_rack;
-struct _ui;
-
-plugin_t * plugin_new (plugin_desc_t * plugin_desc, struct _jack_rack * jack_rack);
-void plugin_destroy (plugin_t * plugin);
-
-void plugin_connect_input_ports (plugin_t * plugin, LADSPA_Data ** inputs);
-void plugin_connect_output_ports (plugin_t * plugin);
-
-#endif /* __JR_PLUGIN_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-
-#include "plugin_desc.h"
-#include "plugin.h"
-
-#define set_string_property(property, value) \
- \
- if (property) \
- g_free (property); \
- \
- if (value) \
- (property) = g_strdup (value); \
- else \
- (property) = NULL;
-
-
-void
-plugin_desc_set_ports (plugin_desc_t * pd,
- unsigned long port_count,
- const LADSPA_PortDescriptor * port_descriptors,
- const LADSPA_PortRangeHint * port_range_hints,
- const char * const * port_names);
-
-
-
-static void
-plugin_desc_init (plugin_desc_t * pd)
-{
- pd->object_file = NULL;
- pd->id = 0;
- pd->name = NULL;
- pd->properties = 0;
- pd->channels = 0;
- pd->port_count = 0;
- pd->port_descriptors = NULL;
- pd->port_range_hints = NULL;
- pd->audio_input_port_indicies = NULL;
- pd->audio_output_port_indicies = NULL;
- pd->audio_aux_port_indicies = NULL;
- pd->control_port_count = 0;
- pd->control_port_indicies = NULL;
- pd->aux_channels = 0;
- pd->aux_are_input = TRUE;
-}
-
-static void
-plugin_desc_free_ports (plugin_desc_t * pd)
-{
- if (pd->port_count)
- {
- g_free (pd->port_descriptors);
- g_free (pd->port_range_hints);
- pd->port_descriptors = NULL;
- pd->port_range_hints = NULL;
- pd->port_count = 0;
- }
-}
-
-static void
-plugin_desc_free (plugin_desc_t * pd)
-{
- plugin_desc_set_object_file (pd, NULL);
- plugin_desc_set_name (pd, NULL);
- plugin_desc_free_ports (pd);
-}
-
-plugin_desc_t *
-plugin_desc_new ()
-{
- plugin_desc_t * pd;
- pd = g_malloc (sizeof (plugin_desc_t));
- plugin_desc_init (pd);
- return pd;
-}
-
-plugin_desc_t *
-plugin_desc_new_with_descriptor (const char * object_file,
- unsigned long index,
- const LADSPA_Descriptor * descriptor)
-{
- plugin_desc_t * pd;
- pd = plugin_desc_new ();
-
- plugin_desc_set_object_file (pd, object_file);
- plugin_desc_set_index (pd, index);
- plugin_desc_set_id (pd, descriptor->UniqueID);
- plugin_desc_set_name (pd, descriptor->Name);
- plugin_desc_set_properties (pd, descriptor->Properties);
- plugin_desc_set_ports (pd,
- descriptor->PortCount,
- descriptor->PortDescriptors,
- descriptor->PortRangeHints,
- descriptor->PortNames);
-
- pd->rt = LADSPA_IS_HARD_RT_CAPABLE(pd->properties) ? TRUE : FALSE;
-
- return pd;
-}
-
-void
-plugin_desc_destroy (plugin_desc_t * pd)
-{
- plugin_desc_free (pd);
- g_free (pd);
-}
-
-void
-plugin_desc_set_object_file (plugin_desc_t * pd, const char * object_file)
-{
- set_string_property (pd->object_file, object_file);
-}
-
-void
-plugin_desc_set_index (plugin_desc_t * pd, unsigned long index)
-{
- pd->index = index;
-}
-
-
-void
-plugin_desc_set_id (plugin_desc_t * pd, unsigned long id)
-{
- pd->id = id;
-}
-
-void
-plugin_desc_set_name (plugin_desc_t * pd, const char * name)
-{
- set_string_property (pd->name, name);
-}
-
-void
-plugin_desc_set_properties (plugin_desc_t * pd, LADSPA_Properties properties)
-{
- pd->properties = properties;
-}
-
-static void
-plugin_desc_add_audio_port_index (unsigned long ** indicies,
- unsigned long * current_port_count,
- unsigned long index)
-{
- (*current_port_count)++;
-
- if (*current_port_count == 0)
- *indicies = g_malloc (sizeof (unsigned long) * *current_port_count);
- else
- *indicies = g_realloc (*indicies, sizeof (unsigned long) * *current_port_count);
-
- (*indicies)[*current_port_count - 1] = index;
-}
-
-static void
-plugin_desc_set_port_counts (plugin_desc_t * pd)
-{
- unsigned long i;
- unsigned long icount = 0;
- unsigned long ocount = 0;
-
- for (i = 0; i < pd->port_count; i++)
- {
- if (LADSPA_IS_PORT_AUDIO (pd->port_descriptors[i]))
- {
- if (LADSPA_IS_PORT_INPUT (pd->port_descriptors[i]))
- plugin_desc_add_audio_port_index (&pd->audio_input_port_indicies, &icount, i);
- else
- plugin_desc_add_audio_port_index (&pd->audio_output_port_indicies, &ocount, i);
- }
- else
- {
- if (LADSPA_IS_PORT_OUTPUT (pd->port_descriptors[i]))
- continue;
-
- pd->control_port_count++;
- if (pd->control_port_count == 0)
- pd->control_port_indicies = g_malloc (sizeof (unsigned long) * pd->control_port_count);
- else
- pd->control_port_indicies = g_realloc (pd->control_port_indicies,
- sizeof (unsigned long) * pd->control_port_count);
-
- pd->control_port_indicies[pd->control_port_count - 1] = i;
- }
- }
-
- if (icount == ocount)
- pd->channels = icount;
- else
- { /* deal with auxilliary ports */
- unsigned long ** port_indicies;
- unsigned long port_count;
- unsigned long i, j;
-
- if (icount > ocount)
- {
- pd->channels = ocount;
- pd->aux_channels = icount - ocount;
- pd->aux_are_input = TRUE;
- port_indicies = &pd->audio_input_port_indicies;
- port_count = icount;
- }
- else
- {
- pd->channels = icount;
- pd->aux_channels = ocount - icount;
- pd->aux_are_input = FALSE;
- port_indicies = &pd->audio_output_port_indicies;
- port_count = ocount;
- }
-
- /* allocate indicies */
- pd->audio_aux_port_indicies = g_malloc (sizeof (unsigned long) * pd->aux_channels);
-
- /* copy indicies */
- for (i = pd->channels, j = 0; i < port_count; i++, j++)
- pd->audio_aux_port_indicies[j] = (*port_indicies)[i];
-
- /* shrink the main indicies to only have channels indicies */
- *port_indicies = g_realloc (*port_indicies, sizeof (unsigned long) * pd->channels);
- }
-}
-
-void
-plugin_desc_set_ports (plugin_desc_t * pd,
- unsigned long port_count,
- const LADSPA_PortDescriptor * port_descriptors,
- const LADSPA_PortRangeHint * port_range_hints,
- const char * const * port_names)
-{
- unsigned long i;
-
- plugin_desc_free_ports (pd);
-
- if (!port_count)
- return;
-
- pd->port_count = port_count;
- pd->port_descriptors = g_malloc (sizeof (LADSPA_PortDescriptor) * port_count);
- pd->port_range_hints = g_malloc (sizeof (LADSPA_PortRangeHint) * port_count);
- pd->port_names = g_malloc (sizeof (char *) * port_count);
-
- memcpy (pd->port_descriptors, port_descriptors, sizeof (LADSPA_PortDescriptor) * port_count);
- memcpy (pd->port_range_hints, port_range_hints, sizeof (LADSPA_PortRangeHint) * port_count);
-
- for (i = 0; i < port_count; i++)
- pd->port_names[i] = g_strdup (port_names[i]);
-
- plugin_desc_set_port_counts (pd);
-}
-
-
-LADSPA_Data
-plugin_desc_get_default_control_value (plugin_desc_t * pd, unsigned long port_index, guint32 sample_rate)
-{
- LADSPA_Data upper, lower;
- LADSPA_PortRangeHintDescriptor hint_descriptor;
-
- hint_descriptor = pd->port_range_hints[port_index].HintDescriptor;
-
- /* set upper and lower, possibly adjusted to the sample rate */
- if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
- upper = pd->port_range_hints[port_index].UpperBound * (LADSPA_Data) sample_rate;
- lower = pd->port_range_hints[port_index].LowerBound * (LADSPA_Data) sample_rate;
- } else {
- upper = pd->port_range_hints[port_index].UpperBound;
- lower = pd->port_range_hints[port_index].LowerBound;
- }
-
- if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor))
- {
- if (lower < FLT_EPSILON)
- lower = FLT_EPSILON;
- }
-
-
- if (LADSPA_IS_HINT_HAS_DEFAULT(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_descriptor)) {
-
- return lower;
-
- } else if (LADSPA_IS_HINT_DEFAULT_LOW(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- return exp(log(lower) * 0.75 + log(upper) * 0.25);
- } else {
- return lower * 0.75 + upper * 0.25;
- }
-
- } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- return exp(log(lower) * 0.5 + log(upper) * 0.5);
- } else {
- return lower * 0.5 + upper * 0.5;
- }
-
- } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- return exp(log(lower) * 0.25 + log(upper) * 0.75);
- } else {
- return lower * 0.25 + upper * 0.75;
- }
-
- } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_descriptor)) {
-
- return upper;
-
- } else if (LADSPA_IS_HINT_DEFAULT_0(hint_descriptor)) {
-
- return 0.0;
-
- } else if (LADSPA_IS_HINT_DEFAULT_1(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
- return (LADSPA_Data) sample_rate;
- } else {
- return 1.0;
- }
-
- } else if (LADSPA_IS_HINT_DEFAULT_100(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
- return 100.0 * (LADSPA_Data) sample_rate;
- } else {
- return 100.0;
- }
-
- } else if (LADSPA_IS_HINT_DEFAULT_440(hint_descriptor)) {
-
- if (LADSPA_IS_HINT_SAMPLE_RATE(hint_descriptor)) {
- return 440.0 * (LADSPA_Data) sample_rate;
- } else {
- return 440.0;
- }
-
- }
-
- } else { /* try and find a reasonable default */
-
- if (LADSPA_IS_HINT_BOUNDED_BELOW(hint_descriptor)) {
- return lower;
- } else if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint_descriptor)) {
- return upper;
- }
- }
-
- return 0.0;
-}
-
-LADSPA_Data
-plugin_desc_change_control_value (plugin_desc_t * pd,
- unsigned long control_index,
- LADSPA_Data value,
- guint32 old_sample_rate,
- guint32 new_sample_rate)
-{
-
- if (LADSPA_IS_HINT_SAMPLE_RATE (pd->port_range_hints[control_index].HintDescriptor))
- {
- LADSPA_Data old_sr, new_sr;
-
- old_sr = (LADSPA_Data) old_sample_rate;
- new_sr = (LADSPA_Data) new_sample_rate;
-
- value /= old_sr;
- value *= new_sr;
- }
-
- return value;
-}
-
-gint
-plugin_desc_get_copies (plugin_desc_t * pd, unsigned long rack_channels)
-{
- gint copies = 1;
-
- if (pd->channels > rack_channels)
- return 0;
-
- while (pd->channels * copies < rack_channels)
- copies++;
-
- if (pd->channels * copies > rack_channels)
- return 0;
-
- return copies;
-}
-
-/* EOF */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JR_PLUGIN_DESC_H__
-#define __JR_PLUGIN_DESC_H__
-
-#include <ladspa.h>
-#include <glib.h>
-
-typedef struct _plugin_desc plugin_desc_t;
-
-struct _plugin_desc
-{
- char * object_file;
- unsigned long index;
- unsigned long id;
- char * name;
- LADSPA_Properties properties;
- gboolean rt;
-
- unsigned long channels;
-
- gboolean aux_are_input;
- unsigned long aux_channels;
-
- unsigned long port_count;
- LADSPA_PortDescriptor * port_descriptors;
- LADSPA_PortRangeHint * port_range_hints;
- char ** port_names;
-
- unsigned long * audio_input_port_indicies;
- unsigned long * audio_output_port_indicies;
-
- unsigned long * audio_aux_port_indicies;
-
- unsigned long control_port_count;
- unsigned long * control_port_indicies;
-};
-
-plugin_desc_t * plugin_desc_new ();
-plugin_desc_t * plugin_desc_new_with_descriptor (const char * object_file,
- unsigned long index,
- const LADSPA_Descriptor * descriptor);
-void plugin_desc_destroy ();
-
-void plugin_desc_set_object_file (plugin_desc_t * pd, const char * object_file);
-void plugin_desc_set_index (plugin_desc_t * pd, unsigned long index);
-void plugin_desc_set_id (plugin_desc_t * pd, unsigned long id);
-void plugin_desc_set_name (plugin_desc_t * pd, const char * name);
-void plugin_desc_set_properties (plugin_desc_t * pd, LADSPA_Properties properties);
-
-struct _plugin * plugin_desc_instantiate (plugin_desc_t * pd);
-
-LADSPA_Data plugin_desc_get_default_control_value (plugin_desc_t * pd, unsigned long port_index, guint32 sample_rate);
-LADSPA_Data plugin_desc_change_control_value (plugin_desc_t *, unsigned long, LADSPA_Data, guint32, guint32);
-
-gint plugin_desc_get_copies (plugin_desc_t * pd, unsigned long rack_channels);
-
-#endif /* __JR_PLUGIN_DESC_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <dlfcn.h>
-#include <math.h>
-#include <strings.h>
-#include <ctype.h>
-#include <ladspa.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "plugin_mgr.h"
-#include "plugin_desc.h"
-
-
-static gboolean
-plugin_is_valid (const LADSPA_Descriptor * descriptor)
-{
- unsigned long i;
- unsigned long icount = 0;
- unsigned long ocount = 0;
-
- for (i = 0; i < descriptor->PortCount; i++)
- {
- if (!LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[i]))
- continue;
-
- if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[i]))
- icount++;
- else
- ocount++;
- }
-
- if (icount == 0 || ocount == 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-plugin_mgr_get_object_file_plugins (plugin_mgr_t * plugin_mgr, const char * filename)
-{
- const char * dlerr;
- void * dl_handle;
- LADSPA_Descriptor_Function get_descriptor;
- const LADSPA_Descriptor * descriptor;
- unsigned long plugin_index;
- plugin_desc_t * desc, * other_desc = NULL;
- GSList * list;
- gboolean exists;
- int err;
-
- /* open the object file */
- dl_handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
- if (!dl_handle)
- {
- fprintf (stderr, "%s: error opening shared object file '%s': %s\n",
- __FUNCTION__, filename, dlerror());
- return;
- }
-
-
- /* get the get_descriptor function */
- dlerror (); /* clear the error report */
-
- get_descriptor = (LADSPA_Descriptor_Function)
- dlsym (dl_handle, "ladspa_descriptor");
-
- dlerr = dlerror();
- if (dlerr) {
- fprintf (stderr, "%s: error finding ladspa_descriptor symbol in object file '%s': %s\n",
- __FUNCTION__, filename, dlerr);
- dlclose (dl_handle);
- return;
- }
-
- plugin_index = 0;
- while ( (descriptor = get_descriptor (plugin_index)) )
- {
- if (!plugin_is_valid (descriptor))
- {
- plugin_index++;
- continue;
- }
-
-
- /* check it doesn't already exist */
- exists = FALSE;
- for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
- {
- other_desc = (plugin_desc_t *) list->data;
-
- if (other_desc->id == descriptor->UniqueID)
- {
- exists = TRUE;
- break;
- }
- }
-
- if (exists)
- {
- printf ("Plugin %ld exists in both '%s' and '%s'; using version in '%s'\n",
- descriptor->UniqueID, other_desc->object_file, filename, other_desc->object_file);
- plugin_index++;
- continue;
- }
-
-
- desc = plugin_desc_new_with_descriptor (filename, plugin_index, descriptor);
- plugin_mgr->all_plugins = g_slist_append (plugin_mgr->all_plugins, desc);
- plugin_index++;
- plugin_mgr->plugin_count++;
-
- /* print in the splash screen */
- /* printf ("Loaded plugin '%s'\n", desc->name); */
- }
-
- err = dlclose (dl_handle);
- if (err)
- {
- fprintf (stderr, "%s: error closing object file '%s': %s\n",
- __FUNCTION__, filename, dlerror ());
- }
-}
-
-static void
-plugin_mgr_get_dir_plugins (plugin_mgr_t * plugin_mgr, const char * dir)
-{
- DIR * dir_stream;
- struct dirent * dir_entry;
- char * file_name;
- int err;
- size_t dirlen;
-
- dir_stream = opendir (dir);
- if (!dir_stream)
- {
-/* fprintf (stderr, "%s: error opening directory '%s': %s\n",
- __FUNCTION__, dir, strerror (errno)); */
- return;
- }
-
- dirlen = strlen (dir);
-
- while ( (dir_entry = readdir (dir_stream)) )
- {
- struct stat info;
-
- if (strcmp (dir_entry->d_name, ".") == 0 ||
- strcmp (dir_entry->d_name, "..") == 0)
- continue;
-
- file_name = g_malloc (dirlen + 1 + strlen (dir_entry->d_name) + 1);
-
- strcpy (file_name, dir);
- if (file_name[dirlen - 1] == '/')
- strcpy (file_name + dirlen, dir_entry->d_name);
- else
- {
- file_name[dirlen] = '/';
- strcpy (file_name + dirlen + 1, dir_entry->d_name);
- }
-
- stat (file_name, &info);
- if (S_ISDIR (info.st_mode))
- plugin_mgr_get_dir_plugins (plugin_mgr, file_name);
- else
- plugin_mgr_get_object_file_plugins (plugin_mgr, file_name);
-
- g_free (file_name);
- }
-
- err = closedir (dir_stream);
- if (err)
- fprintf (stderr, "%s: error closing directory '%s': %s\n",
- __FUNCTION__, dir, strerror (errno));
-}
-
-static void
-plugin_mgr_get_path_plugins (plugin_mgr_t * plugin_mgr)
-{
- char * ladspa_path, * dir;
-
- ladspa_path = g_strdup (getenv ("LADSPA_PATH"));
- if (!ladspa_path)
- ladspa_path = g_strdup ("/usr/local/lib/ladspa:/usr/lib/ladspa:/usr/lib64/ladspa");
-
- dir = strtok (ladspa_path, ":");
- do
- plugin_mgr_get_dir_plugins (plugin_mgr, dir);
- while ((dir = strtok (NULL, ":")));
-
- g_free (ladspa_path);
-}
-
-static gint
-plugin_mgr_sort (gconstpointer a, gconstpointer b)
-{
- const plugin_desc_t * da;
- const plugin_desc_t * db;
- da = (const plugin_desc_t *) a;
- db = (const plugin_desc_t *) b;
-
- return strcasecmp (da->name, db->name);
-}
-
-plugin_mgr_t *
-plugin_mgr_new ()
-{
- plugin_mgr_t * pm;
-
- pm = g_malloc (sizeof (plugin_mgr_t));
- pm->all_plugins = NULL;
- pm->plugins = NULL;
- pm->plugin_count = 0;
-
- plugin_mgr_get_path_plugins (pm);
-
- if (!pm->all_plugins)
- {
- fprintf (stderr, "No LADSPA plugins were found!\n\nCheck your LADSPA_PATH environment variable.\n");
- abort ();
- }
-
- pm->all_plugins = g_slist_sort (pm->all_plugins, plugin_mgr_sort);
-
- return pm;
-}
-
-void
-plugin_mgr_destroy (plugin_mgr_t * plugin_mgr)
-{
- GSList * list;
-
- for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
- plugin_desc_destroy ((plugin_desc_t *) list->data);
-
- g_slist_free (plugin_mgr->plugins);
- g_slist_free (plugin_mgr->all_plugins);
- free (plugin_mgr);
-}
-
-
-void
-plugin_mgr_set_plugins (plugin_mgr_t * plugin_mgr, unsigned long rack_channels)
-{
- GSList * list;
- plugin_desc_t * desc;
-
- /* clear the current plugins */
- g_slist_free (plugin_mgr->plugins);
- plugin_mgr->plugins = NULL;
-
- for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
- {
- desc = (plugin_desc_t *) list->data;
-
- if (plugin_desc_get_copies (desc, rack_channels) != 0)
- plugin_mgr->plugins = g_slist_append (plugin_mgr->plugins, desc);
- }
-}
-
-static plugin_desc_t *
-plugin_mgr_find_desc (plugin_mgr_t * plugin_mgr, GSList * plugins, unsigned long id)
-{
- GSList * list;
- plugin_desc_t * desc;
-
- for (list = plugins; list; list = g_slist_next (list))
- {
- desc = (plugin_desc_t *) list->data;
-
- if (desc->id == id)
- return desc;
- }
-
- return NULL;
-}
-
-plugin_desc_t *
-plugin_mgr_get_desc (plugin_mgr_t * plugin_mgr, unsigned long id)
-{
- return plugin_mgr_find_desc (plugin_mgr, plugin_mgr->plugins, id);
-}
-
-plugin_desc_t *
-plugin_mgr_get_any_desc (plugin_mgr_t * plugin_mgr, unsigned long id)
-{
- return plugin_mgr_find_desc (plugin_mgr, plugin_mgr->all_plugins, id);
-}
-
-
-/* EOF */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JR_PLUGIN_MANAGER_H__
-#define __JR_PLUGIN_MANAGER_H__
-
-#include <glib.h>
-
-#include "plugin_desc.h"
-
-typedef struct _plugin_mgr plugin_mgr_t;
-
-struct _plugin_mgr
-{
- GSList * all_plugins;
-
- GSList * plugins;
- unsigned long plugin_count;
-};
-
-struct _ui;
-
-plugin_mgr_t * plugin_mgr_new ();
-void plugin_mgr_destroy (plugin_mgr_t * plugin_mgr);
-
-void plugin_mgr_set_plugins (plugin_mgr_t * plugin_mgr, unsigned long rack_channels);
-
-plugin_desc_t * plugin_mgr_get_desc (plugin_mgr_t * plugin_mgr, unsigned long id);
-plugin_desc_t * plugin_mgr_get_any_desc (plugin_mgr_t * plugin_mgr, unsigned long id);
-
-#endif /* __JR_PLUGIN_MANAGER_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define _GNU_SOURCE
-
-#include <math.h>
-
-#include "plugin_settings.h"
-
-
-static void
-settings_set_to_default (settings_t * settings, guint32 sample_rate)
-{
- unsigned long control;
- guint copy;
- LADSPA_Data value;
-
- for (control = 0; control < settings->desc->control_port_count; control++)
- {
- value = plugin_desc_get_default_control_value (settings->desc, control, sample_rate);
-
- for (copy = 0; copy < settings->copies; copy++)
- {
- settings->control_values[copy][control] = value;
- }
-
- settings->locks[control] = TRUE;
- }
-}
-
-settings_t *
-settings_new (plugin_desc_t * desc, unsigned long channels, guint32 sample_rate)
-{
- settings_t * settings;
- unsigned long channel;
- guint copies;
-
- settings = g_malloc (sizeof (settings_t));
- copies = plugin_desc_get_copies (desc, channels);
-
- settings->sample_rate = sample_rate;
- settings->desc = desc;
- settings->copies = copies;
- settings->channels = channels;
- settings->lock_all = TRUE;
- settings->enabled = FALSE;
- settings->locks = NULL;
- settings->control_values = NULL;
- settings->wet_dry_enabled = FALSE;
- settings->wet_dry_locked = TRUE;
-
- /* control settings */
- if (desc->control_port_count > 0)
- {
- guint copy;
-
- settings->locks = g_malloc (sizeof (gboolean) * desc->control_port_count);
-
- settings->control_values = g_malloc (sizeof (LADSPA_Data *) * copies);
- for (copy = 0; copy < copies; copy++)
- {
- settings->control_values[copy] = g_malloc (sizeof (LADSPA_Data) * desc->control_port_count);
- }
-
- settings_set_to_default (settings, sample_rate);
- }
-
- /* wet/dry settings */
- settings->wet_dry_values = g_malloc (sizeof (LADSPA_Data) * channels);
- for (channel = 0; channel < channels; channel++)
- settings->wet_dry_values[channel] = 1.0;
-
- return settings;
-}
-
-settings_t *
-settings_dup (settings_t * other)
-{
- settings_t * settings;
- plugin_desc_t * desc;
- unsigned long channel;
-
- settings = g_malloc (sizeof (settings_t));
-
- settings->sample_rate = other->sample_rate;
- settings->desc = other->desc;
- settings->copies = settings_get_copies (other);
- settings->channels = settings_get_channels (other);
- settings->wet_dry_enabled = settings_get_wet_dry_enabled (other);
- settings->wet_dry_locked = settings_get_wet_dry_locked (other);
- settings->lock_all = settings_get_lock_all (other);
- settings->enabled = settings_get_enabled (other);
- settings->locks = NULL;
- settings->control_values = NULL;
-
- desc = other->desc;
-
- if (desc->control_port_count > 0)
- {
- guint copy;
- unsigned long control;
-
- settings->locks = g_malloc (sizeof (gboolean) * desc->control_port_count);
- for (control = 0; control < desc->control_port_count; control++)
- settings_set_lock (settings, control, settings_get_lock (other, control));
-
- settings->control_values = g_malloc (sizeof (LADSPA_Data *) * settings->copies);
- for (copy = 0; copy < settings->copies; copy++)
- {
- settings->control_values[copy] = g_malloc (sizeof (LADSPA_Data) * desc->control_port_count);
-
- for (control = 0; control < desc->control_port_count; control++)
- {
- settings->control_values[copy][control] = settings_get_control_value (other, copy, control);
- }
- }
- }
-
- settings->wet_dry_values = g_malloc (sizeof (LADSPA_Data) * settings->channels);
- for (channel = 0; channel < settings->channels; channel++)
- settings->wet_dry_values[channel] = settings_get_wet_dry_value (other, channel);
-
- return settings;
-}
-
-void
-settings_destroy (settings_t * settings)
-{
- if (settings->desc->control_port_count > 0)
- {
- guint i;
- for (i = 0; i < settings->copies; i++)
- g_free (settings->control_values[i]);
-
- g_free (settings->control_values);
- g_free (settings->locks);
- }
-
- g_free (settings->wet_dry_values);
-
- g_free (settings);
-}
-
-static void
-settings_set_copies (settings_t * settings, guint copies)
-{
- guint copy;
- guint last_copy;
- unsigned long control;
-
- if (copies <= settings->copies)
- return;
-
- last_copy = settings->copies - 1;
-
- settings->control_values = g_realloc (settings->control_values,
- sizeof (LADSPA_Data *) * copies);
-
- /* copy over the last settings to the new copies */
- for (copy = settings->copies; copy < copies; copy++)
- {
- for (control = 0; control < settings->desc->control_port_count; control++)
- {
- settings->control_values[copy][control] =
- settings->control_values[last_copy][control];
- }
- }
-
- settings->copies = copies;
-}
-
-static void
-settings_set_channels (settings_t * settings, unsigned long channels)
-{
- unsigned long channel;
- LADSPA_Data last_value;
-
- if (channels <= settings->channels)
- return;
-
- settings->wet_dry_values = g_realloc (settings->wet_dry_values, sizeof (LADSPA_Data) * channels);
-
- last_value = settings->wet_dry_values[settings->channels - 1];
-
- for (channel = settings->channels; channel < channels; channel++)
- settings->wet_dry_values[channel] = last_value;
-
- settings->channels = channels;
-}
-
-void
-settings_set_sample_rate (settings_t * settings, guint32 sample_rate)
-{
- LADSPA_Data old_sample_rate;
- LADSPA_Data new_sample_rate;
-
- g_return_if_fail (settings != NULL);
-
- if (settings->sample_rate == sample_rate)
- return;
-
- if (settings->desc->control_port_count > 0)
- {
- unsigned long control;
- guint copy;
-
- new_sample_rate = (LADSPA_Data) sample_rate;
- old_sample_rate = (LADSPA_Data) settings->sample_rate;
-
- for (control = 0; control < settings->desc->control_port_count; control++)
- {
- for (copy = 0; copy < settings->copies; copy++)
- {
- if (LADSPA_IS_HINT_SAMPLE_RATE (settings->desc->port_range_hints[control].HintDescriptor))
- {
- settings->control_values[copy][control] =
- (settings->control_values[copy][control] / old_sample_rate) * new_sample_rate;
- }
- }
- }
- }
-
- settings->sample_rate = sample_rate;
-}
-
-void
-settings_set_control_value (settings_t * settings, guint copy, unsigned long control_index, LADSPA_Data value)
-{
- g_return_if_fail (settings != NULL);
- g_return_if_fail (control_index < settings->desc->control_port_count);
-
- if (copy >= settings->copies)
- settings_set_copies (settings, copy + 1);
-
- settings->control_values[copy][control_index] = value;
-}
-
-void
-settings_set_lock (settings_t * settings, unsigned long control_index, gboolean locked)
-{
- g_return_if_fail (settings != NULL);
- g_return_if_fail (control_index < settings->desc->control_port_count);
-
- settings->locks[control_index] = locked;
-}
-
-void
-settings_set_lock_all (settings_t * settings, gboolean lock_all)
-{
- g_return_if_fail (settings != NULL);
-
- settings->lock_all = lock_all;
-}
-
-void
-settings_set_enabled (settings_t * settings, gboolean enabled)
-{
- g_return_if_fail (settings != NULL);
-
- settings->enabled = enabled;
-}
-
-void
-settings_set_wet_dry_enabled (settings_t * settings, gboolean enabled)
-{
- g_return_if_fail (settings != NULL);
-
- settings->wet_dry_enabled = enabled;
-}
-
-void
-settings_set_wet_dry_locked (settings_t * settings, gboolean locked)
-{
- g_return_if_fail (settings != NULL);
-
- settings->wet_dry_locked = locked;
-}
-
-void
-settings_set_wet_dry_value (settings_t * settings, unsigned long channel, LADSPA_Data value)
-{
- g_return_if_fail (settings != NULL);
-
- if (channel >= settings->channels)
- settings_set_channels (settings, channel + 1);
-
- settings->wet_dry_values[channel] = value;
-}
-
-
-LADSPA_Data
-settings_get_control_value (settings_t * settings, guint copy, unsigned long control_index)
-{
- g_return_val_if_fail (settings != NULL, NAN);
- g_return_val_if_fail (control_index < settings->desc->control_port_count, NAN);
-
- if (copy >= settings->copies)
- settings_set_copies (settings, copy - 1);
-
- return settings->control_values[copy][control_index];
-}
-
-gboolean
-settings_get_lock (const settings_t * settings, unsigned long control_index)
-{
- g_return_val_if_fail (settings != NULL, FALSE);
-
- return settings->locks[control_index];
-}
-
-gboolean
-settings_get_lock_all (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, FALSE);
-
- return settings->lock_all;
-}
-
-gboolean
-settings_get_enabled (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, FALSE);
-
- return settings->enabled;
-}
-
-guint
-settings_get_copies (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, 0);
-
- return settings->copies;
-}
-
-
-unsigned long
-settings_get_channels (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, 0);
-
- return settings->channels;
-}
-
-gboolean
-settings_get_wet_dry_enabled (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, FALSE);
-
- return settings->wet_dry_enabled;
-}
-
-gboolean
-settings_get_wet_dry_locked (const settings_t * settings)
-{
- g_return_val_if_fail (settings != NULL, FALSE);
-
- return settings->wet_dry_locked;
-}
-
-LADSPA_Data
-settings_get_wet_dry_value (settings_t * settings, unsigned long channel)
-{
- g_return_val_if_fail (settings != NULL, NAN);
-
- if (channel >= settings->channels)
- settings_set_channels (settings, channel + 1);
-
- return settings->wet_dry_values[channel];
-}
-
-
-
-/* EOF */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JR_PLUGIN_SETTINGS_H__
-#define __JR_PLUGIN_SETTINGS_H__
-
-#include <glib.h>
-#include <ladspa.h>
-
-#include "plugin_mgr.h"
-#include "plugin_desc.h"
-
-typedef struct _settings settings_t;
-
-struct _settings
-{
- guint32 sample_rate;
- plugin_desc_t * desc;
- guint copies;
- LADSPA_Data ** control_values;
- gboolean * locks;
- gboolean lock_all;
- gboolean enabled;
- unsigned long channels;
- gboolean wet_dry_enabled;
- gboolean wet_dry_locked;
- LADSPA_Data * wet_dry_values;
-};
-
-settings_t * settings_new (plugin_desc_t * desc, unsigned long channels, guint32 sample_rate);
-settings_t * settings_dup (settings_t * settings);
-void settings_destroy (settings_t * settings);
-
-void settings_set_control_value (settings_t * settings, guint copy, unsigned long control_index, LADSPA_Data value);
-void settings_set_lock (settings_t * settings, unsigned long control_index, gboolean locked);
-void settings_set_lock_all (settings_t * settings, gboolean lock_all);
-void settings_set_enabled (settings_t * settings, gboolean enabled);
-void settings_set_wet_dry_enabled (settings_t * settings, gboolean enabled);
-void settings_set_wet_dry_locked (settings_t * settings, gboolean locked);
-void settings_set_wet_dry_value (settings_t * settings, unsigned long channel, LADSPA_Data value);
-
-LADSPA_Data settings_get_control_value (settings_t * settings, guint copy, unsigned long control_index);
-gboolean settings_get_lock (const settings_t * settings, unsigned long control_index);
-gboolean settings_get_lock_all (const settings_t * settings);
-gboolean settings_get_enabled (const settings_t * settings);
-guint settings_get_copies (const settings_t * settings);
-unsigned long settings_get_channels (const settings_t * settings);
-gboolean settings_get_wet_dry_enabled (const settings_t * settings);
-gboolean settings_get_wet_dry_locked (const settings_t * settings);
-LADSPA_Data settings_get_wet_dry_value (settings_t * settings, unsigned long channel);
-
-void settings_set_sample_rate (settings_t * settings, guint32 sample_rate);
-
-#endif /* __JR_PLUGIN_SETTINGS_H__ */
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <jack/jack.h>
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <time.h>
-#include <ctype.h>
-
-#include "process.h"
-#include "lock_free_fifo.h"
-#include "plugin.h"
-#include "jack_rack.h"
-
-#ifndef _
-#define _(x) x
-#endif
-
-#define USEC_PER_SEC 1000000
-#define MSEC_PER_SEC 1000
-#define TIME_RUN_SKIP_COUNT 5
-#define MAX_BUFFER_SIZE 4096
-
-jack_nframes_t sample_rate;
-jack_nframes_t buffer_size;
-
-static void
-jack_shutdown_cb (void * data)
-{
- process_info_t * procinfo = data;
-
- procinfo->quit = TRUE;
-}
-
-/** process messages for plugins' control ports */
-void process_control_port_messages (process_info_t * procinfo) {
- plugin_t * plugin;
- unsigned long control;
- unsigned long channel;
- gint copy;
-
- if (!procinfo->chain) return;
-
- for (plugin = procinfo->chain; plugin; plugin = plugin->next)
- {
- if (plugin->desc->control_port_count > 0)
- for (control = 0; control < plugin->desc->control_port_count; control++)
- for (copy = 0; copy < plugin->copies; copy++)
- {
- while (lff_read (plugin->holders[copy].ui_control_fifos + control,
- plugin->holders[copy].control_memory + control) == 0);
- }
-
- if (plugin->wet_dry_enabled)
- for (channel = 0; channel < procinfo->channels; channel++)
- {
- while (lff_read (plugin->wet_dry_fifos + channel,
- plugin->wet_dry_values + channel) == 0);
- }
- }
-}
-
-int get_jack_buffers (process_info_t * procinfo, jack_nframes_t frames) {
- unsigned long channel;
-
- for (channel = 0; channel < procinfo->channels; channel++)
- {
- procinfo->jack_input_buffers[channel] = jack_port_get_buffer (procinfo->jack_input_ports[channel], frames);
- if (!procinfo->jack_input_buffers[channel])
- {
- fprintf (stderr, "%s: no jack buffer for input port %ld\n", __FUNCTION__, channel);
- return 1;
- }
-
- procinfo->jack_output_buffers[channel] = jack_port_get_buffer (procinfo->jack_output_ports[channel], frames);
- if (!procinfo->jack_output_buffers[channel])
- {
- fprintf (stderr, "%s: no jack buffer for output port %ld\n", __FUNCTION__, channel);
- return 1;
- }
- }
-
- return 0;
-}
-
-plugin_t *
-get_first_enabled_plugin (process_info_t * procinfo)
-{
- plugin_t * first_enabled;
-
- if (!procinfo->chain) return NULL;
-
- for (first_enabled = procinfo->chain;
- first_enabled;
- first_enabled = first_enabled->next)
- {
- if (first_enabled->enabled) return first_enabled;
- }
-
- return NULL;
-}
-
-plugin_t *
-get_last_enabled_plugin (process_info_t * procinfo)
-{
- plugin_t * last_enabled;
-
- if (!procinfo->chain) return NULL;
-
- for (last_enabled = procinfo->chain_end;
- last_enabled;
- last_enabled = last_enabled->prev)
- {
- if (last_enabled->enabled) return last_enabled;
- }
-
- return NULL;
-}
-
-void
-connect_chain (process_info_t * procinfo, jack_nframes_t frames)
-{
- plugin_t * first_enabled, * last_enabled, * plugin;
- gint copy;
- unsigned long channel;
- if (!procinfo->chain) return;
-
- first_enabled = get_first_enabled_plugin (procinfo);
- if (!first_enabled) return;
-
- last_enabled = get_last_enabled_plugin (procinfo);
-
- /* sort out the aux ports */
- plugin = first_enabled;
- do
- {
- if (plugin->desc->aux_channels > 0 && plugin->enabled)
- {
- if (procinfo->jack_client)
- {
- for (copy = 0; copy < plugin->copies; copy++)
- for (channel = 0; channel < plugin->desc->aux_channels; channel++)
- plugin->descriptor->
- connect_port (plugin->holders[copy].instance,
- plugin->desc->audio_aux_port_indicies[channel],
- jack_port_get_buffer (plugin->holders[copy].aux_ports[channel], frames));
- }
- else
- {
- for (copy = 0; copy < frames; copy++)
- procinfo->silent_buffer[copy] = 0.0;
-
- for (copy = 0; copy < plugin->copies; copy++)
- for (channel = 0; channel < plugin->desc->aux_channels; channel++)
- plugin->descriptor->
- connect_port (plugin->holders[copy].instance,
- plugin->desc->audio_aux_port_indicies[channel],
- procinfo->silent_buffer);
- }
- }
- }
- while ( (plugin != last_enabled) && (plugin = plugin->next) );
-
- /* ensure that all the of the enabled plugins are connected to their memory */
- plugin_connect_output_ports (first_enabled);
- if (first_enabled != last_enabled)
- {
- plugin_connect_input_ports (last_enabled, last_enabled->prev->audio_output_memory);
- for (plugin = first_enabled->next; plugin; plugin = plugin->next)
- {
- if (plugin->enabled)
- {
- plugin_connect_input_ports (plugin, plugin->prev->audio_output_memory);
- plugin_connect_output_ports (plugin);
- }
- }
- }
-
- /* input buffers for first plugin */
- plugin_connect_input_ports (first_enabled, procinfo->jack_input_buffers);
-}
-
-void
-process_chain (process_info_t * procinfo, jack_nframes_t frames)
-{
- plugin_t * first_enabled;
- plugin_t * last_enabled = NULL;
- plugin_t * plugin;
- unsigned long channel;
- unsigned long i;
-
- if (procinfo->jack_client)
- {
- LADSPA_Data zero_signal[frames];
- guint copy;
-
- /* set the zero signal to zero */
- for (channel = 0; channel < frames; channel++)
- zero_signal[channel] = 0.0;
-
- /* possibly set aux output channels to zero if they're not enabled */
- for (plugin = procinfo->chain; plugin; plugin = plugin->next)
- if (!plugin->enabled &&
- plugin->desc->aux_channels > 0 &&
- !plugin->desc->aux_are_input)
- for (copy = 0; copy < plugin->copies; copy++)
- for (channel = 0; channel < plugin->desc->aux_channels; channel++)
- memcpy (jack_port_get_buffer (plugin->holders[copy].aux_ports[channel], frames),
- zero_signal, sizeof (LADSPA_Data) * frames);
- }
-
- first_enabled = get_first_enabled_plugin (procinfo);
-
- /* no chain; just copy input to output */
- if (!procinfo->chain || !first_enabled)
- {
- unsigned long channel;
- for (channel = 0; channel < procinfo->channels; channel++)
- {
- memcpy (procinfo->jack_output_buffers[channel],
- procinfo->jack_input_buffers[channel],
- sizeof(LADSPA_Data) * frames);
- }
- return;
- }
-
- /* all past here is guaranteed to have at least 1 enabled plugin */
-
- last_enabled = get_last_enabled_plugin (procinfo);
-
- for (plugin = first_enabled;
- plugin;
- plugin = plugin->next)
- {
- if (plugin->enabled)
- {
- for (i = 0; i < plugin->copies; i++)
- plugin->descriptor->run (plugin->holders[i].instance, frames);
-
- if (plugin->wet_dry_enabled)
- for (channel = 0; channel < procinfo->channels; channel++)
- for (i = 0; i < frames; i++)
- {
- plugin->audio_output_memory[channel][i] *= plugin->wet_dry_values[channel];
- plugin->audio_output_memory[channel][i] += plugin->audio_input_memory[channel][i] * (1.0 - plugin->wet_dry_values[channel]);
- }
-
- if (plugin == last_enabled)
- break;
- }
- else
- {
-
- /* copy the data through */
- for (i = 0; i < procinfo->channels; i++)
- memcpy (plugin->audio_output_memory[i],
- plugin->prev->audio_output_memory[i],
- sizeof(LADSPA_Data) * frames);
- }
- }
-
- /* copy the last enabled data to the jack ports */
- for (i = 0; i < procinfo->channels; i++)
- memcpy (procinfo->jack_output_buffers[i],
- last_enabled->audio_output_memory[i],
- sizeof(LADSPA_Data) * frames);
-
-}
-
-int process_ladspa (process_info_t * procinfo, jack_nframes_t frames,
- LADSPA_Data ** inputs, LADSPA_Data ** outputs) {
- unsigned long channel;
-
- if (!procinfo)
- {
- fprintf (stderr, "%s: no process_info from jack!\n", __FUNCTION__);
- return 1;
- }
-
- if (procinfo->quit == TRUE)
- return 1;
-
- process_control_port_messages (procinfo);
-
- for (channel = 0; channel < procinfo->channels; channel++)
- {
- procinfo->jack_input_buffers[channel] = inputs[channel];
- if (!procinfo->jack_input_buffers[channel])
- {
- fprintf (stderr, "%s: no jack buffer for input port %ld\n", __FUNCTION__, channel);
- return 1;
- }
-
- procinfo->jack_output_buffers[channel] = outputs[channel];
- if (!procinfo->jack_output_buffers[channel])
- {
- fprintf (stderr, "%s: no jack buffer for output port %ld\n", __FUNCTION__, channel);
- return 1;
- }
- }
-
- connect_chain (procinfo, frames);
-
- process_chain (procinfo, frames);
-
- return 0;
-}
-
-int process_jack (jack_nframes_t frames, void * data) {
- int err;
- process_info_t * procinfo;
-
- procinfo = (process_info_t *) data;
-
- if (!procinfo)
- {
- fprintf (stderr, "%s: no process_info from jack!\n", __FUNCTION__);
- return 1;
- }
-
- if (procinfo->port_count == 0)
- return 0;
-
- if (procinfo->quit == TRUE)
- return 1;
-
- process_control_port_messages (procinfo);
-
- err = get_jack_buffers (procinfo, frames);
- if (err)
- {
- fprintf(stderr, "%s: failed to get jack ports, not processing\n", __FUNCTION__);
- return 0;
- }
-
- connect_chain (procinfo, frames);
-
- process_chain (procinfo, frames);
-
- return 0;
-}
-
-
-
-/*******************************************
- ************** non RT stuff ***************
- *******************************************/
-
-static int
-process_info_connect_jack (process_info_t * procinfo)
-{
- printf (_("Connecting to JACK server with client name '%s'\n"), procinfo->jack_client_name);
-
- procinfo->jack_client = jack_client_new (procinfo->jack_client_name);
-
- if (!procinfo->jack_client)
- {
- fprintf (stderr, "%s: could not create jack client; is the jackd server running?\n", __FUNCTION__);
- return 1;
- }
-
- printf (_("Connected to JACK server\n"));
-
- jack_set_process_callback (procinfo->jack_client, process_jack, procinfo);
- jack_on_shutdown (procinfo->jack_client, jack_shutdown_cb, procinfo);
-
- return 0;
-}
-
-static void
-process_info_connect_port (process_info_t * procinfo,
- gshort in,
- unsigned long port_index,
- const char * port_name)
-{
- const char ** jack_ports;
- unsigned long jack_port_index;
- int err;
- char * full_port_name;
-
- jack_ports = jack_get_ports (procinfo->jack_client, NULL, NULL,
- JackPortIsPhysical | (in ? JackPortIsOutput : JackPortIsInput));
-
- if (!jack_ports)
- return;
-
- for (jack_port_index = 0;
- jack_ports[jack_port_index] && jack_port_index <= port_index;
- jack_port_index++)
- {
- if (jack_port_index != port_index)
- continue;
-
- full_port_name = g_strdup_printf ("%s:%s", procinfo->jack_client_name, port_name);
-
- printf (_("Connecting ports '%s' and '%s'\n"), full_port_name, jack_ports[jack_port_index]);
-
- err = jack_connect (procinfo->jack_client,
- in ? jack_ports[jack_port_index] : full_port_name,
- in ? full_port_name : jack_ports[jack_port_index]);
-
- if (err)
- fprintf (stderr, "%s: error connecting ports '%s' and '%s'\n",
- __FUNCTION__, full_port_name, jack_ports[jack_port_index]);
- else
- printf (_("Connected ports '%s' and '%s'\n"), full_port_name, jack_ports[jack_port_index]);
-
- free (full_port_name);
- }
-
- free (jack_ports);
-}
-
-int
-process_info_set_port_count (process_info_t * procinfo,
- unsigned long port_count, gboolean connect_inputs, gboolean connect_outputs)
-{
- unsigned long i;
- char * port_name;
- jack_port_t ** port_ptr;
- gshort in;
-
- if (procinfo->port_count >= port_count)
- return -1;
-
- if (procinfo->port_count == 0)
- {
- procinfo->jack_input_ports = g_malloc (sizeof (jack_port_t *) * port_count);
- procinfo->jack_output_ports = g_malloc (sizeof (jack_port_t *) * port_count);
-
- procinfo->jack_input_buffers = g_malloc (sizeof (LADSPA_Data *) * port_count);
- procinfo->jack_output_buffers = g_malloc (sizeof (LADSPA_Data *) * port_count);
- }
- else
- {
- procinfo->jack_input_ports = g_realloc (procinfo->jack_input_ports, sizeof (jack_port_t *) * port_count);
- procinfo->jack_output_ports = g_realloc (procinfo->jack_output_ports, sizeof (jack_port_t *) * port_count);
-
- procinfo->jack_input_buffers = g_realloc (procinfo->jack_input_buffers, sizeof (LADSPA_Data *) * port_count);
- procinfo->jack_output_buffers = g_realloc (procinfo->jack_output_buffers, sizeof (LADSPA_Data *) * port_count);
- }
-
- for (i = procinfo->port_count; i < port_count; i++)
- {
- for (in = 0; in < 2; in++)
- {
- port_name = g_strdup_printf ("%s_%ld", in ? "in" : "out", i + 1);
-
- //printf (_("Creating %s port %s\n"), in ? "input" : "output", port_name);
-
- port_ptr = (in ? &procinfo->jack_input_ports[i]
- : &procinfo->jack_output_ports[i]);
-
- *port_ptr = jack_port_register (procinfo->jack_client,
- port_name,
- JACK_DEFAULT_AUDIO_TYPE,
- in ? JackPortIsInput : JackPortIsOutput,
- 0);
-
- if (!*port_ptr)
- {
- fprintf (stderr, "%s: could not register port '%s'; aborting\n",
- __FUNCTION__, port_name);
- return 1;
- }
-
- //printf (_("Created %s port %s\n"), in ? "input" : "output", port_name);
-
- if ((in && connect_inputs) || (!in && connect_outputs))
- process_info_connect_port (procinfo, in, i, port_name);
-
- g_free (port_name);
- }
- }
-
- procinfo->port_count = port_count;
-
- return 0;
-}
-
-void
-process_info_set_channels (process_info_t * procinfo,
- unsigned long channels, gboolean connect_inputs, gboolean connect_outputs)
-{
- process_info_set_port_count (procinfo, channels, connect_inputs, connect_outputs);
- procinfo->channels = channels;
-}
-
-process_info_t *
-process_info_new (const char * client_name, unsigned long rack_channels,
- gboolean connect_inputs, gboolean connect_outputs)
-{
- process_info_t * procinfo;
- char * jack_client_name;
- int err;
-
- procinfo = g_malloc (sizeof (process_info_t));
-
- procinfo->chain = NULL;
- procinfo->chain_end = NULL;
- procinfo->jack_client = NULL;
- procinfo->port_count = 0;
- procinfo->jack_input_ports = NULL;
- procinfo->jack_output_ports = NULL;
- procinfo->channels = rack_channels;
- procinfo->quit = FALSE;
-
- if ( client_name == NULL )
- {
- sample_rate = 48000; // should be set externally before calling process_ladspa
- buffer_size = MAX_BUFFER_SIZE;
- procinfo->silent_buffer = g_malloc (sizeof (LADSPA_Data) * buffer_size );
- procinfo->jack_input_buffers = g_malloc (sizeof (LADSPA_Data *) * rack_channels);
- procinfo->jack_output_buffers = g_malloc (sizeof (LADSPA_Data *) * rack_channels);
-
- return procinfo;
- }
-
- /* sort out the client name */
- procinfo->jack_client_name = jack_client_name = strdup (client_name);
- for (err = 0; jack_client_name[err] != '\0'; err++)
- {
- if (jack_client_name[err] == ' ')
- jack_client_name[err] = '_';
- else if (!isalnum (jack_client_name[err]))
- { /* shift all the chars up one (to remove the non-alphanumeric char) */
- int i;
- for (i = err; jack_client_name[i] != '\0'; i++)
- jack_client_name[i] = jack_client_name[i + 1];
- }
- else if (isupper (jack_client_name[err]))
- jack_client_name[err] = tolower (jack_client_name[err]);
- }
-
- err = process_info_connect_jack (procinfo);
- if (err)
- {
-/* g_free (procinfo); */
- return NULL;
-/* abort (); */
- }
-
- sample_rate = jack_get_sample_rate (procinfo->jack_client);
- buffer_size = jack_get_sample_rate (procinfo->jack_client);
-
- jack_set_process_callback (procinfo->jack_client, process_jack, procinfo);
- jack_on_shutdown (procinfo->jack_client, jack_shutdown_cb, procinfo);
-
- jack_activate (procinfo->jack_client);
-
- err = process_info_set_port_count (procinfo, rack_channels, connect_inputs, connect_outputs);
- if (err)
- return NULL;
-
- return procinfo;
-}
-
-void
-process_info_destroy (process_info_t * procinfo) {
- if (procinfo->jack_client)
- {
- jack_deactivate (procinfo->jack_client);
- jack_client_close (procinfo->jack_client);
- }
- g_free (procinfo->silent_buffer);
- g_free (procinfo->jack_input_ports);
- g_free (procinfo->jack_output_ports);
- g_free (procinfo->jack_input_buffers);
- g_free (procinfo->jack_output_buffers);
- g_free (procinfo);
-}
-
-void process_quit (process_info_t * procinfo) {
- procinfo->quit = TRUE;
-}
+++ /dev/null
-/*
- * JACK Rack
- *
- * Original:
- * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
- *
- * Modification for MLT:
- * Copyright (C) 2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __JLH_PROCESS_H__
-#define __JLH_PROCESS_H__
-
-#include <glib.h>
-#include <jack/jack.h>
-#include <ladspa.h>
-
-#include "lock_free_fifo.h"
-
-typedef struct _process_info process_info_t;
-
-/** this is what gets passed to the process() callback and contains all
- the data the process callback will need */
-struct _process_info {
-
- /** the plugin instance chain */
- struct _plugin * chain;
- struct _plugin * chain_end;
-
- jack_client_t * jack_client;
- unsigned long port_count;
- jack_port_t ** jack_input_ports;
- jack_port_t ** jack_output_ports;
-
- unsigned long channels;
- LADSPA_Data ** jack_input_buffers;
- LADSPA_Data ** jack_output_buffers;
- LADSPA_Data * silent_buffer;
-
- char * jack_client_name;
- int quit;
-};
-
-extern jack_nframes_t sample_rate;
-extern jack_nframes_t buffer_size;
-
-process_info_t * process_info_new (const char * client_name,
- unsigned long rack_channels, gboolean connect_inputs, gboolean connect_outputs);
-void process_info_destroy (process_info_t * procinfo);
-
-void process_info_set_channels (process_info_t * procinfo,
- unsigned long channels, gboolean connect_inputs, gboolean connect_outputs);
-
-int process_ladspa (process_info_t * procinfo, jack_nframes_t frames,
- LADSPA_Data ** inputs, LADSPA_Data ** outputs);
-
-int process_jack (jack_nframes_t frames, void * data);
-
-void process_quit (process_info_t * procinfo);
-
-#endif /* __JLH_PROCESS_H__ */
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltkdenlive$(LIBSUF)
-
-OBJS = factory.o \
- filter_boxblur.o \
- filter_freeze.o \
- filter_wave.o \
- producer_framebuffer.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += -lm
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2007 Jean-Baptiste Mardelle
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_boxblur_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_freeze_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_wave_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_framebuffer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "boxblur", filter_boxblur_init );
- MLT_REGISTER( filter_type, "freeze", filter_freeze_init );
- MLT_REGISTER( filter_type, "wave", filter_wave_init );
- MLT_REGISTER( producer_type, "framebuffer", producer_framebuffer_init );
-}
+++ /dev/null
-/*
- * filter_boxblur.c -- blur filter
- * Copyright (C) ?-2007 Leny Grisel <leny.grisel@laposte.net>
- * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@ader.ch>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-
-static void PreCompute(uint8_t *yuv, int32_t *rgb, int width, int height)
-{
- register int x, y, z;
- register int uneven = width % 2;
- int w = (width - uneven ) / 2;
- int yy, uu, vv;
- int r, g, b;
- int32_t pts[3];
- for (y=0; y<height; y++)
- {
- for (x=0; x<w; x++)
- {
- uu = yuv[1];
- vv = yuv[3];
- yy = yuv[0];
- YUV2RGB(yy, uu, vv, r, g, b);
- pts[0] = r;
- pts[1] = g;
- pts[2] = b;
- for (z = 0; z < 3; z++)
- {
- if (x>0) pts[z]+=rgb[-3];
- if (y>0) pts[z]+=rgb[-(width*3)];
- if (x>0 && y>0) pts[z]-=rgb[-((width+1)*3)];
- *rgb++=pts[z];
- }
-
- yy = yuv[2];
- YUV2RGB(yy, uu, vv, r, g, b);
- pts[0] = r;
- pts[1] = g;
- pts[2] = b;
- for (z = 0; z < 3; z++)
- {
- pts[z]+=rgb[-3];
- if (y>0)
- {
- pts[z]+=rgb[-(width*3)];
- pts[z]-=rgb[-((width+1)*3)];
- }
- *rgb++=pts[z];
- }
- yuv += 4;
- }
- if (uneven)
- {
- uu = yuv[1];
- vv = yuv[3];
- yy = yuv[0];
- YUV2RGB(yy, uu, vv, r, g, b);
- pts[0] = r;
- pts[1] = g;
- pts[2] = b;
- for (z = 0; z < 3; z++)
- {
- pts[z]+=rgb[-3];
- if (y>0)
- {
- pts[z]+=rgb[-(width*3)];
- pts[z]-=rgb[-((width+1)*3)];
- }
- *rgb++=pts[z];
- }
- yuv += 2;
- }
- }
-}
-
-static int32_t GetRGB(int32_t *rgb, unsigned int w, unsigned int h, unsigned int x, int offsetx, unsigned int y, int offsety, unsigned int z)
-{
- int xtheo = x * 2 + offsetx;
- int ytheo = y + offsety;
- if (xtheo < 0) xtheo = 0; else if (xtheo >= w) xtheo = w - 1;
- if (ytheo < 0) ytheo = 0; else if (ytheo >= h) ytheo = h - 1;
- return rgb[3*(xtheo+ytheo*w)+z];
-}
-
-static int32_t GetRGB2(int32_t *rgb, unsigned int w, unsigned int h, unsigned int x, int offsetx, unsigned int y, int offsety, unsigned int z)
-{
- int xtheo = x * 2 + 1 + offsetx;
- int ytheo = y + offsety;
- if (xtheo < 0) xtheo = 0; else if (xtheo >= w) xtheo = w - 1;
- if (ytheo < 0) ytheo = 0; else if (ytheo >= h) ytheo = h - 1;
- return rgb[3*(xtheo+ytheo*w)+z];
-}
-
-static void DoBoxBlur(uint8_t *yuv, int32_t *rgb, unsigned int width, unsigned int height, unsigned int boxw, unsigned int boxh)
-{
- register int x, y;
- int32_t r, g, b;
- register int uneven = width % 2;
- register int y0, y1, u0, u1, v0, v1;
- int w = (width - uneven ) / 2;
- float mul = 1.f / ((boxw*2) * (boxh*2));
-
- for (y = 0; y < height; y++)
- {
- for (x = 0; x < w; x++)
- {
- r = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 0) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 0) - GetRGB(rgb, width, height, x, -boxw, y, + boxh, 0) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 0);
- g = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 1) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 1) - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 1) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 1);
- b = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 2) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 2) - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 2) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 2);
- r = (int32_t) (r * mul);
- g = (int32_t) (g * mul);
- b = (int32_t) (b * mul);
- RGB2YUV (r, g, b, y0, u0, v0);
-
- r = GetRGB2(rgb, width, height, x, +boxw, y, +boxh, 0) + GetRGB2(rgb, width, height, x, -boxw, y, -boxh, 0) - GetRGB2(rgb, width, height, x, -boxw, y, +boxh, 0) - GetRGB2(rgb, width, height, x, +boxw, y, -boxh, 0);
- g = GetRGB2(rgb, width, height, x, +boxw, y, +boxh, 1) + GetRGB2(rgb, width, height, x, -boxw, y, -boxh, 1) - GetRGB2(rgb, width, height, x, -boxw, y, +boxh, 1) - GetRGB2(rgb, width, height, x, +boxw, y, -boxh, 1);
- b = GetRGB2(rgb, width, height, x, +boxw, y, +boxh, 2) + GetRGB2(rgb, width, height, x, -boxw, y, -boxh, 2) - GetRGB2(rgb, width, height, x, -boxw, y, +boxh, 2) - GetRGB2(rgb, width, height, x, +boxw, y, -boxh, 2);
- r = (int32_t) (r * mul);
- g = (int32_t) (g * mul);
- b = (int32_t) (b * mul);
- RGB2YUV (r, g, b, y1, u1, v1);
- *yuv++ = y0;
- *yuv++ = (u0+u1) >> 1;
- *yuv++ = y1;
- *yuv++ = (v0+v1) >> 1;
- }
- if (uneven)
- {
- r = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 0) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 0) - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 0) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 0);
- g = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 1) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 1) - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 1) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 1);
- b = GetRGB(rgb, width, height, x, +boxw, y, +boxh, 2) + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 2) - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 2) - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 2);
- r = (int32_t) (r * mul);
- g = (int32_t) (g * mul);
- b = (int32_t) (b * mul);
- RGB2YUV (r, g, b, y0, u0, v0);
- *yuv++ = mul * y0;
- *yuv++ = mul * u0;
- }
- }
-}
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- short hori = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "hori" );
- short vert = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "vert" );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- double factor = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" );
- if (factor != 0) {
- int h = *height + 1;
- int32_t *rgb = mlt_pool_alloc (3 * *width * h * sizeof(int32_t));
- PreCompute (*image, rgb, *width, h);
- DoBoxBlur (*image, rgb, *width, h, (int) factor*hori, (int) factor*vert);
- mlt_pool_release (rgb);
- }
- }
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the starting blur level
- double blur = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "start" );
- short hori = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "hori" );
- short vert = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "vert" );
-
- // If there is an end adjust gain to the range
- if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
- mlt_position time = mlt_frame_get_position( frame );
- double position = (double) ( time - in ) / ( out - in + 1.0 );
- double end = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "end" );
- blur += ( end - blur ) * position;
- }
-
- // Push the frame filter
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "boxblur", blur );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "hori", hori );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "vert", vert );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_boxblur_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "10" : arg);
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "hori", arg == NULL ? "1" : arg);
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "vert", arg == NULL ? "1" : arg);
- }
- return this;
-}
-
-
-
+++ /dev/null
-/*
- * filter_freeze.c -- simple frame freezing filter
- * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@kdenlive.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_service.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_property.h>
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the image
- mlt_filter filter = mlt_frame_pop_service( this );
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
-
- mlt_frame freeze_frame = NULL;;
- int freeze_before = mlt_properties_get_int( properties, "freeze_before" );
- int freeze_after = mlt_properties_get_int( properties, "freeze_after" );
- mlt_position pos = mlt_properties_get_position( properties, "frame" );
- mlt_position currentpos = mlt_properties_get_position( properties, "_seek_frame" );
-
- int do_freeze = 0;
- if (freeze_before == 0 && freeze_after == 0) {
- do_freeze = 1;
- } else if (freeze_before != 0 && pos > currentpos) {
- do_freeze = 1;
- } else if (freeze_after != 0 && pos < currentpos) {
- do_freeze = 1;
- }
-
- if (do_freeze == 1) {
- freeze_frame = mlt_properties_get_data( properties, "freeze_frame", NULL );
-
- if( freeze_frame == NULL || mlt_properties_get_position( properties, "_frame" ) != pos )
- {
- // freeze_frame has not been fetched yet, so fetch it and cache it.
- mlt_producer producer = mlt_frame_get_original_producer(this);
- mlt_producer_seek( producer, pos );
-
- // Get the frame
- mlt_service_get_frame( mlt_producer_service(producer), &freeze_frame, 0 );
-
- mlt_properties props = MLT_FRAME_PROPERTIES( this );
- mlt_properties freeze_properties = MLT_FRAME_PROPERTIES( freeze_frame );
- mlt_properties_set_double( freeze_properties, "consumer_aspect_ratio", mlt_properties_get_double( props, "consumer_aspect_ratio" ) );
- mlt_properties_set( freeze_properties, "rescale.interp", mlt_properties_get( props, "rescale.interp" ) );
- mlt_properties_set_double( freeze_properties, "aspect_ratio", mlt_frame_get_aspect_ratio( this ) );
- mlt_properties_set_int( freeze_properties, "progressive", mlt_properties_get_int( props, "progressive" ) );
-
- mlt_properties_set_data( properties, "freeze_frame", freeze_frame, 0, NULL, NULL );
- mlt_properties_set_position( properties, "_frame", pos );
- }
- int error = mlt_frame_get_image( freeze_frame, image, format, width, height, 1 );
- return error;
- }
-
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- // Push the filter on to the stack
- mlt_frame_push_service( frame, this );
-
- // Determine the time position of this frame
- mlt_properties_set_position( MLT_FILTER_PROPERTIES( this ), "_seek_frame", mlt_frame_get_position( frame ) - mlt_filter_get_in( this ) );
-
- // Push the frame filter
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_freeze_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- // Set the frame which will be chosen for freeze
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "frame", "0" );
-
- // If freeze_after = 1, only frames after the "frame" value will be frozen
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "freeze_after", "0" );
-
- // If freeze_before = 1, only frames after the "frame" value will be frozen
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "freeze_before", "0" );
- }
- return this;
-}
-
-
-
+++ /dev/null
-/*
- * wave.c -- wave filter
- * Copyright (C) ?-2007 Leny Grisel <leny.grisel@laposte.net>
- * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@ader.ch>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-// this is a utility function used by DoWave below
-static uint8_t getPoint(uint8_t *src, int w, int h, int x, int y, int z)
-{
- if (x<0) x+=-((-x)%w)+w; else if (x>=w) x=x%w;
- if (y<0) y+=-((-y)%h)+h; else if (y>=h) y=y%h;
- return src[(x+y*w)*4+z];
-}
-
-// the main meat of the algorithm lies here
-static void DoWave(uint8_t *src, int src_w, int src_h, uint8_t *dst, mlt_position position, int speed, int factor, int deformX, int deformY)
-{
- register int x, y;
- int decalY, decalX, z;
- float amplitude, phase, pulsation;
- register int uneven = src_w % 2;
- int w = (src_w - uneven ) / 2;
- amplitude = factor;
- pulsation = 0.5 / factor; // smaller means bigger period
- phase = position * pulsation * speed / 10; // smaller means longer
- for (y=0;y<src_h;y++) {
- decalX = deformX ? sin(pulsation * y + phase) * amplitude : 0;
- for (x=0;x<w;x++) {
- decalY = deformY ? sin(pulsation * x * 2 + phase) * amplitude : 0;
- for (z=0; z<4; z++)
- *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
- }
- if (uneven) {
- decalY = sin(pulsation * x * 2 + phase) * amplitude;
- for (z=0; z<2; z++)
- *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
- }
- }
-}
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- mlt_position position = mlt_frame_get_position( this );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- double factor = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "wave" );
- int speed = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "speed" );
- int deformX = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformX" );
- int deformY = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformY" );
- if (factor != 0) {
- int image_size = *width * (*height + 1) * 2;
- uint8_t *dest = mlt_pool_alloc (image_size);
- DoWave(*image, *width, (*height + 1), dest, position, speed, factor, deformX, deformY);
- memcpy(*image, dest, image_size);
- mlt_pool_release(dest);
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the starting wave level
- double wave = mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "start" );
- int speed = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "speed" );
- int deformX = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformX" );
- int deformY = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformY" );
-
- // If there is an end adjust gain to the range
- if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
- mlt_position time = mlt_frame_get_position( frame );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "end" ) );
- wave += ( end - wave ) * position;
- }
-
- // Push the frame filter
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "wave", wave );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "speed", speed );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformX", deformX );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformY", deformY );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_wave_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "10" : arg);
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "speed", arg == NULL ? "5" : arg);
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformX", arg == NULL ? "1" : arg);
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformY", arg == NULL ? "1" : arg);
- }
- return this;
-}
-
-
-
+++ /dev/null
-/*
- * producer_framebuffer.c -- create subspeed frames
- * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@ader.ch>
- * Author: Jean-Baptiste Mardelle, based on the code of motion_est by Zachary Drew
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <sys/time.h>
-#include <assert.h>
-
-// Forward references.
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
-
-/** Image stack(able) method
-*/
-
-static int framebuffer_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- // Get the filter object and properties
- mlt_producer producer = mlt_frame_pop_service( this );
- mlt_frame first_frame = mlt_frame_pop_service( this );
-
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Frame properties objects
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( this );
- mlt_properties first_frame_properties = MLT_FRAME_PROPERTIES( first_frame );
-
- *width = mlt_properties_get_int( frame_properties, "width" );
- *height = mlt_properties_get_int( frame_properties, "height" );
-
- int size;
- switch ( *format )
- {
- case mlt_image_yuv420p:
- size = *width * 3 * ( *height + 1 ) / 2;
- break;
- case mlt_image_rgb24:
- size = *width * ( *height + 1 ) * 3;
- break;
- default:
- *format = mlt_image_yuv422;
- size = *width * ( *height + 1 ) * 2;
- break;
- }
-
- uint8_t *output = mlt_properties_get_data( producer_properties, "output_buffer", NULL );
-
- if( output == NULL )
- {
- output = mlt_pool_alloc( size );
-
- // Let someone else clean up
- mlt_properties_set_data( producer_properties, "output_buffer", output, size, mlt_pool_release, NULL );
- }
-
- uint8_t *first_image = mlt_properties_get_data( first_frame_properties, "image", NULL );
-
- // which frames are buffered?
-
- int error = 0;
-
- if( first_image == NULL )
- {
- mlt_properties props = MLT_FRAME_PROPERTIES( this );
- mlt_properties test_properties = MLT_FRAME_PROPERTIES( first_frame );
- mlt_properties_set_double( test_properties, "consumer_aspect_ratio", mlt_properties_get_double( props, "consumer_aspect_ratio" ) );
- mlt_properties_set( test_properties, "rescale.interp", mlt_properties_get( props, "rescale.interp" ) );
-
- error = mlt_frame_get_image( first_frame, &first_image, format, width, height, writable );
-
- if( error != 0 ) {
- fprintf(stderr, "first_image == NULL get image died\n");
- return error;
- }
- }
-
- // Start with a base image
- memcpy( output, first_image, size );
-
- *image = output;
- mlt_properties_set_data( frame_properties, "image", output, size, NULL, NULL );
-
- // Make sure that no further scaling is done
- mlt_properties_set( frame_properties, "rescale.interps", "none" );
- mlt_properties_set( frame_properties, "scale", "off" );
-
- mlt_frame_close( first_frame );
-
- return 0;
-}
-
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Construct a new frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- if( frame != NULL )
- {
- mlt_frame first_frame = mlt_properties_get_data( properties, "first_frame", NULL );
-
- mlt_position first_position = (first_frame != NULL) ? mlt_frame_get_position( first_frame ) : -1;
-
- // Get the real producer
- mlt_producer real_producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // get properties
- int strobe = mlt_properties_get_int( properties, "strobe");
- int freeze = mlt_properties_get_int( properties, "freeze");
- int freeze_after = mlt_properties_get_int( properties, "freeze_after");
- int freeze_before = mlt_properties_get_int( properties, "freeze_before");
-
- mlt_position need_first;
-
- if (!freeze || freeze_after || freeze_before) {
- double prod_speed = mlt_properties_get_double( properties, "_speed");
- double actual_position = prod_speed * (double) mlt_producer_position( this );
-
- if (mlt_properties_get_int( properties, "reverse")) actual_position = mlt_producer_get_playtime(this) - actual_position;
-
- if (strobe < 2)
- {
- need_first = floor( actual_position );
- }
- else
- {
- // Strobe effect wanted, calculate frame position
- need_first = floor( actual_position );
- need_first -= need_first%strobe;
- }
- if (freeze)
- {
- if (freeze_after && need_first > freeze) need_first = freeze;
- else if (freeze_before && need_first < freeze) need_first = freeze;
- }
- }
- else need_first = freeze;
-
- if( need_first != first_position )
- {
- mlt_frame_close( first_frame );
- first_position = -1;
- first_frame = NULL;
- }
-
- if( first_frame == NULL )
- {
- // Seek the producer to the correct place
- mlt_producer_seek( real_producer, need_first );
-
- // Get the frame
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( real_producer ), &first_frame, index );
- }
-
- // Make sure things are in their place
- mlt_properties_set_data( properties, "first_frame", first_frame, 0, NULL, NULL );
-
- // Stack the producer and producer's get image
- mlt_frame_push_service( *frame, first_frame );
- mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( first_frame ) );
-
- mlt_frame_push_service( *frame, this );
- mlt_frame_push_service( *frame, framebuffer_get_image );
-
-
- // Give the returned frame temporal identity
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
- }
-
- return 0;
-}
-
-
-mlt_producer producer_framebuffer_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- if ( !arg ) return NULL;
- mlt_producer this = NULL;
- this = calloc( 1, sizeof( struct mlt_producer_s ) );
- mlt_producer_init( this, NULL );
-
- // Wrap fezzik
- mlt_producer real_producer;
-
- // Check if a speed was specified.
- /**
-
- * Speed must be appended to the filename with '?'. To play your video at 50%:
- inigo framebuffer:my_video.mpg?0.5
-
- * Stroboscope effect can be obtained by adding a stobe=x parameter, where
- x is the number of frames that will be ignored.
-
- * You can play the movie backwards by adding reverse=1
-
- * You can freeze the clip at a determined position by adding freeze=frame_pos
- add freeze_after=1 to freeze only paste position or freeze_before to freeze before it
-
- **/
-
- double speed = 0.0;
- char *props = strdup( arg );
- char *ptr = strrchr( props, '?' );
-
- if ( ptr )
- {
- speed = atof( ptr + 1 );
- if ( speed != 0.0 )
- // If speed was valid, then strip it and the delimiter.
- // Otherwise, an invalid speed probably means this '?' was not a delimiter.
- *ptr = '\0';
- }
-
- real_producer = mlt_factory_producer( profile, "fezzik", props );
- free( props );
-
- if (speed == 0.0) speed = 1.0;
-
- if ( this != NULL && real_producer != NULL)
- {
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fezzik normalised it for us already
- mlt_properties_set_int( properties, "fezzik_normalised", 1);
- mlt_properties_set( properties, "resource", arg);
-
- // Store the producer and fitler
- mlt_properties_set_data( properties, "producer", real_producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
-
- // Grab some stuff from the real_producer
- mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( real_producer ), "length, width,height" );
-
- if ( speed < 0 )
- {
- speed = -speed;
- mlt_properties_set_int( properties, "reverse", 1 );
- }
-
- if ( speed != 1.0 )
- {
- double real_length = ( (double) mlt_producer_get_length( real_producer ) ) / speed;
- mlt_properties_set_position( properties, "length", real_length );
- }
- mlt_properties_set_position( properties, "out", mlt_producer_get_length( this ) - 1 );
-
- // Since we control the seeking, prevent it from seeking on its own
- mlt_producer_set_speed( real_producer, 0 );
- mlt_producer_set_speed( this, speed );
-
- // Override the get_frame method
- this->get_frame = producer_get_frame;
- }
- else
- {
- if ( this )
- mlt_producer_close( this );
- if ( real_producer )
- mlt_producer_close( real_producer );
-
- this = NULL;
- }
- return this;
-}
+++ /dev/null
-include ../../../config.mak
-include config.mak
-
-TARGET = ../libmltkino.so
-
-OBJS = factory.o producer_kino.o
-CPPOBJS = kino_wrapper.o avi.o error.o filehandler.o riff.o
-
-CFLAGS += -I../../
-CXXFLAGS += $(CFLAGS) -Wno-deprecated
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += -lstdc++
-
-ifdef HAVE_LIBQUICKTIME
-CFLAGS += `pkg-config --cflags libquicktime`
-CXXFLAGS += `pkg-config --cflags libquicktime`
-LDFLAGS += `pkg-config --libs libquicktime`
-endif
-
-ifdef HAVE_LIBDV
-CFLAGS += `pkg-config --cflags libdv`
-LDFLAGS += `pkg-config --libs libdv`
-endif
-
-
-SRCS := $(OBJS:.o=.c) $(CPPOBJS:.o=.cc)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS) $(CPPOBJS)
- $(CC) -shared -o $@ $(OBJS) $(CPPOBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend config.h config.mak
-
-clean:
- rm -f $(OBJS) $(TARGET) $(CPPOBJS)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
-* avi.cc library for AVI file format i/o
-* Copyright (C) 2000 - 2002 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "config.h"
-
-// C++ includes
-
-#include <string>
-#include <iostream>
-#include <iomanip>
-
-using std::cout;
-using std::hex;
-using std::dec;
-using std::setw;
-using std::setfill;
-using std::endl;
-
-// C includes
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-
-// local includes
-
-#include "error.h"
-#include "riff.h"
-#include "avi.h"
-
-#define PADDING_SIZE (512)
-#define PADDING_1GB (0x40000000)
-#define IX00_INDEX_SIZE (4028)
-
-#define AVIF_HASINDEX 0x00000010
-#define AVIF_MUSTUSEINDEX 0x00000020
-#define AVIF_TRUSTCKTYPE 0x00000800
-#define AVIF_ISINTERLEAVED 0x00000100
-#define AVIF_WASCAPTUREFILE 0x00010000
-#define AVIF_COPYRIGHTED 0x00020000
-
-
-//static char g_zeroes[ PADDING_SIZE ];
-
-/** The constructor
-
- \todo mainHdr not initialized
- \todo add checking for NULL pointers
-
-*/
-
-AVIFile::AVIFile() : RIFFFile(),
- idx1( NULL ), file_list( -1 ), riff_list( -1 ),
- hdrl_list( -1 ), avih_chunk( -1 ), movi_list( -1 ), junk_chunk( -1 ), idx1_chunk( -1 ),
- index_type( -1 ), current_ix00( -1 ), odml_list( -1 ), dmlh_chunk( -1 ), isUpdateIdx1( true )
-{
- // cerr << "0x" << hex << (long)this << dec << " AVIFile::AVIFile() : RIFFFile(), ..." << endl;
-
- for ( int i = 0; i < 2; ++i )
- {
- indx[ i ] = new AVISuperIndex;
- memset( indx[ i ], 0, sizeof( AVISuperIndex ) );
- ix[ i ] = new AVIStdIndex;
- memset( ix[ i ], 0, sizeof( AVIStdIndex ) );
- indx_chunk[ i ] = -1;
- ix_chunk[ i ] = -1;
- strl_list[ i ] = -1;
- strh_chunk[ i ] = -1;
- strf_chunk[ i ] = -1;
- }
- idx1 = new AVISimpleIndex;
- memset( idx1, 0, sizeof( AVISimpleIndex ) );
-}
-
-
-/** The copy constructor
-
- \todo add checking for NULL pointers
-
-*/
-
-AVIFile::AVIFile( const AVIFile& avi ) : RIFFFile( avi )
-{
- // cerr << "0x" << hex << (long)this << dec << " 0x" << hex << (long)&avi << dec << " AVIFile::AVIFile(const AVIFile& avi) : RIFFFile(avi)" << endl;
-
- mainHdr = avi.mainHdr;
- idx1 = new AVISimpleIndex;
- *idx1 = *avi.idx1;
- file_list = avi.file_list;
- riff_list = avi.riff_list;
- hdrl_list = avi.hdrl_list;
- avih_chunk = avi.avih_chunk;
- movi_list = avi.movi_list;
- junk_chunk = avi.junk_chunk;
- idx1_chunk = avi.idx1_chunk;
-
- for ( int i = 0; i < 2; ++i )
- {
- indx[ i ] = new AVISuperIndex;
- *indx[ i ] = *avi.indx[ i ];
- ix[ i ] = new AVIStdIndex;
- *ix[ i ] = *avi.ix[ i ];
- indx_chunk[ i ] = avi.indx_chunk[ i ];
- ix_chunk[ i ] = avi.ix_chunk[ i ];
- strl_list[ i ] = avi.strl_list[ i ];
- strh_chunk[ i ] = avi.strh_chunk[ i ];
- strf_chunk[ i ] = avi.strf_chunk[ i ];
- }
-
- index_type = avi.index_type;
- current_ix00 = avi.current_ix00;
-
- for ( int i = 0; i < 62; ++i )
- dmlh[ i ] = avi.dmlh[ i ];
-
- isUpdateIdx1 = avi.isUpdateIdx1;
-
-}
-
-
-/** The assignment operator
-
-*/
-
-AVIFile& AVIFile::operator=( const AVIFile& avi )
-{
- // cerr << "0x" << hex << (long)this << dec << " 0x" << hex << (long)&avi << dec << " AVIFile& AVIFile::operator=(const AVIFile& avi)" << endl;
-
- if ( this != &avi )
- {
- RIFFFile::operator=( avi );
- mainHdr = avi.mainHdr;
- *idx1 = *avi.idx1;
- file_list = avi.file_list;
- riff_list = avi.riff_list;
- hdrl_list = avi.hdrl_list;
- avih_chunk = avi.avih_chunk;
- movi_list = avi.movi_list;
- junk_chunk = avi.junk_chunk;
- idx1_chunk = avi.idx1_chunk;
-
- for ( int i = 0; i < 2; ++i )
- {
- *indx[ i ] = *avi.indx[ i ];
- *ix[ i ] = *avi.ix[ i ];
- indx_chunk[ i ] = avi.indx_chunk[ i ];
- ix_chunk[ i ] = avi.ix_chunk[ i ];
- strl_list[ i ] = avi.strl_list[ i ];
- strh_chunk[ i ] = avi.strh_chunk[ i ];
- strf_chunk[ i ] = avi.strf_chunk[ i ];
- }
-
- index_type = avi.index_type;
- current_ix00 = avi.current_ix00;
-
- for ( int i = 0; i < 62; ++i )
- dmlh[ i ] = avi.dmlh[ i ];
-
- isUpdateIdx1 = avi.isUpdateIdx1;
- }
- return *this;
-}
-
-
-/** The destructor
-
-*/
-
-AVIFile::~AVIFile()
-{
- // cerr << "0x" << hex << (long)this << dec << " AVIFile::~AVIFile()" << endl;
-
- for ( int i = 0; i < 2; ++i )
- {
- delete ix[ i ];
- delete indx[ i ];
- }
- delete idx1;
-}
-
-/** Initialize the AVI structure to its initial state, either for PAL or NTSC format
-
- Initialize the AVIFile attributes: mainHdr, indx, ix00, idx1
-
- \todo consolidate AVIFile::Init, AVI1File::Init, AVI2File::Init. They are somewhat redundant.
- \param format pass AVI_PAL or AVI_NTSC
- \param sampleFrequency the sample frequency of the audio content
- \param indexType pass AVI_SMALL_INDEX or AVI_LARGE_INDEX
-
-*/
-
-void AVIFile::Init( int format, int sampleFrequency, int indexType )
-{
- int i, j;
-
- assert( ( format == AVI_PAL ) || ( format == AVI_NTSC ) );
-
- index_type = indexType;
-
- switch ( format )
- {
- case AVI_PAL:
- mainHdr.dwMicroSecPerFrame = 40000;
- mainHdr.dwSuggestedBufferSize = 144008;
- break;
-
- case AVI_NTSC:
- mainHdr.dwMicroSecPerFrame = 33366;
- mainHdr.dwSuggestedBufferSize = 120008;
- break;
-
- default: /* no default allowed */
- assert( 0 );
- break;
- }
-
- /* Initialize the 'avih' chunk */
-
- mainHdr.dwMaxBytesPerSec = 3600000 + sampleFrequency * 4;
- mainHdr.dwPaddingGranularity = PADDING_SIZE;
- mainHdr.dwFlags = AVIF_TRUSTCKTYPE;
- if ( indexType & AVI_SMALL_INDEX )
- mainHdr.dwFlags |= AVIF_HASINDEX;
- mainHdr.dwTotalFrames = 0;
- mainHdr.dwInitialFrames = 0;
- mainHdr.dwStreams = 1;
- mainHdr.dwWidth = 0;
- mainHdr.dwHeight = 0;
- mainHdr.dwReserved[ 0 ] = 0;
- mainHdr.dwReserved[ 1 ] = 0;
- mainHdr.dwReserved[ 2 ] = 0;
- mainHdr.dwReserved[ 3 ] = 0;
-
- /* Initialize the 'idx1' chunk */
-
- for ( int i = 0; i < 8000; ++i )
- {
- idx1->aIndex[ i ].dwChunkId = 0;
- idx1->aIndex[ i ].dwFlags = 0;
- idx1->aIndex[ i ].dwOffset = 0;
- idx1->aIndex[ i ].dwSize = 0;
- }
- idx1->nEntriesInUse = 0;
-
- /* Initialize the 'indx' chunk */
-
- for ( i = 0; i < 2; ++i )
- {
- indx[ i ] ->wLongsPerEntry = 4;
- indx[ i ] ->bIndexSubType = 0;
- indx[ i ] ->bIndexType = KINO_AVI_INDEX_OF_INDEXES;
- indx[ i ] ->nEntriesInUse = 0;
- indx[ i ] ->dwReserved[ 0 ] = 0;
- indx[ i ] ->dwReserved[ 1 ] = 0;
- indx[ i ] ->dwReserved[ 2 ] = 0;
- for ( j = 0; j < 2014; ++j )
- {
- indx[ i ] ->aIndex[ j ].qwOffset = 0;
- indx[ i ] ->aIndex[ j ].dwSize = 0;
- indx[ i ] ->aIndex[ j ].dwDuration = 0;
- }
- }
-
- /* The ix00 and ix01 chunk will be added dynamically in avi_write_frame
- as needed */
-
- /* Initialize the 'dmlh' chunk. I have no clue what this means
- though */
-
- for ( i = 0; i < 62; ++i )
- dmlh[ i ] = 0;
- //dmlh[0] = -1; /* frame count + 1? */
-
-}
-
-
-/** Find position and size of a given frame in the file
-
- Depending on which index is available, search one of them to
- find position and frame size
-
- \todo the size parameter is redundant. All frames have the same size, which is also in the mainHdr.
- \todo all index related operations should be isolated
- \param offset the file offset to the start of the frame
- \param size the size of the frame
- \param frameNum the number of the frame we wish to find
- \return 0 if the frame could be found, -1 otherwise
-*/
-
-int AVIFile::GetDVFrameInfo( off_t &offset, int &size, int frameNum )
-{
- switch ( index_type )
- {
- case AVI_LARGE_INDEX:
-
- /* find relevant index in indx0 */
-
- int i;
-
- for ( i = 0; frameNum >= indx[ 0 ] ->aIndex[ i ].dwDuration; frameNum -= indx[ 0 ] ->aIndex[ i ].dwDuration, ++i )
- ;
-
- if ( i != current_ix00 )
- {
- fail_if( lseek( fd, indx[ 0 ] ->aIndex[ i ].qwOffset + RIFF_HEADERSIZE, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, ix[ 0 ], indx[ 0 ] ->aIndex[ i ].dwSize - RIFF_HEADERSIZE ) );
- current_ix00 = i;
- }
-
- if ( frameNum < ix[ 0 ] ->nEntriesInUse )
- {
- offset = ix[ 0 ] ->qwBaseOffset + ix[ 0 ] ->aIndex[ frameNum ].dwOffset;
- size = ix[ 0 ] ->aIndex[ frameNum ].dwSize;
- return 0;
- }
- else
- return -1;
- break;
-
- case AVI_SMALL_INDEX:
- int index = -1;
- int frameNumIndex = 0;
- for ( int i = 0; i < idx1->nEntriesInUse; ++i )
- {
- FOURCC chunkID1 = make_fourcc( "00dc" );
- FOURCC chunkID2 = make_fourcc( "00db" );
- if ( idx1->aIndex[ i ].dwChunkId == chunkID1 ||
- idx1->aIndex[ i ].dwChunkId == chunkID2 )
- {
- if ( frameNumIndex == frameNum )
- {
- index = i;
- break;
- }
- ++frameNumIndex;
- }
- }
- if ( index != -1 )
- {
- // compatibility check for broken dvgrab dv2 format
- if ( idx1->aIndex[ 0 ].dwOffset > GetDirectoryEntry( movi_list ).offset )
- {
- offset = idx1->aIndex[ index ].dwOffset + RIFF_HEADERSIZE;
- }
- else
- {
- // new, correct dv2 format
- offset = idx1->aIndex[ index ].dwOffset + RIFF_HEADERSIZE + GetDirectoryEntry( movi_list ).offset;
- }
- size = idx1->aIndex[ index ].dwSize;
- return 0;
- }
- else
- return -1;
- break;
- }
- return -1;
-}
-
-/** Find position and size of a given frame in the file
-
- Depending on which index is available, search one of them to
- find position and frame size
-
- \todo the size parameter is redundant. All frames have the same size, which is also in the mainHdr.
- \todo all index related operations should be isolated
- \param offset the file offset to the start of the frame
- \param size the size of the frame
- \param frameNum the number of the frame we wish to find
- \param chunkID the ID of the type of chunk we want
- \return 0 if the frame could be found, -1 otherwise
-*/
-
-int AVIFile::GetFrameInfo( off_t &offset, int &size, int frameNum, FOURCC chunkID )
-{
- if ( index_type & AVI_LARGE_INDEX )
- {
- int i;
-
- for ( i = 0; frameNum >= indx[ 0 ] ->aIndex[ i ].dwDuration; frameNum -= indx[ 0 ] ->aIndex[ i ].dwDuration, ++i )
- ;
-
- if ( i != current_ix00 )
- {
- fail_if( lseek( fd, indx[ 0 ] ->aIndex[ i ].qwOffset + RIFF_HEADERSIZE, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, ix[ 0 ], indx[ 0 ] ->aIndex[ i ].dwSize - RIFF_HEADERSIZE ) );
- current_ix00 = i;
- }
-
- if ( frameNum < ix[ 0 ] ->nEntriesInUse )
- {
- if ( ( FOURCC ) ix[ 0 ] ->dwChunkId == chunkID )
- {
- offset = ix[ 0 ] ->qwBaseOffset + ix[ 0 ] ->aIndex[ frameNum ].dwOffset;
- size = ix[ 0 ] ->aIndex[ frameNum ].dwSize;
- return 0;
- }
- }
- }
- if ( index_type & AVI_SMALL_INDEX )
- {
- int index = -1;
- int frameNumIndex = 0;
- for ( int i = 0; i < idx1->nEntriesInUse; ++i )
- {
- if ( idx1->aIndex[ i ].dwChunkId == chunkID )
- {
- if ( frameNumIndex == frameNum )
- {
- index = i;
- break;
- }
- ++frameNumIndex;
- }
- }
- if ( index != -1 )
- {
- // compatibility check for broken dvgrab dv2 format
- if ( idx1->aIndex[ 0 ].dwOffset > GetDirectoryEntry( movi_list ).offset )
- {
- offset = idx1->aIndex[ index ].dwOffset + RIFF_HEADERSIZE;
- }
- else
- {
- // new, correct dv2 format
- offset = idx1->aIndex[ index ].dwOffset + RIFF_HEADERSIZE + GetDirectoryEntry( movi_list ).offset;
- }
- size = idx1->aIndex[ index ].dwSize;
- return 0;
- }
- }
- return -1;
-}
-
-/** Read in a frame
-
- \todo we actually don't need the frame here, we could use just a void pointer
- \param frame a reference to the frame object that will receive the frame data
- \param frameNum the frame number to read
- \return 0 if the frame could be read, -1 otherwise
-*/
-
-int AVIFile::GetDVFrame( uint8_t *data, int frameNum )
-{
- off_t offset;
- int size;
-
- if ( GetDVFrameInfo( offset, size, frameNum ) != 0 || size < 0 )
- return -1;
- pthread_mutex_lock( &file_mutex );
- fail_if( lseek( fd, offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, data, size ) );
- pthread_mutex_unlock( &file_mutex );
-
- return 0;
-}
-
-/** Read in a frame
-
- \param data a pointer to the audio buffer
- \param frameNum the frame number to read
- \param chunkID the ID of the type of chunk we want
- \return the size the of the frame data, 0 if could not be read
-*/
-
-int AVIFile::getFrame( void *data, int frameNum, FOURCC chunkID )
-{
- off_t offset;
- int size;
-
- if ( GetFrameInfo( offset, size, frameNum, chunkID ) != 0 )
- return 0;
- fail_if( lseek( fd, offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, data, size ) );
-
- return size;
-}
-
-int AVIFile::GetTotalFrames() const
-{
- return mainHdr.dwTotalFrames;
-}
-
-
-/** prints out a directory entry in text form
-
- Every subclass of RIFFFile is supposed to override this function
- and to implement it for the entry types it knows about. For all
- other entry types it should call its parent::PrintDirectoryData.
-
- \todo use 64 bit routines
- \param entry the entry to print
-*/
-
-void AVIFile::PrintDirectoryEntryData( const RIFFDirEntry &entry ) const
-{
- static FOURCC lastStreamType = make_fourcc( " " );
-
- if ( entry.type == make_fourcc( "avih" ) )
- {
-
- int i;
- MainAVIHeader main_avi_header;
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &main_avi_header, sizeof( MainAVIHeader ) ) );
-
- cout << " dwMicroSecPerFrame: " << ( int ) main_avi_header.dwMicroSecPerFrame << endl
- << " dwMaxBytesPerSec: " << ( int ) main_avi_header.dwMaxBytesPerSec << endl
- << " dwPaddingGranularity: " << ( int ) main_avi_header.dwPaddingGranularity << endl
- << " dwFlags: " << ( int ) main_avi_header.dwFlags << endl
- << " dwTotalFrames: " << ( int ) main_avi_header.dwTotalFrames << endl
- << " dwInitialFrames: " << ( int ) main_avi_header.dwInitialFrames << endl
- << " dwStreams: " << ( int ) main_avi_header.dwStreams << endl
- << " dwSuggestedBufferSize: " << ( int ) main_avi_header.dwSuggestedBufferSize << endl
- << " dwWidth: " << ( int ) main_avi_header.dwWidth << endl
- << " dwHeight: " << ( int ) main_avi_header.dwHeight << endl;
- for ( i = 0; i < 4; ++i )
- cout << " dwReserved[" << i << "]: " << ( int ) main_avi_header.dwReserved[ i ] << endl;
-
- }
- else if ( entry.type == make_fourcc( "strh" ) )
- {
-
- AVIStreamHeader avi_stream_header;
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &avi_stream_header, sizeof( AVIStreamHeader ) ) );
-
- lastStreamType = avi_stream_header.fccType;
-
- cout << " fccType: '"
- << ((char *)&avi_stream_header.fccType)[0]
- << ((char *)&avi_stream_header.fccType)[1]
- << ((char *)&avi_stream_header.fccType)[2]
- << ((char *)&avi_stream_header.fccType)[3]
- << '\'' << endl
- << " fccHandler: '"
- << ((char *)&avi_stream_header.fccHandler)[0]
- << ((char *)&avi_stream_header.fccHandler)[1]
- << ((char *)&avi_stream_header.fccHandler)[2]
- << ((char *)&avi_stream_header.fccHandler)[3]
- << '\'' << endl
- << " dwFlags: " << ( int ) avi_stream_header.dwFlags << endl
- << " wPriority: " << ( int ) avi_stream_header.wPriority << endl
- << " wLanguage: " << ( int ) avi_stream_header.wLanguage << endl
- << " dwInitialFrames: " << ( int ) avi_stream_header.dwInitialFrames << endl
- << " dwScale: " << ( int ) avi_stream_header.dwScale << endl
- << " dwRate: " << ( int ) avi_stream_header.dwRate << endl
- << " dwLength: " << ( int ) avi_stream_header.dwLength << endl
- << " dwQuality: " << ( int ) avi_stream_header.dwQuality << endl
- << " dwSampleSize: " << ( int ) avi_stream_header.dwSampleSize << endl;
-
- }
- else if ( entry.type == make_fourcc( "indx" ) )
- {
-
- int i;
- AVISuperIndex avi_super_index;
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &avi_super_index, sizeof( AVISuperIndex ) ) );
-
- cout << " wLongsPerEntry: " << ( int ) avi_super_index.wLongsPerEntry
- << endl
- << " bIndexSubType: " << ( int ) avi_super_index.bIndexSubType << endl
- << " bIndexType: " << ( int ) avi_super_index.bIndexType << endl
- << " nEntriesInUse: " << ( int ) avi_super_index.nEntriesInUse << endl
- << " dwChunkId: '"
- << ((char *)&avi_super_index.dwChunkId)[0]
- << ((char *)&avi_super_index.dwChunkId)[1]
- << ((char *)&avi_super_index.dwChunkId)[2]
- << ((char *)&avi_super_index.dwChunkId)[3]
- << '\'' << endl
- << " dwReserved[0]: " << ( int ) avi_super_index.dwReserved[ 0 ] << endl
- << " dwReserved[1]: " << ( int ) avi_super_index.dwReserved[ 1 ] << endl
- << " dwReserved[2]: " << ( int ) avi_super_index.dwReserved[ 2 ] << endl;
- for ( i = 0; i < avi_super_index.nEntriesInUse; ++i )
- {
- cout << ' ' << setw( 4 ) << setfill( ' ' ) << i
- << ": qwOffset : 0x" << setw( 12 ) << setfill( '0' ) << hex << avi_super_index.aIndex[ i ].qwOffset << endl
- << " dwSize : 0x" << setw( 8 ) << avi_super_index.aIndex[ i ].dwSize << endl
- << " dwDuration : " << dec << avi_super_index.aIndex[ i ].dwDuration << endl;
- }
- }
- else if ( entry.type == make_fourcc( "strf" ) )
- {
- if ( lastStreamType == make_fourcc( "auds" ) )
- {
- WAVEFORMATEX waveformatex;
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &waveformatex, sizeof( WAVEFORMATEX ) ) );
- cout << " waveformatex.wFormatTag : " << waveformatex.wFormatTag << endl;
- cout << " waveformatex.nChannels : " << waveformatex.nChannels << endl;
- cout << " waveformatex.nSamplesPerSec : " << waveformatex.nSamplesPerSec << endl;
- cout << " waveformatex.nAvgBytesPerSec: " << waveformatex.nAvgBytesPerSec << endl;
- cout << " waveformatex.nBlockAlign : " << waveformatex.nBlockAlign << endl;
- cout << " waveformatex.wBitsPerSample : " << waveformatex.wBitsPerSample << endl;
- cout << " waveformatex.cbSize : " << waveformatex.cbSize << endl;
- }
- else if ( lastStreamType == make_fourcc( "vids" ) )
- {
- BITMAPINFOHEADER bitmapinfo;
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &bitmapinfo, sizeof( BITMAPINFOHEADER ) ) );
- cout << " bitmapinfo.biSize : " << bitmapinfo.biSize << endl;
- cout << " bitmapinfo.biWidth : " << bitmapinfo.biWidth << endl;
- cout << " bitmapinfo.biHeight : " << bitmapinfo.biHeight << endl;
- cout << " bitmapinfo.biPlanes : " << bitmapinfo.biPlanes << endl;
- cout << " bitmapinfo.biBitCount : " << bitmapinfo.biBitCount << endl;
- cout << " bitmapinfo.biCompression : " << bitmapinfo.biCompression << endl;
- cout << " bitmapinfo.biSizeImage : " << bitmapinfo.biSizeImage << endl;
- cout << " bitmapinfo.biXPelsPerMeter: " << bitmapinfo.biXPelsPerMeter << endl;
- cout << " bitmapinfo.biYPelsPerMeter: " << bitmapinfo.biYPelsPerMeter << endl;
- cout << " bitmapinfo.biClrUsed : " << bitmapinfo.biClrUsed << endl;
- cout << " bitmapinfo.biClrImportant : " << bitmapinfo.biClrImportant << endl;
- }
- else if ( lastStreamType == make_fourcc( "iavs" ) )
- {
- DVINFO dvinfo;
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &dvinfo, sizeof( DVINFO ) ) );
- cout << " dvinfo.dwDVAAuxSrc : 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVAAuxSrc << endl;
- cout << " dvinfo.dwDVAAuxCtl : 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVAAuxCtl << endl;
- cout << " dvinfo.dwDVAAuxSrc1: 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVAAuxSrc1 << endl;
- cout << " dvinfo.dwDVAAuxCtl1: 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVAAuxCtl1 << endl;
- cout << " dvinfo.dwDVVAuxSrc : 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVVAuxSrc << endl;
- cout << " dvinfo.dwDVVAuxCtl : 0x" << setw( 8 ) << setfill( '0' ) << hex << dvinfo.dwDVVAuxCtl << endl;
- }
- }
-
- /* This is the Standard Index. It is an array of offsets and
- sizes relative to some start offset. */
-
- else if ( ( entry.type == make_fourcc( "ix00" ) ) || ( entry.type == make_fourcc( "ix01" ) ) )
- {
-
- int i;
- AVIStdIndex avi_std_index;
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, &avi_std_index, sizeof( AVIStdIndex ) ) );
-
- cout << " wLongsPerEntry: " << ( int ) avi_std_index.wLongsPerEntry
- << endl
- << " bIndexSubType: " << ( int ) avi_std_index.bIndexSubType << endl
- << " bIndexType: " << ( int ) avi_std_index.bIndexType << endl
- << " nEntriesInUse: " << ( int ) avi_std_index.nEntriesInUse << endl
- << " dwChunkId: '"
- << ((char *)&avi_std_index.dwChunkId)[0]
- << ((char *)&avi_std_index.dwChunkId)[1]
- << ((char *)&avi_std_index.dwChunkId)[2]
- << ((char *)&avi_std_index.dwChunkId)[3]
- << '\'' << endl
- << " qwBaseOffset: 0x" << setw( 12 ) << hex << avi_std_index.qwBaseOffset << endl
- << " dwReserved: " << dec << ( int ) avi_std_index.dwReserved << endl;
- for ( i = 0; i < avi_std_index.nEntriesInUse; ++i )
- {
- cout << ' ' << setw( 4 ) << setfill( ' ' ) << i
- << ": dwOffset : 0x" << setw( 8 ) << setfill( '0' ) << hex << avi_std_index.aIndex[ i ].dwOffset
- << " (0x" << setw( 12 ) << avi_std_index.qwBaseOffset + avi_std_index.aIndex[ i ].dwOffset << ')' << endl
- << " dwSize : 0x" << setw( 8 ) << avi_std_index.aIndex[ i ].dwSize << dec << endl;
- }
-
- }
- else if ( entry.type == make_fourcc( "idx1" ) )
- {
-
- int i;
- int numEntries = entry.length / sizeof( int ) / 4;
- DWORD *idx1 = new DWORD[ numEntries * 4 ];
- // FOURCC movi_list = FindDirectoryEntry(make_fourcc("movi"));
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, idx1, entry.length ) );
-
- for ( i = 0; i < numEntries; ++i )
- {
-
- cout << ' ' << setw( 4 ) << setfill( ' ' ) << i << setfill( '0' ) << ": dwChunkId : '"
- << ((char *)&idx1[ i * 4 + 0 ])[0]
- << ((char *)&idx1[ i * 4 + 0 ])[1]
- << ((char *)&idx1[ i * 4 + 0 ])[2]
- << ((char *)&idx1[ i * 4 + 0 ])[3]
- << '\'' << endl
- << " dwType : 0x" << setw( 8 ) << hex << idx1[ i * 4 + 1 ] << endl
- << " dwOffset : 0x" << setw( 8 ) << idx1[ i * 4 + 2 ] << endl
- // << " (0x" << setw(8) << idx1[i * 4 + 2] + GetDirectoryEntry(movi_list).offset << ')' << endl
- << " dwSize : 0x" << setw( 8 ) << idx1[ i * 4 + 3 ] << dec << endl;
- }
-
- delete[] idx1;
- }
- else if ( entry.type == make_fourcc( "dmlh" ) )
- {
- int i;
- int numEntries = entry.length / sizeof( int );
- DWORD *dmlh = new DWORD[ numEntries ];
-
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, dmlh, entry.length ) );
-
- for ( i = 0; i < numEntries; ++i )
- {
- cout << ' ' << setw( 4 ) << setfill( ' ' ) << i << setfill( '0' ) << ": "
- << " dwTotalFrames: 0x" << setw( 8 ) << hex << dmlh[ i ]
- << " (" << dec << dmlh[ i ] << ")" << endl;
- }
- delete[] dmlh;
- }
-}
-
-
-/** If this is not a movi list, read its contents
-
-*/
-
-void AVIFile::ParseList( int parent )
-{
- FOURCC type;
- FOURCC name;
- DWORD length;
- int list;
- off_t pos;
- off_t listEnd;
-
- /* Read in the chunk header (type and length). */
- fail_neg( read( fd, &type, sizeof( type ) ) );
- fail_neg( read( fd, &length, sizeof( length ) ) );
- if ( length & 1 )
- length++;
-
- /* The contents of the list starts here. Obtain its offset. The list
- name (4 bytes) is already part of the contents). */
-
- pos = lseek( fd, 0, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- fail_neg( read( fd, &name, sizeof( name ) ) );
-
- /* if we encounter a movi list, do not read it. It takes too much time
- and we don't need it anyway. */
-
- if ( name != make_fourcc( "movi" ) )
- {
- // if (1) {
-
- /* Add an entry for this list. */
- list = AddDirectoryEntry( type, name, sizeof( name ), parent );
-
- /* Read in any chunks contained in this list. This list is the
- parent for all chunks it contains. */
-
- listEnd = pos + length;
- while ( pos < listEnd )
- {
- ParseChunk( list );
- pos = lseek( fd, 0, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- }
- }
- else
- {
- /* Add an entry for this list. */
-
- movi_list = AddDirectoryEntry( type, name, length, parent );
-
- pos = lseek( fd, length - 4, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- }
-}
-
-
-void AVIFile::ParseRIFF()
-{
- RIFFFile::ParseRIFF();
-
- avih_chunk = FindDirectoryEntry( make_fourcc( "avih" ) );
- if ( avih_chunk != -1 )
- ReadChunk( avih_chunk, ( void* ) & mainHdr, sizeof( MainAVIHeader ) );
-}
-
-
-void AVIFile::ReadIndex()
-{
- indx_chunk[ 0 ] = FindDirectoryEntry( make_fourcc( "indx" ) );
- if ( indx_chunk[ 0 ] != -1 )
- {
- ReadChunk( indx_chunk[ 0 ], ( void* ) indx[ 0 ], sizeof( AVISuperIndex ) );
- index_type = AVI_LARGE_INDEX;
-
- /* recalc number of frames from each index */
- mainHdr.dwTotalFrames = 0;
- for ( int i = 0;
- i < indx[ 0 ] ->nEntriesInUse;
- mainHdr.dwTotalFrames += indx[ 0 ] ->aIndex[ i++ ].dwDuration )
- ;
- return ;
- }
- idx1_chunk = FindDirectoryEntry( make_fourcc( "idx1" ) );
- if ( idx1_chunk != -1 )
- {
- ReadChunk( idx1_chunk, ( void* ) idx1, sizeof( AVISuperIndex ) );
- idx1->nEntriesInUse = GetDirectoryEntry( idx1_chunk ).length / 16;
- index_type = AVI_SMALL_INDEX;
-
- /* recalc number of frames from the simple index */
- int frameNumIndex = 0;
- FOURCC chunkID1 = make_fourcc( "00dc" );
- FOURCC chunkID2 = make_fourcc( "00db" );
- for ( int i = 0; i < idx1->nEntriesInUse; ++i )
- {
- if ( idx1->aIndex[ i ].dwChunkId == chunkID1 ||
- idx1->aIndex[ i ].dwChunkId == chunkID2 )
- {
- ++frameNumIndex;
- }
- }
- mainHdr.dwTotalFrames = frameNumIndex;
- return ;
- }
-}
-
-
-void AVIFile::FlushIndx( int stream )
-{
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
- int i;
-
- /* Write out the previous index. When this function is
- entered for the first time, there is no index to
- write. Note: this may be an expensive operation
- because of a time consuming seek to the former file
- position. */
-
- if ( ix_chunk[ stream ] != -1 )
- WriteChunk( ix_chunk[ stream ], ix[ stream ] );
-
- /* make a new ix chunk. */
-
- if ( stream == 0 )
- type = make_fourcc( "ix00" );
- else
- type = make_fourcc( "ix01" );
- ix_chunk[ stream ] = AddDirectoryEntry( type, 0, sizeof( AVIStdIndex ), movi_list );
- GetDirectoryEntry( ix_chunk[ stream ], type, name, length, offset, parent );
-
- /* fill out all required fields. The offsets in the
- array are relative to qwBaseOffset, so fill in the
- offset to the next free location in the file
- there. */
-
- ix[ stream ] ->wLongsPerEntry = 2;
- ix[ stream ] ->bIndexSubType = 0;
- ix[ stream ] ->bIndexType = KINO_AVI_INDEX_OF_CHUNKS;
- ix[ stream ] ->nEntriesInUse = 0;
- ix[ stream ] ->dwChunkId = indx[ stream ] ->dwChunkId;
- ix[ stream ] ->qwBaseOffset = offset + length;
- ix[ stream ] ->dwReserved = 0;
-
- for ( i = 0; i < IX00_INDEX_SIZE; ++i )
- {
- ix[ stream ] ->aIndex[ i ].dwOffset = 0;
- ix[ stream ] ->aIndex[ i ].dwSize = 0;
- }
-
- /* add a reference to this new index in our super
- index. */
-
- i = indx[ stream ] ->nEntriesInUse++;
- indx[ stream ] ->aIndex[ i ].qwOffset = offset - RIFF_HEADERSIZE;
- indx[ stream ] ->aIndex[ i ].dwSize = length + RIFF_HEADERSIZE;
- indx[ stream ] ->aIndex[ i ].dwDuration = 0;
-}
-
-
-void AVIFile::UpdateIndx( int stream, int chunk, int duration )
-{
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
- int i;
-
- /* update the appropiate entry in the super index. It reflects
- the number of frames in the referenced index. */
-
- i = indx[ stream ] ->nEntriesInUse - 1;
- indx[ stream ] ->aIndex[ i ].dwDuration += duration;
-
- /* update the standard index. Calculate the file position of
- the new frame. */
-
- GetDirectoryEntry( chunk, type, name, length, offset, parent );
-
- indx[ stream ] ->dwChunkId = type;
- i = ix[ stream ] ->nEntriesInUse++;
- ix[ stream ] ->aIndex[ i ].dwOffset = offset - ix[ stream ] ->qwBaseOffset;
- ix[ stream ] ->aIndex[ i ].dwSize = length;
-}
-
-
-void AVIFile::UpdateIdx1( int chunk, int flags )
-{
- if ( idx1->nEntriesInUse < 20000 )
- {
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
-
- GetDirectoryEntry( chunk, type, name, length, offset, parent );
-
- idx1->aIndex[ idx1->nEntriesInUse ].dwChunkId = type;
- idx1->aIndex[ idx1->nEntriesInUse ].dwFlags = flags;
- idx1->aIndex[ idx1->nEntriesInUse ].dwOffset = offset - GetDirectoryEntry( movi_list ).offset - RIFF_HEADERSIZE;
- idx1->aIndex[ idx1->nEntriesInUse ].dwSize = length;
- idx1->nEntriesInUse++;
- }
-}
-
-bool AVIFile::verifyStreamFormat( FOURCC type )
-{
- int i, j = 0;
- AVIStreamHeader avi_stream_header;
- BITMAPINFOHEADER bih;
- FOURCC strh = make_fourcc( "strh" );
- FOURCC strf = make_fourcc( "strf" );
-
- while ( ( i = FindDirectoryEntry( strh, j++ ) ) != -1 )
- {
- ReadChunk( i, ( void* ) & avi_stream_header, sizeof( AVIStreamHeader ) );
- if ( avi_stream_header.fccHandler == type )
- return true;
- }
- j = 0;
- while ( ( i = FindDirectoryEntry( strf, j++ ) ) != -1 )
- {
- ReadChunk( i, ( void* ) & bih, sizeof( BITMAPINFOHEADER ) );
- if ( ( FOURCC ) bih.biCompression == type )
- return true;
- }
-
- return false;
-}
-
-bool AVIFile::verifyStream( FOURCC type )
-{
- int i, j = 0;
- AVIStreamHeader avi_stream_header;
- FOURCC strh = make_fourcc( "strh" );
-
- while ( ( i = FindDirectoryEntry( strh, j++ ) ) != -1 )
- {
- ReadChunk( i, ( void* ) & avi_stream_header, sizeof( AVIStreamHeader ) );
- if ( avi_stream_header.fccType == type )
- return true;
- }
- return false;
-}
-
-bool AVIFile::isOpenDML( void )
-{
- int i, j = 0;
- FOURCC dmlh = make_fourcc( "dmlh" );
-
- while ( ( i = FindDirectoryEntry( dmlh, j++ ) ) != -1 )
- {
- return true;
- }
- return false;
-}
-
-AVI1File::AVI1File() : AVIFile()
-{}
-
-
-AVI1File::~AVI1File()
-{}
-
-
-/* Initialize the AVI structure to its initial state, either for PAL
- or NTSC format */
-
-void AVI1File::Init( int format, int sampleFrequency, int indexType )
-{
- int num_blocks;
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
-
- assert( ( format == AVI_PAL ) || ( format == AVI_NTSC ) );
-
- AVIFile::Init( format, sampleFrequency, indexType );
-
- switch ( format )
- {
- case AVI_PAL:
- mainHdr.dwWidth = 720;
- mainHdr.dwHeight = 576;
-
- streamHdr[ 0 ].dwScale = 1;
- streamHdr[ 0 ].dwRate = 25;
- streamHdr[ 0 ].dwSuggestedBufferSize = 144008;
-
- /* initialize the 'strf' chunk */
-
- /* Meaning of the DV stream format chunk per Microsoft
- dwDVAAuxSrc
- Specifies the Audio Auxiliary Data Source Pack for the first audio block
- (first 5 DV DIF sequences for 525-60 systems or 6 DV DIF sequences for 625-50 systems) of
- a frame. A DIF sequence is a data block that contains 150 DIF blocks. A DIF block consists
- of 80 bytes. The Audio Auxiliary Data Source Pack is defined in section D.7.1 of Part 2,
- Annex D, "The Pack Header Table and Contents of Packs" of the Specification of
- Consumer-use Digital VCRs.
- dwDVAAuxCtl
- Specifies the Audio Auxiliary Data Source Control Pack for the first audio block of a
- frame. The Audio Auxiliary Data Control Pack is defined in section D.7.2 of Part 2,
- Annex D, "The Pack Header Table and Contents of Packs" of the Specification of
- Consumer-use Digital VCRs.
- dwDVAAuxSrc1
- Specifies the Audio Auxiliary Data Source Pack for the second audio block
- (second 5 DV DIF sequences for 525-60 systems or 6 DV DIF sequences for 625-50 systems) of a frame.
- dwDVAAuxCtl1
- Specifies the Audio Auxiliary Data Source Control Pack for the second audio block of a frame.
- dwDVVAuxSrc
- Specifies the Video Auxiliary Data Source Pack as defined in section D.8.1 of Part 2,
- Annex D, "The Pack Header Table and Contents of Packs" of the Specification of
- Consumer-use Digital VCRs.
- dwDVVAuxCtl
- Specifies the Video Auxiliary Data Source Control Pack as defined in section D.8.2 of Part 2,
- Annex D, "The Pack Header Table and Contents of Packs" of the Specification of
- Consumer-use Digital VCRs.
- dwDVReserved[2]
- Reserved. Set this array to zero.
- */
-
- dvinfo.dwDVAAuxSrc = 0xd1e030d0;
- dvinfo.dwDVAAuxCtl = 0xffa0cf3f;
- dvinfo.dwDVAAuxSrc1 = 0xd1e03fd0;
- dvinfo.dwDVAAuxCtl1 = 0xffa0cf3f;
- dvinfo.dwDVVAuxSrc = 0xff20ffff;
- dvinfo.dwDVVAuxCtl = 0xfffdc83f;
- dvinfo.dwDVReserved[ 0 ] = 0;
- dvinfo.dwDVReserved[ 1 ] = 0;
- break;
-
- case AVI_NTSC:
- mainHdr.dwWidth = 720;
- mainHdr.dwHeight = 480;
-
- streamHdr[ 0 ].dwScale = 1001;
- streamHdr[ 0 ].dwRate = 30000;
- streamHdr[ 0 ].dwSuggestedBufferSize = 120008;
-
- /* initialize the 'strf' chunk */
- dvinfo.dwDVAAuxSrc = 0xc0c000c0;
- dvinfo.dwDVAAuxCtl = 0xffa0cf3f;
- dvinfo.dwDVAAuxSrc1 = 0xc0c001c0;
- dvinfo.dwDVAAuxCtl1 = 0xffa0cf3f;
- dvinfo.dwDVVAuxSrc = 0xff80ffff;
- dvinfo.dwDVVAuxCtl = 0xfffcc83f;
- dvinfo.dwDVReserved[ 0 ] = 0;
- dvinfo.dwDVReserved[ 1 ] = 0;
- break;
-
- default: /* no default allowed */
- assert( 0 );
- break;
- }
-
- indx[ 0 ] ->dwChunkId = make_fourcc( "00__" );
-
- /* Initialize the 'strh' chunk */
-
- streamHdr[ 0 ].fccType = make_fourcc( "iavs" );
- streamHdr[ 0 ].fccHandler = make_fourcc( "dvsd" );
- streamHdr[ 0 ].dwFlags = 0;
- streamHdr[ 0 ].wPriority = 0;
- streamHdr[ 0 ].wLanguage = 0;
- streamHdr[ 0 ].dwInitialFrames = 0;
- streamHdr[ 0 ].dwStart = 0;
- streamHdr[ 0 ].dwLength = 0;
- streamHdr[ 0 ].dwQuality = 0;
- streamHdr[ 0 ].dwSampleSize = 0;
- streamHdr[ 0 ].rcFrame.top = 0;
- streamHdr[ 0 ].rcFrame.bottom = 0;
- streamHdr[ 0 ].rcFrame.left = 0;
- streamHdr[ 0 ].rcFrame.right = 0;
-
- /* This is a simple directory structure setup. For details see the
- "OpenDML AVI File Format Extensions" document.
-
- An AVI file contains basically two types of objects, a
- "chunk" and a "list" object. The list object contains any
- number of chunks. Since a list is also a chunk, it is
- possible to create a hierarchical "list of lists"
- structure.
-
- Every AVI file starts with a "RIFF" object, which is a list
- of several other required objects. The actual DV data is
- contained in a "movi" list, each frame is in its own chunk.
-
- Old AVI files (pre OpenDML V. 1.02) contain only one RIFF
- chunk of less than 1 GByte size per file. The current
- format which allow for almost arbitrary sizes can contain
- several RIFF chunks of less than 1 GByte size. Old software
- however would only deal with the first RIFF chunk.
-
- Note that the first entry (FILE) isn�t actually part
- of the AVI file. I use this (pseudo-) directory entry to
- keep track of the RIFF chunks and their positions in the
- AVI file.
- */
-
- /* Create the container directory entry */
-
- file_list = AddDirectoryEntry( make_fourcc( "FILE" ), make_fourcc( "FILE" ), 0, RIFF_NO_PARENT );
-
- /* Create a basic directory structure. Only chunks defined from here on will be written to the AVI file. */
-
- riff_list = AddDirectoryEntry( make_fourcc( "RIFF" ), make_fourcc( "AVI " ), RIFF_LISTSIZE, file_list );
- hdrl_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "hdrl" ), RIFF_LISTSIZE, riff_list );
- avih_chunk = AddDirectoryEntry( make_fourcc( "avih" ), 0, sizeof( MainAVIHeader ), hdrl_list );
- strl_list[ 0 ] = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "strl" ), RIFF_LISTSIZE, hdrl_list );
- strh_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "strh" ), 0, sizeof( AVIStreamHeader ), strl_list[ 0 ] );
- strf_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "strf" ), 0, sizeof( dvinfo ), strl_list[ 0 ] );
- if ( index_type & AVI_LARGE_INDEX )
- indx_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "indx" ), 0, sizeof( AVISuperIndex ), strl_list[ 0 ] );
-
- odml_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "odml" ), RIFF_LISTSIZE, hdrl_list );
- dmlh_chunk = AddDirectoryEntry( make_fourcc( "dmlh" ), 0, 0x00f8, odml_list );
-
- /* align movi list to block */
- GetDirectoryEntry( hdrl_list, type, name, length, offset, parent );
- num_blocks = length / PADDING_SIZE + 1;
- length = num_blocks * PADDING_SIZE - length - 5 * RIFF_HEADERSIZE; // why 5?
- junk_chunk = AddDirectoryEntry( make_fourcc( "JUNK" ), 0, length, riff_list );
-
- movi_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "movi" ), RIFF_LISTSIZE, riff_list );
-
- /* The ix00 chunk will be added dynamically to the movi_list in avi_write_frame
- as needed */
-
- ix_chunk[ 0 ] = -1;
-}
-
-
-/* Write a DV video frame. This is somewhat complex... */
-
-#if 0
-bool AVI1File::WriteFrame( const Frame &frame )
-{
- int frame_chunk;
- int junk_chunk;
- int num_blocks;
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
-
- /* exit if no large index and 1GB reached */
- if ( !( index_type & AVI_LARGE_INDEX ) && isUpdateIdx1 == false )
- return false;
-
- /* Check if we need a new ix00 Standard Index. It has a
- capacity of IX00_INDEX_SIZE frames. Whenever we exceed that
- number, we need a new index. The new ix00 chunk is also
- part of the movi list. */
-
- if ( ( index_type & AVI_LARGE_INDEX ) && ( ( ( streamHdr[ 0 ].dwLength - 0 ) % IX00_INDEX_SIZE ) == 0 ) )
- FlushIndx( 0 );
-
- /* Write the DV frame data.
-
- Make a new 00__ chunk for the new frame, write out the
- frame. */
-
- frame_chunk = AddDirectoryEntry( make_fourcc( "00__" ), 0, frame.GetFrameSize(), movi_list );
- if ( ( index_type & AVI_LARGE_INDEX ) && ( streamHdr[ 0 ].dwLength % IX00_INDEX_SIZE ) == 0 )
- {
- GetDirectoryEntry( frame_chunk, type, name, length, offset, parent );
- ix[ 0 ] ->qwBaseOffset = offset - RIFF_HEADERSIZE;
- }
- WriteChunk( frame_chunk, frame.data );
- // num_blocks = (frame.GetFrameSize() + RIFF_HEADERSIZE) / PADDING_SIZE + 1;
- // length = num_blocks * PADDING_SIZE - frame.GetFrameSize() - 2 * RIFF_HEADERSIZE;
- // junk_chunk = AddDirectoryEntry(make_fourcc("JUNK"), 0, length, movi_list);
- // WriteChunk(junk_chunk, g_zeroes);
-
- if ( index_type & AVI_LARGE_INDEX )
- UpdateIndx( 0, frame_chunk, 1 );
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- UpdateIdx1( frame_chunk, 0x10 );
-
- /* update some variables with the new frame count. */
-
- if ( isUpdateIdx1 )
- ++mainHdr.dwTotalFrames;
- ++streamHdr[ 0 ].dwLength;
- ++dmlh[ 0 ];
-
- /* Find out if the current riff list is close to 1 GByte in
- size. If so, start a new (extended) RIFF. The only allowed
- item in the new RIFF chunk is a movi list (with video
- frames and indexes as usual). */
-
- GetDirectoryEntry( riff_list, type, name, length, offset, parent );
- if ( length > 0x3f000000 )
- {
- /* write idx1 only once and before end of first GB */
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- {
- int idx1_chunk = AddDirectoryEntry( make_fourcc( "idx1" ), 0, idx1->nEntriesInUse * 16, riff_list );
- WriteChunk( idx1_chunk, ( void* ) idx1 );
- }
- isUpdateIdx1 = false;
-
- if ( index_type & AVI_LARGE_INDEX )
- {
- /* pad out to 1GB */
- //GetDirectoryEntry(riff_list, type, name, length, offset, parent);
- //junk_chunk = AddDirectoryEntry(make_fourcc("JUNK"), 0, PADDING_1GB - length - 5 * RIFF_HEADERSIZE, riff_list);
- //WriteChunk(junk_chunk, g_zeroes);
-
- /* padding for alignment */
- GetDirectoryEntry( riff_list, type, name, length, offset, parent );
- num_blocks = ( length + 4 * RIFF_HEADERSIZE ) / PADDING_SIZE + 1;
- length = ( num_blocks * PADDING_SIZE ) - length - 4 * RIFF_HEADERSIZE - 2 * RIFF_LISTSIZE;
- if ( length > 0 )
- {
- junk_chunk = AddDirectoryEntry( make_fourcc( "JUNK" ), 0, length, riff_list );
- WriteChunk( junk_chunk, g_zeroes );
- }
-
- riff_list = AddDirectoryEntry( make_fourcc( "RIFF" ), make_fourcc( "AVIX" ), RIFF_LISTSIZE, file_list );
- movi_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "movi" ), RIFF_LISTSIZE, riff_list );
- }
- }
- return true;
-}
-#endif
-
-void AVI1File::WriteRIFF()
-{
-
- WriteChunk( avih_chunk, ( void* ) & mainHdr );
- WriteChunk( strh_chunk[ 0 ], ( void* ) & streamHdr[ 0 ] );
- WriteChunk( strf_chunk[ 0 ], ( void* ) & dvinfo );
- WriteChunk( dmlh_chunk, ( void* ) & dmlh );
-
- if ( index_type & AVI_LARGE_INDEX )
- {
- WriteChunk( indx_chunk[ 0 ], ( void* ) indx[ 0 ] );
- WriteChunk( ix_chunk[ 0 ], ( void* ) ix[ 0 ] );
- }
-
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- {
- int idx1_chunk = AddDirectoryEntry( make_fourcc( "idx1" ), 0, idx1->nEntriesInUse * 16, riff_list );
- WriteChunk( idx1_chunk, ( void* ) idx1 );
- }
-
- RIFFFile::WriteRIFF();
-}
-
-
-AVI2File::AVI2File() : AVIFile()
-{}
-
-
-AVI2File::~AVI2File()
-{}
-
-
-/* Initialize the AVI structure to its initial state, either for PAL
- or NTSC format */
-
-void AVI2File::Init( int format, int sampleFrequency, int indexType )
-{
- int num_blocks;
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
-
- assert( ( format == AVI_PAL ) || ( format == AVI_NTSC ) );
-
- AVIFile::Init( format, sampleFrequency, indexType );
-
- switch ( format )
- {
-
- case AVI_PAL:
- mainHdr.dwStreams = 2;
- mainHdr.dwWidth = 720;
- mainHdr.dwHeight = 576;
-
- /* Initialize the 'strh' chunk */
-
- streamHdr[ 0 ].fccType = make_fourcc( "vids" );
- streamHdr[ 0 ].fccHandler = make_fourcc( "dvsd" );
- streamHdr[ 0 ].dwFlags = 0;
- streamHdr[ 0 ].wPriority = 0;
- streamHdr[ 0 ].wLanguage = 0;
- streamHdr[ 0 ].dwInitialFrames = 0;
- streamHdr[ 0 ].dwScale = 1;
- streamHdr[ 0 ].dwRate = 25;
- streamHdr[ 0 ].dwStart = 0;
- streamHdr[ 0 ].dwLength = 0;
- streamHdr[ 0 ].dwSuggestedBufferSize = 144008;
- streamHdr[ 0 ].dwQuality = -1;
- streamHdr[ 0 ].dwSampleSize = 0;
- streamHdr[ 0 ].rcFrame.top = 0;
- streamHdr[ 0 ].rcFrame.bottom = 0;
- streamHdr[ 0 ].rcFrame.left = 0;
- streamHdr[ 0 ].rcFrame.right = 0;
-
- bitmapinfo.biSize = sizeof( bitmapinfo );
- bitmapinfo.biWidth = 720;
- bitmapinfo.biHeight = 576;
- bitmapinfo.biPlanes = 1;
- bitmapinfo.biBitCount = 24;
- bitmapinfo.biCompression = make_fourcc( "dvsd" );
- bitmapinfo.biSizeImage = 144000;
- bitmapinfo.biXPelsPerMeter = 0;
- bitmapinfo.biYPelsPerMeter = 0;
- bitmapinfo.biClrUsed = 0;
- bitmapinfo.biClrImportant = 0;
-
- streamHdr[ 1 ].fccType = make_fourcc( "auds" );
- streamHdr[ 1 ].fccHandler = 0;
- streamHdr[ 1 ].dwFlags = 0;
- streamHdr[ 1 ].wPriority = 0;
- streamHdr[ 1 ].wLanguage = 0;
- streamHdr[ 1 ].dwInitialFrames = 0;
- streamHdr[ 1 ].dwScale = 2 * 2;
- streamHdr[ 1 ].dwRate = sampleFrequency * 2 * 2;
- streamHdr[ 1 ].dwStart = 0;
- streamHdr[ 1 ].dwLength = 0;
- streamHdr[ 1 ].dwSuggestedBufferSize = 8192;
- streamHdr[ 1 ].dwQuality = -1;
- streamHdr[ 1 ].dwSampleSize = 2 * 2;
- streamHdr[ 1 ].rcFrame.top = 0;
- streamHdr[ 1 ].rcFrame.bottom = 0;
- streamHdr[ 1 ].rcFrame.left = 0;
- streamHdr[ 1 ].rcFrame.right = 0;
-
- break;
-
- case AVI_NTSC:
- mainHdr.dwTotalFrames = 0;
- mainHdr.dwStreams = 2;
- mainHdr.dwWidth = 720;
- mainHdr.dwHeight = 480;
-
- /* Initialize the 'strh' chunk */
-
- streamHdr[ 0 ].fccType = make_fourcc( "vids" );
- streamHdr[ 0 ].fccHandler = make_fourcc( "dvsd" );
- streamHdr[ 0 ].dwFlags = 0;
- streamHdr[ 0 ].wPriority = 0;
- streamHdr[ 0 ].wLanguage = 0;
- streamHdr[ 0 ].dwInitialFrames = 0;
- streamHdr[ 0 ].dwScale = 1001;
- streamHdr[ 0 ].dwRate = 30000;
- streamHdr[ 0 ].dwStart = 0;
- streamHdr[ 0 ].dwLength = 0;
- streamHdr[ 0 ].dwSuggestedBufferSize = 120008;
- streamHdr[ 0 ].dwQuality = -1;
- streamHdr[ 0 ].dwSampleSize = 0;
- streamHdr[ 0 ].rcFrame.top = 0;
- streamHdr[ 0 ].rcFrame.bottom = 0;
- streamHdr[ 0 ].rcFrame.left = 0;
- streamHdr[ 0 ].rcFrame.right = 0;
-
- bitmapinfo.biSize = sizeof( bitmapinfo );
- bitmapinfo.biWidth = 720;
- bitmapinfo.biHeight = 480;
- bitmapinfo.biPlanes = 1;
- bitmapinfo.biBitCount = 24;
- bitmapinfo.biCompression = make_fourcc( "dvsd" );
- bitmapinfo.biSizeImage = 120000;
- bitmapinfo.biXPelsPerMeter = 0;
- bitmapinfo.biYPelsPerMeter = 0;
- bitmapinfo.biClrUsed = 0;
- bitmapinfo.biClrImportant = 0;
-
- streamHdr[ 1 ].fccType = make_fourcc( "auds" );
- streamHdr[ 1 ].fccHandler = 0;
- streamHdr[ 1 ].dwFlags = 0;
- streamHdr[ 1 ].wPriority = 0;
- streamHdr[ 1 ].wLanguage = 0;
- streamHdr[ 1 ].dwInitialFrames = 1;
- streamHdr[ 1 ].dwScale = 2 * 2;
- streamHdr[ 1 ].dwRate = sampleFrequency * 2 * 2;
- streamHdr[ 1 ].dwStart = 0;
- streamHdr[ 1 ].dwLength = 0;
- streamHdr[ 1 ].dwSuggestedBufferSize = 8192;
- streamHdr[ 1 ].dwQuality = 0;
- streamHdr[ 1 ].dwSampleSize = 2 * 2;
- streamHdr[ 1 ].rcFrame.top = 0;
- streamHdr[ 1 ].rcFrame.bottom = 0;
- streamHdr[ 1 ].rcFrame.left = 0;
- streamHdr[ 1 ].rcFrame.right = 0;
-
- break;
- }
- waveformatex.wFormatTag = 1;
- waveformatex.nChannels = 2;
- waveformatex.nSamplesPerSec = sampleFrequency;
- waveformatex.nAvgBytesPerSec = sampleFrequency * 2 * 2;
- waveformatex.nBlockAlign = 4;
- waveformatex.wBitsPerSample = 16;
- waveformatex.cbSize = 0;
-
- file_list = AddDirectoryEntry( make_fourcc( "FILE" ), make_fourcc( "FILE" ), 0, RIFF_NO_PARENT );
-
- /* Create a basic directory structure. Only chunks defined from here on will be written to the AVI file. */
-
- riff_list = AddDirectoryEntry( make_fourcc( "RIFF" ), make_fourcc( "AVI " ), RIFF_LISTSIZE, file_list );
- hdrl_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "hdrl" ), RIFF_LISTSIZE, riff_list );
- avih_chunk = AddDirectoryEntry( make_fourcc( "avih" ), 0, sizeof( MainAVIHeader ), hdrl_list );
-
- strl_list[ 0 ] = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "strl" ), RIFF_LISTSIZE, hdrl_list );
- strh_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "strh" ), 0, sizeof( AVIStreamHeader ), strl_list[ 0 ] );
- strf_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "strf" ), 0, sizeof( BITMAPINFOHEADER ), strl_list[ 0 ] );
- if ( index_type & AVI_LARGE_INDEX )
- {
- indx_chunk[ 0 ] = AddDirectoryEntry( make_fourcc( "indx" ), 0, sizeof( AVISuperIndex ), strl_list[ 0 ] );
- ix_chunk[ 0 ] = -1;
- indx[ 0 ] ->dwChunkId = make_fourcc( "00dc" );
- }
-
- strl_list[ 1 ] = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "strl" ), RIFF_LISTSIZE, hdrl_list );
- strh_chunk[ 1 ] = AddDirectoryEntry( make_fourcc( "strh" ), 0, sizeof( AVIStreamHeader ), strl_list[ 1 ] );
- strf_chunk[ 1 ] = AddDirectoryEntry( make_fourcc( "strf" ), 0, sizeof( WAVEFORMATEX ) - 2, strl_list[ 1 ] );
- junk_chunk = AddDirectoryEntry( make_fourcc( "JUNK" ), 0, 2, strl_list[ 1 ] );
- if ( index_type & AVI_LARGE_INDEX )
- {
- indx_chunk[ 1 ] = AddDirectoryEntry( make_fourcc( "indx" ), 0, sizeof( AVISuperIndex ), strl_list[ 1 ] );
- ix_chunk[ 1 ] = -1;
- indx[ 1 ] ->dwChunkId = make_fourcc( "01wb" );
-
- odml_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "odml" ), RIFF_LISTSIZE, hdrl_list );
- dmlh_chunk = AddDirectoryEntry( make_fourcc( "dmlh" ), 0, 0x00f8, odml_list );
- }
-
- /* align movi list to block */
- GetDirectoryEntry( hdrl_list, type, name, length, offset, parent );
- num_blocks = length / PADDING_SIZE + 1;
- length = num_blocks * PADDING_SIZE - length - 5 * RIFF_HEADERSIZE; // why 5 headers?
- junk_chunk = AddDirectoryEntry( make_fourcc( "JUNK" ), 0, length, riff_list );
-
- movi_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "movi" ), RIFF_LISTSIZE, riff_list );
-
- idx1->aIndex[ idx1->nEntriesInUse ].dwChunkId = make_fourcc( "7Fxx" );
- idx1->aIndex[ idx1->nEntriesInUse ].dwFlags = 0;
- idx1->aIndex[ idx1->nEntriesInUse ].dwOffset = 0;
- idx1->aIndex[ idx1->nEntriesInUse ].dwSize = 0;
- idx1->nEntriesInUse++;
-}
-
-
-void AVI2File::WriteRIFF()
-{
- WriteChunk( avih_chunk, ( void* ) & mainHdr );
- WriteChunk( strh_chunk[ 0 ], ( void* ) & streamHdr[ 0 ] );
- WriteChunk( strf_chunk[ 0 ], ( void* ) & bitmapinfo );
- if ( index_type & AVI_LARGE_INDEX )
- {
- WriteChunk( dmlh_chunk, ( void* ) & dmlh );
- WriteChunk( indx_chunk[ 0 ], ( void* ) indx[ 0 ] );
- WriteChunk( ix_chunk[ 0 ], ( void* ) ix[ 0 ] );
- }
- WriteChunk( strh_chunk[ 1 ], ( void* ) & streamHdr[ 1 ] );
- WriteChunk( strf_chunk[ 1 ], ( void* ) & waveformatex );
- if ( index_type & AVI_LARGE_INDEX )
- {
- WriteChunk( indx_chunk[ 1 ], ( void* ) indx[ 1 ] );
- WriteChunk( ix_chunk[ 1 ], ( void* ) ix[ 1 ] );
- }
-
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- {
- int idx1_chunk = AddDirectoryEntry( make_fourcc( "idx1" ), 0, idx1->nEntriesInUse * 16, riff_list );
- WriteChunk( idx1_chunk, ( void* ) idx1 );
- }
- RIFFFile::WriteRIFF();
-}
-
-
-/** Write a DV video frame
-
- \param frame the frame to write
-*/
-
-#if 0
-bool AVI2File::WriteFrame( const Frame &frame )
-{
- int audio_chunk;
- int frame_chunk;
- int junk_chunk;
- char soundbuf[ 20000 ];
- int audio_size;
- int num_blocks;
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
-
- /* exit if no large index and 1GB reached */
- if ( !( index_type & AVI_LARGE_INDEX ) && isUpdateIdx1 == false )
- return false;
-
- /* Check if we need a new ix00 Standard Index. It has a
- capacity of IX00_INDEX_SIZE frames. Whenever we exceed that
- number, we need a new index. The new ix00 chunk is also
- part of the movi list. */
-
- if ( ( index_type & AVI_LARGE_INDEX ) && ( ( ( streamHdr[ 0 ].dwLength - 0 ) % IX00_INDEX_SIZE ) == 0 ) )
- {
- FlushIndx( 0 );
- FlushIndx( 1 );
- }
-
- /* Write audio data if we have it */
-
- audio_size = frame.ExtractAudio( soundbuf );
- if ( audio_size > 0 )
- {
- audio_chunk = AddDirectoryEntry( make_fourcc( "01wb" ), 0, audio_size, movi_list );
- if ( ( index_type & AVI_LARGE_INDEX ) && ( streamHdr[ 0 ].dwLength % IX00_INDEX_SIZE ) == 0 )
- {
- GetDirectoryEntry( audio_chunk, type, name, length, offset, parent );
- ix[ 1 ] ->qwBaseOffset = offset - RIFF_HEADERSIZE;
- }
- WriteChunk( audio_chunk, soundbuf );
- // num_blocks = (audio_size + RIFF_HEADERSIZE) / PADDING_SIZE + 1;
- // length = num_blocks * PADDING_SIZE - audio_size - 2 * RIFF_HEADERSIZE;
- // junk_chunk = AddDirectoryEntry(make_fourcc("JUNK"), 0, length, movi_list);
- // WriteChunk(junk_chunk, g_zeroes);
- if ( index_type & AVI_LARGE_INDEX )
- UpdateIndx( 1, audio_chunk, audio_size / waveformatex.nChannels / 2 );
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- UpdateIdx1( audio_chunk, 0x00 );
- streamHdr[ 1 ].dwLength += audio_size / waveformatex.nChannels / 2;
-
- }
-
- /* Write video data */
-
- frame_chunk = AddDirectoryEntry( make_fourcc( "00dc" ), 0, frame.GetFrameSize(), movi_list );
- if ( ( index_type & AVI_LARGE_INDEX ) && ( streamHdr[ 0 ].dwLength % IX00_INDEX_SIZE ) == 0 )
- {
- GetDirectoryEntry( frame_chunk, type, name, length, offset, parent );
- ix[ 0 ] ->qwBaseOffset = offset - RIFF_HEADERSIZE;
- }
- WriteChunk( frame_chunk, frame.data );
- // num_blocks = (frame.GetFrameSize() + RIFF_HEADERSIZE) / PADDING_SIZE + 1;
- // length = num_blocks * PADDING_SIZE - frame.GetFrameSize() - 2 * RIFF_HEADERSIZE;
- // junk_chunk = AddDirectoryEntry(make_fourcc("JUNK"), 0, length, movi_list);
- // WriteChunk(junk_chunk, g_zeroes);
- if ( index_type & AVI_LARGE_INDEX )
- UpdateIndx( 0, frame_chunk, 1 );
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- UpdateIdx1( frame_chunk, 0x10 );
-
- /* update some variables with the new frame count. */
-
- if ( isUpdateIdx1 )
- ++mainHdr.dwTotalFrames;
- ++streamHdr[ 0 ].dwLength;
- ++dmlh[ 0 ];
-
- /* Find out if the current riff list is close to 1 GByte in
- size. If so, start a new (extended) RIFF. The only allowed
- item in the new RIFF chunk is a movi list (with video
- frames and indexes as usual). */
-
- GetDirectoryEntry( riff_list, type, name, length, offset, parent );
- if ( length > 0x3f000000 )
- {
-
- /* write idx1 only once and before end of first GB */
- if ( ( index_type & AVI_SMALL_INDEX ) && isUpdateIdx1 )
- {
- int idx1_chunk = AddDirectoryEntry( make_fourcc( "idx1" ), 0, idx1->nEntriesInUse * 16, riff_list );
- WriteChunk( idx1_chunk, ( void* ) idx1 );
- }
- isUpdateIdx1 = false;
-
- if ( index_type & AVI_LARGE_INDEX )
- {
- /* padding for alignment */
- GetDirectoryEntry( riff_list, type, name, length, offset, parent );
- num_blocks = ( length + 4 * RIFF_HEADERSIZE ) / PADDING_SIZE + 1;
- length = ( num_blocks * PADDING_SIZE ) - length - 4 * RIFF_HEADERSIZE - 2 * RIFF_LISTSIZE;
- if ( length > 0 )
- {
- junk_chunk = AddDirectoryEntry( make_fourcc( "JUNK" ), 0, length, riff_list );
- WriteChunk( junk_chunk, g_zeroes );
- }
-
- riff_list = AddDirectoryEntry( make_fourcc( "RIFF" ), make_fourcc( "AVIX" ), RIFF_LISTSIZE, file_list );
- movi_list = AddDirectoryEntry( make_fourcc( "LIST" ), make_fourcc( "movi" ), RIFF_LISTSIZE, riff_list );
- }
- }
- return true;
-}
-#endif
-
-void AVI1File::setDVINFO( DVINFO &info )
-{
- // do not do this until debugged audio against DirectShow
- return ;
-
- dvinfo.dwDVAAuxSrc = info.dwDVAAuxSrc;
- dvinfo.dwDVAAuxCtl = info.dwDVAAuxCtl;
- dvinfo.dwDVAAuxSrc1 = info.dwDVAAuxSrc1;
- dvinfo.dwDVAAuxCtl1 = info.dwDVAAuxCtl1;
- dvinfo.dwDVVAuxSrc = info.dwDVVAuxSrc;
- dvinfo.dwDVVAuxCtl = info.dwDVVAuxCtl;
-}
-
-
-void AVI2File::setDVINFO( DVINFO &info )
-{}
-
-void AVIFile::setFccHandler( FOURCC type, FOURCC handler )
-{
- for ( int i = 0; i < mainHdr.dwStreams; i++ )
- {
- if ( streamHdr[ i ].fccType == type )
- {
- int k, j = 0;
- FOURCC strf = make_fourcc( "strf" );
- BITMAPINFOHEADER bih;
-
- streamHdr[ i ].fccHandler = handler;
-
- while ( ( k = FindDirectoryEntry( strf, j++ ) ) != -1 )
- {
- ReadChunk( k, ( void* ) & bih, sizeof( BITMAPINFOHEADER ) );
- bih.biCompression = handler;
- }
- }
- }
-}
-
-bool AVIFile::getStreamFormat( void* data, FOURCC type )
-{
- int i, j = 0;
- FOURCC strh = make_fourcc( "strh" );
- FOURCC strf = make_fourcc( "strf" );
- AVIStreamHeader avi_stream_header;
- bool result = false;
-
- while ( ( result == false ) && ( i = FindDirectoryEntry( strh, j++ ) ) != -1 )
- {
- ReadChunk( i, ( void* ) & avi_stream_header, sizeof( AVIStreamHeader ) );
- if ( avi_stream_header.fccType == type )
- {
- FOURCC chunkID;
- int size;
-
- pthread_mutex_lock( &file_mutex );
- fail_neg( read( fd, &chunkID, sizeof( FOURCC ) ) );
- if ( chunkID == strf )
- {
- fail_neg( read( fd, &size, sizeof( int ) ) );
- fail_neg( read( fd, data, size ) );
- result = true;
- }
- pthread_mutex_unlock( &file_mutex );
- }
- }
- return result;
-}
+++ /dev/null
-/*
-* avi.h library for AVI file format i/o
-* Copyright (C) 2000 - 2002 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*
-* Tag: $Name$
-*
-* Change log:
-*
-* $Log$
-* Revision 1.4 2005/07/25 07:21:39 lilo_booter
-* + fixes for opendml dv avi
-*
-* Revision 1.3 2005/06/21 20:59:39 lilo_booter
-* src/framework/mlt_consumer.c src/framework/mlt_consumer.h
-* + Added a general profile handling for size, aspect ratio and display ratio
-*
-* src/framework/mlt_producer.c
-* + Correction to aspect ratio properties
-*
-* src/inigo/inigo.c
-* + Minimalist support for sdl_preview (still not very good)
-*
-* src/modules/avformat/consumer_avformat.c
-* + Takes consumer profile into account
-*
-* src/modules/core/filter_resize.c
-* + Corrections for synthesised producers and aspect ratio (inherits from consumer)
-*
-* src/modules/core/producer_colour.c
-* src/modules/core/producer_noise.c
-* src/modules/gtk2/producer_pango.c
-* + Ensures that resize picks up consumer aspect ratio
-*
-* src/modules/dv/consumer_libdv.c
-* + Honour wide screen output
-*
-* src/modules/gtk2/producer_pixbuf.c
-* + Correction for 1:1 aspect ratio
-*
-* src/modules/kino/Makefile
-* src/modules/kino/avi.cc
-* src/modules/kino/avi.h
-* src/modules/kino/configure
-* src/modules/kino/filehandler.cc
-* + Attempt to allow mov dv files to provide audio
-*
-* src/modules/sdl/consumer_sdl.c
-* src/modules/sdl/consumer_sdl_preview.c
-* src/modules/sdl/consumer_sdl_still.c
-* + Takes consumer profile into account
-*
-* Revision 1.2 2005/04/15 14:37:03 lilo_booter
-* Minor correction
-*
-* Revision 1.1 2005/04/15 14:28:26 lilo_booter
-* Initial version
-*
-* Revision 1.16 2005/04/01 23:43:10 ddennedy
-* apply endian fixes from Daniel Kobras
-*
-* Revision 1.15 2004/10/11 01:37:11 ddennedy
-* mutex safety locks in RIFF and AVI classes, type 2 AVI optimization, mencoder export script
-*
-* Revision 1.14 2003/11/25 23:00:52 ddennedy
-* cleanup and a few bugfixes
-*
-* Revision 1.13 2003/10/21 16:34:32 ddennedy
-* GNOME2 port phase 1: initial checkin
-*
-* Revision 1.11.2.5 2003/07/24 14:13:57 ddennedy
-* support for distinct audio stream in type2 AVI and Quicktime; support for more DV FOURCCs
-*
-* Revision 1.11.2.4 2003/06/10 23:53:36 ddennedy
-* Daniel Kobras' WriteFrame error handling and automatic OpenDML, bugfixes in scene list updates, export AV/C Record
-*
-* Revision 1.11.2.3 2003/02/20 21:59:57 ddennedy
-* bugfixes to capture and AVI
-*
-* Revision 1.11.2.2 2003/01/13 05:15:31 ddennedy
-* added More Info panel and supporting methods
-*
-* Revision 1.11.2.1 2002/11/25 04:48:31 ddennedy
-* bugfix to report errors when loading files
-*
-* Revision 1.11 2002/10/08 07:46:41 ddennedy
-* AVI bugfixes, compatibility, optimization, warn bad file in capture and export dv file, allow no mplex
-*
-* Revision 1.10 2002/05/17 08:04:25 ddennedy
-* revert const-ness of Frame references in Frame, FileHandler, and AVI classes
-*
-* Revision 1.9 2002/05/15 04:39:35 ddennedy
-* bugfixes to dv2 AVI write, audio export, Xv init
-*
-* Revision 1.8 2002/04/29 05:09:22 ddennedy
-* raw dv file support, Frame::ExtractAudio uses libdv, audioScrub prefs
-*
-* Revision 1.7 2002/04/09 06:53:42 ddennedy
-* cleanup, new libdv 0.9.5, large AVI, dnd storyboard
-*
-* Revision 1.7 2002/03/25 21:34:25 arne
-* Support for large (64 bit) files mostly completed
-*
-* Revision 1.6 2002/03/10 13:29:41 arne
-* more changes for 64 bit access
-*
-* Revision 1.5 2002/03/09 17:59:28 arne
-* moved index routines to AVIFile
-*
-* Revision 1.4 2002/03/09 10:26:26 arne
-* improved constructors and assignment operator
-*
-* Revision 1.3 2002/03/09 08:55:57 arne
-* moved a few variables to AVIFile
-*
-* Revision 1.2 2002/03/04 19:22:43 arne
-* updated to latest Kino avi code
-*
-* Revision 1.1.1.1 2002/03/03 19:08:08 arne
-* import of version 1.01
-*
-*/
-
-/** Common AVI declarations
-
- Some of this comes from the public domain AVI specification, which
- explains the microsoft-style definitions.
-
- \file avi.h
-*/
-
-#ifndef _AVI_H
-#define _AVI_H 1
-
-#include <stdint.h>
-#include "riff.h"
-
-#define PACKED(x) __attribute__((packed)) x
-
-#define AVI_SMALL_INDEX (0x01)
-#define AVI_LARGE_INDEX (0x02)
-#define KINO_AVI_INDEX_OF_INDEXES (0x00)
-#define KINO_AVI_INDEX_OF_CHUNKS (0x01)
-#define AVI_INDEX_2FIELD (0x01)
-
-enum { AVI_PAL, AVI_NTSC, AVI_AUDIO_48KHZ, AVI_AUDIO_44KHZ, AVI_AUDIO_32KHZ };
-
-/** Declarations of the main AVI file header
-
- The contents of this struct goes into the 'avih' chunk. */
-
-typedef struct
-{
- /// frame display rate (or 0L)
- DWORD dwMicroSecPerFrame;
-
- /// max. transfer rate
- DWORD dwMaxBytesPerSec;
-
- /// pad to multiples of this size, normally 2K
- DWORD dwPaddingGranularity;
-
- /// the ever-present flags
- DWORD dwFlags;
-
- /// # frames in file
- DWORD dwTotalFrames;
- DWORD dwInitialFrames;
- DWORD dwStreams;
- DWORD dwSuggestedBufferSize;
-
- DWORD dwWidth;
- DWORD dwHeight;
-
- DWORD dwReserved[ 4 ];
-}
-PACKED(MainAVIHeader);
-
-typedef struct
-{
- WORD top, bottom, left, right;
-}
-PACKED(RECT);
-
-/** Declaration of a stream header
-
- The contents of this struct goes into the 'strh' header. */
-
-typedef struct
-{
- FOURCC fccType;
- FOURCC fccHandler;
- DWORD dwFlags; /* Contains AVITF_* flags */
- WORD wPriority;
- WORD wLanguage;
- DWORD dwInitialFrames;
- DWORD dwScale;
- DWORD dwRate; /* dwRate / dwScale == samples/second */
- DWORD dwStart;
- DWORD dwLength; /* In units above... */
- DWORD dwSuggestedBufferSize;
- DWORD dwQuality;
- DWORD dwSampleSize;
- RECT rcFrame;
-}
-PACKED(AVIStreamHeader);
-
-typedef struct
-{
- DWORD dwDVAAuxSrc;
- DWORD dwDVAAuxCtl;
- DWORD dwDVAAuxSrc1;
- DWORD dwDVAAuxCtl1;
- DWORD dwDVVAuxSrc;
- DWORD dwDVVAuxCtl;
- DWORD dwDVReserved[ 2 ];
-}
-PACKED(DVINFO);
-
-typedef struct
-{
- DWORD biSize;
- LONG biWidth;
- LONG biHeight;
- WORD biPlanes;
- WORD biBitCount;
- DWORD biCompression;
- DWORD biSizeImage;
- LONG biXPelsPerMeter;
- LONG biYPelsPerMeter;
- DWORD biClrUsed;
- DWORD biClrImportant;
- char dummy[ 1040 ];
-}
-PACKED(BITMAPINFOHEADER);
-
-typedef struct
-{
- WORD wFormatTag;
- WORD nChannels;
- DWORD nSamplesPerSec;
- DWORD nAvgBytesPerSec;
- WORD nBlockAlign;
- WORD wBitsPerSample;
- WORD cbSize;
- WORD dummy;
-}
-PACKED(WAVEFORMATEX);
-
-typedef struct
-{
- WORD wLongsPerEntry;
- BYTE bIndexSubType;
- BYTE bIndexType;
- DWORD nEntriesInUse;
- FOURCC dwChunkId;
- DWORD dwReserved[ 3 ];
- struct avisuperindex_entry
- {
- QUADWORD qwOffset;
- DWORD dwSize;
- DWORD dwDuration;
- }
- aIndex[ 3198 ];
-}
-PACKED(AVISuperIndex);
-
-typedef struct
-{
- WORD wLongsPerEntry;
- BYTE bIndexSubType;
- BYTE bIndexType;
- DWORD nEntriesInUse;
- FOURCC dwChunkId;
- QUADWORD qwBaseOffset;
- DWORD dwReserved;
- struct avifieldindex_entry
- {
- DWORD dwOffset;
- DWORD dwSize;
- }
- aIndex[ 17895 ];
-}
-PACKED(AVIStdIndex);
-
-typedef struct
-{
- struct avisimpleindex_entry
- {
- FOURCC dwChunkId;
- DWORD dwFlags;
- DWORD dwOffset;
- DWORD dwSize;
- }
- aIndex[ 20000 ];
- DWORD nEntriesInUse;
-}
-PACKED(AVISimpleIndex);
-
-typedef struct
-{
- DWORD dirEntryType;
- DWORD dirEntryName;
- DWORD dirEntryLength;
- size_t dirEntryOffset;
- int dirEntryWrittenFlag;
- int dirEntryParentList;
-}
-AviDirEntry;
-
-
-/** base class for all AVI type files
-
- It contains methods and members which are the same in all AVI type files regardless of the particular compression, number
- of streams etc.
-
- The AVIFile class also contains methods for handling several indexes to the video frame content. */
-
-class AVIFile : public RIFFFile
-{
-public:
- AVIFile();
- AVIFile( const AVIFile& );
- virtual ~AVIFile();
- virtual AVIFile& operator=( const AVIFile& );
-
- virtual void Init( int format, int sampleFrequency, int indexType );
- virtual int GetDVFrameInfo( off_t &offset, int &size, int frameNum );
- virtual int GetFrameInfo( off_t &offset, int &size, int frameNum, FOURCC chunkID );
- virtual int GetDVFrame( uint8_t *data, int frameNum );
- virtual int getFrame( void *data, int frameNum, FOURCC chunkID );
- virtual int GetTotalFrames() const;
- virtual void PrintDirectoryEntryData( const RIFFDirEntry &entry ) const;
- //virtual bool WriteFrame( const Frame &frame ) { return false; }
- virtual void ParseList( int parent );
- virtual void ParseRIFF( void );
- virtual void ReadIndex( void );
- virtual void WriteRIFF( void )
- { }
- virtual void FlushIndx( int stream );
- virtual void UpdateIndx( int stream, int chunk, int duration );
- virtual void UpdateIdx1( int chunk, int flags );
- virtual bool verifyStreamFormat( FOURCC type );
- virtual bool verifyStream( FOURCC type );
- virtual bool isOpenDML( void );
- virtual void setDVINFO( DVINFO& )
- { }
- virtual void setFccHandler( FOURCC type, FOURCC handler );
- virtual bool getStreamFormat( void* data, FOURCC type );
-
-protected:
- MainAVIHeader mainHdr;
- AVISimpleIndex *idx1;
- int file_list;
- int riff_list;
- int hdrl_list;
- int avih_chunk;
- int movi_list;
- int junk_chunk;
- int idx1_chunk;
-
- AVIStreamHeader streamHdr[ 2 ];
- AVISuperIndex *indx[ 2 ];
- AVIStdIndex *ix[ 2 ];
- int indx_chunk[ 2 ];
- int ix_chunk[ 2 ];
- int strl_list[ 2 ];
- int strh_chunk[ 2 ];
- int strf_chunk[ 2 ];
-
- int index_type;
- int current_ix00;
-
- DWORD dmlh[ 62 ];
- int odml_list;
- int dmlh_chunk;
- bool isUpdateIdx1;
-
-};
-
-
-/** writing Type 1 DV AVIs
-
-*/
-
-class AVI1File : public AVIFile
-{
-public:
- AVI1File();
- virtual ~AVI1File();
-
- virtual void Init( int format, int sampleFrequency, int indexType );
- //virtual bool WriteFrame( const Frame &frame );
- virtual void WriteRIFF( void );
- virtual void setDVINFO( DVINFO& );
-
-private:
- DVINFO dvinfo;
-
- AVI1File( const AVI1File& );
- AVI1File& operator=( const AVI1File& );
-};
-
-
-/** writing Type 2 (separate audio data) DV AVIs
-
-This file type contains both audio and video tracks. It is therefore more compatible
-to certain Windows programs, which expect any AVI having both audio and video tracks.
-The video tracks contain the raw DV data (as in type 1) and the extracted audio tracks.
-
-Note that because the DV data contains audio information anyway, this means duplication
-of data and a slight increase of file size.
-
-*/
-
-class AVI2File : public AVIFile
-{
-public:
- AVI2File();
- virtual ~AVI2File();
-
- virtual void Init( int format, int sampleFrequency, int indexType );
- //virtual bool WriteFrame( const Frame &frame );
- virtual void WriteRIFF( void );
- virtual void setDVINFO( DVINFO& );
-
-private:
- BITMAPINFOHEADER bitmapinfo;
- WAVEFORMATEX waveformatex;
-
- AVI2File( const AVI2File& );
- AVI2File& operator=( const AVI2File& );
-};
-#endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- if [ "$targetos" = "Darwin" ]
- then
- echo "- does not build on Darwin: disabling"
- touch ../disable-kino
- exit 0
- fi
-
- # Entirely optional...
- pkg-config libquicktime 2> /dev/null
- lqt_disabled=$?
-
- pkg-config libdv 2> /dev/null
- libdv_disabled=$?
-
- echo > config.h
- [ "$lqt_disabled" = "0" ] && echo "#define HAVE_LIBQUICKTIME" >> config.h
- [ "$libdv_disabled" = "0" ] && echo "#define HAVE_LIBDV" >> config.h
- echo > config.mak
- [ "$lqt_disabled" = "0" ] && echo "HAVE_LIBQUICKTIME=1" >> config.mak
- [ "$libdv_disabled" = "0" ] && echo "HAVE_LIBDV=1" >> config.mak
-
- [ "$lqt_disabled" != "0" ] && echo "- libquicktime not found: only enabling dv avi support"
- [ "$libdv_disabled" != "0" -a "$lqt_disabled" = "0" ] && echo "- libdv not found: mov dv may not have audio"
-
- exit 0
-fi
+++ /dev/null
-/* <endian_types.h>
- *
- * Quick hack to handle endianness and word length issues.
- * Defines _le, _be, and _ne variants to standard ISO types
- * like int32_t, that are stored in little-endian, big-endian,
- * and native-endian byteorder in memory, respectively.
- * Caveat: int32_le_t and friends cannot be used in vararg
- * functions like printf() without an explicit cast.
- *
- * Copyright (c) 2003-2005 Daniel Kobras <kobras@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _ENDIAN_TYPES_H
-#define _ENDIAN_TYPES_H
-
-/* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */
-#ifndef _BSD_SOURCE
-# define _BSD_SOURCE
-#ifndef __FreeBSD__
-# include <endian.h>
-#else
-# include <sys/endian.h>
-#endif /* __FreeBSD__ */
-# undef _BSD_SOURCE
-#else
-#ifndef __FreeBSD__
-# include <endian.h>
-#else
-# include <sys/endian.h>
-#endif /* __FreeBSD__ */
-#endif
-
-#include <sys/types.h>
-#ifndef __FreeBSD__
-#include <byteswap.h>
-#else
-#define bswap_16(x) bswap16(x)
-#define bswap_32(x) bswap32(x)
-#define bswap_64(x) bswap64(x)
-#endif /* __FreeBSD__ */
-
-static inline int8_t bswap(const int8_t& x)
-{
- return x;
-}
-
-static inline u_int8_t bswap(const u_int8_t& x)
-{
- return x;
-}
-
-static inline int16_t bswap(const int16_t& x)
-{
- return bswap_16(x);
-}
-
-static inline u_int16_t bswap(const u_int16_t& x)
-{
- return bswap_16(x);
-}
-
-static inline int32_t bswap(const int32_t& x)
-{
- return bswap_32(x);
-}
-
-static inline u_int32_t bswap(const u_int32_t& x)
-{
- return bswap_32(x);
-}
-
-static inline int64_t bswap(const int64_t& x)
-{
- return bswap_64(x);
-}
-
-static inline u_int64_t bswap(const u_int64_t& x)
-{
- return bswap_64(x);
-}
-
-#define le_to_cpu cpu_to_le
-#define be_to_cpu cpu_to_be
-
-template <class T> static inline T cpu_to_le(const T& x)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return x;
-#else
- return bswap(x);
-#endif
-}
-
-template <class T> static inline T cpu_to_be(const T& x)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return bswap(x);
-#else
- return x;
-#endif
-}
-
-template <class T> class le_t {
- T m;
- T read() const {
- return le_to_cpu(m);
- };
- void write(const T& n) {
- m = cpu_to_le(n);
- };
-public:
- le_t(void) {
- m = 0;
- };
- le_t(const T& o) {
- write(o);
- };
- operator T() const {
- return read();
- };
- le_t<T> operator++() {
- write(read() + 1);
- return *this;
- };
- le_t<T> operator++(int) {
- write(read() + 1);
- return *this;
- };
- le_t<T> operator--() {
- write(read() - 1);
- return *this;
- };
- le_t<T> operator--(int) {
- write(read() - 1);
- return *this;
- };
- le_t<T>& operator+=(const T& t) {
- write(read() + t);
- return *this;
- };
- le_t<T>& operator-=(const T& t) {
- write(read() - t);
- return *this;
- };
- le_t<T>& operator&=(const le_t<T>& t) {
- m &= t.m;
- return *this;
- };
- le_t<T>& operator|=(const le_t<T>& t) {
- m |= t.m;
- return *this;
- };
-} __attribute__((packed));
-
-/* Just copy-and-pasted from le_t. Too lazy to do it right. */
-
-template <class T> class be_t {
- T m;
- T read() const {
- return be_to_cpu(m);
- };
- void write(const T& n) {
- m = cpu_to_be(n);
- };
-public:
- be_t(void) {
- m = 0;
- };
- be_t(const T& o) {
- write(o);
- };
- operator T() const {
- return read();
- };
- be_t<T> operator++() {
- write(read() + 1);
- return *this;
- };
- be_t<T> operator++(int) {
- write(read() + 1);
- return *this;
- };
- be_t<T> operator--() {
- write(read() - 1);
- return *this;
- };
- be_t<T> operator--(int) {
- write(read() - 1);
- return *this;
- };
- be_t<T>& operator+=(const T& t) {
- write(read() + t);
- return *this;
- };
- be_t<T>& operator-=(const T& t) {
- write(read() - t);
- return *this;
- };
- be_t<T>& operator&=(const be_t<T>& t) {
- m &= t.m;
- return *this;
- };
- be_t<T>& operator|=(const be_t<T>& t) {
- m |= t.m;
- return *this;
- };
-} __attribute__((packed));
-
-/* Define types of native endianness similar to the little and big endian
- * versions below. Not really necessary but useful occasionally to emphasize
- * endianness of data.
- */
-
-typedef int8_t int8_ne_t;
-typedef int16_t int16_ne_t;
-typedef int32_t int32_ne_t;
-typedef int64_t int64_ne_t;
-typedef u_int8_t u_int8_ne_t;
-typedef u_int16_t u_int16_ne_t;
-typedef u_int32_t u_int32_ne_t;
-typedef u_int64_t u_int64_ne_t;
-
-
-/* The classes work on their native endianness as well, but obviously
- * introduce some overhead. Use the faster typedefs to native types
- * therefore, unless you're debugging.
- */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-typedef int8_ne_t int8_le_t;
-typedef int16_ne_t int16_le_t;
-typedef int32_ne_t int32_le_t;
-typedef int64_ne_t int64_le_t;
-typedef u_int8_ne_t u_int8_le_t;
-typedef u_int16_ne_t u_int16_le_t;
-typedef u_int32_ne_t u_int32_le_t;
-typedef u_int64_ne_t u_int64_le_t;
-typedef int8_t int8_be_t;
-typedef be_t<int16_t> int16_be_t;
-typedef be_t<int32_t> int32_be_t;
-typedef be_t<int64_t> int64_be_t;
-typedef u_int8_t u_int8_be_t;
-typedef be_t<u_int16_t> u_int16_be_t;
-typedef be_t<u_int32_t> u_int32_be_t;
-typedef be_t<u_int64_t> u_int64_be_t;
-#else
-typedef int8_ne_t int8_be_t;
-typedef int16_ne_t int16_be_t;
-typedef int32_ne_t int32_be_t;
-typedef int64_ne_t int64_be_t;
-typedef u_int8_ne_t u_int8_be_t;
-typedef u_int16_ne_t u_int16_be_t;
-typedef u_int32_ne_t u_int32_be_t;
-typedef u_int64_ne_t u_int64_be_t;
-typedef int8_t int8_le_t;
-typedef le_t<int16_t> int16_le_t;
-typedef le_t<int32_t> int32_le_t;
-typedef le_t<int64_t> int64_le_t;
-typedef u_int8_t u_int8_le_t;
-typedef le_t<u_int16_t> u_int16_le_t;
-typedef le_t<u_int32_t> u_int32_le_t;
-typedef le_t<u_int64_t> u_int64_le_t;
-#endif
-
-#endif
+++ /dev/null
-/*
-* error.cc Error handling
-* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-// C++ includes
-
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-
-using std::ostringstream;
-using std::string;
-using std::endl;
-using std::ends;
-using std::cerr;
-
-// C includes
-
-#include <errno.h>
-#include <string.h>
-
-// local includes
-
-#include "error.h"
-
-void real_fail_neg( int eval, const char *eval_str, const char *func, const char *file, int line )
-{
- if ( eval < 0 )
- {
- string exc;
- ostringstream sb;
-
- sb << file << ":" << line << ": In function \"" << func << "\": \"" << eval_str << "\" evaluated to " << eval;
- if ( errno != 0 )
- sb << endl << file << ":" << line << ": errno: " << errno << " (" << strerror( errno ) << ")";
- sb << ends;
- exc = sb.str();
- cerr << exc << endl;
- throw exc;
- }
-}
-
-
-/** error handler for NULL result codes
-
- Whenever this is called with a NULL argument, it will throw an
- exception. Typically used with functions like malloc() and new().
-
-*/
-
-void real_fail_null( const void *eval, const char *eval_str, const char *func, const char *file, int line )
-{
- if ( eval == NULL )
- {
-
- string exc;
- ostringstream sb;
-
- sb << file << ":" << line << ": In function \"" << func << "\": " << eval_str << " is NULL" << ends;
- exc = sb.str();
- cerr << exc << endl;
- throw exc;
- }
-}
-
-
-void real_fail_if( bool eval, const char *eval_str, const char *func, const char *file, int line )
-{
- if ( eval == true )
- {
-
- string exc;
- ostringstream sb;
-
- sb << file << ":" << line << ": In function \"" << func << "\": condition \"" << eval_str << "\" is true";
- if ( errno != 0 )
- sb << endl << file << ":" << line << ": errno: " << errno << " (" << strerror( errno ) << ")";
- sb << ends;
- exc = sb.str();
- cerr << exc << endl;
- throw exc;
- }
-}
+++ /dev/null
-/*
-* error.h Error handling
-* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef _ERROR_H
-#define _ERROR_H 1
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- /*
- * Should check for gcc/g++ and version > 2.6 I suppose
- */
-#ifndef __ASSERT_FUNCTION
-# define __ASSERT_FUNCTION __PRETTY_FUNCTION__
-#endif
-
-#define fail_neg(eval) real_fail_neg (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
-#define fail_null(eval) real_fail_null (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
-#define fail_if(eval) real_fail_if (eval, #eval, __ASSERT_FUNCTION, __FILE__, __LINE__)
-
- void real_fail_neg ( int eval, const char * eval_str, const char * func, const char * file, int line );
- void real_fail_null ( const void * eval, const char * eval_str, const char * func, const char * file, int line );
- void real_fail_if ( bool eval, const char * eval_str, const char * func, const char * file, int line );
-
- extern void sigpipe_clear( );
- extern int sigpipe_get( );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_producer producer_kino_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( producer_type, "kino", producer_kino_init );
-}
+++ /dev/null
-/*
-* filehandler.cc -- saving DV data into different file formats
-* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "config.h"
-
-extern "C" {
-#include <framework/mlt_frame.h>
-}
-
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-
-using std::cerr;
-using std::endl;
-using std::ostringstream;
-using std::setw;
-using std::setfill;
-
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <assert.h>
-#include <time.h>
-#include <sys/time.h>
-#include <string.h>
-#include <stdlib.h>
-
-// libdv header files
-#ifdef HAVE_LIBDV
-#include <libdv/dv.h>
-#endif
-
-#include "filehandler.h"
-#include "error.h"
-#include "riff.h"
-#include "avi.h"
-
-FileTracker *FileTracker::instance = NULL;
-
-FileTracker::FileTracker( ) : mode( CAPTURE_MOVIE_APPEND )
-{
- cerr << ">> Constructing File Capture tracker" << endl;
-}
-
-FileTracker::~FileTracker( )
-{
- cerr << ">> Destroying File Capture tracker" << endl;
-}
-
-FileTracker &FileTracker::GetInstance( )
-{
- if ( instance == NULL )
- instance = new FileTracker();
-
- return *instance;
-}
-
-void FileTracker::SetMode( FileCaptureMode mode )
-{
- this->mode = mode;
-}
-
-FileCaptureMode FileTracker::GetMode( )
-{
- return this->mode;
-}
-
-char *FileTracker::Get( int index )
-{
- return list[ index ];
-}
-
-void FileTracker::Add( const char *file )
-{
- if ( this->mode != CAPTURE_IGNORE )
- {
- cerr << ">>>> Registering " << file << " with the tracker" << endl;
- list.push_back( strdup( file ) );
- }
-}
-
-unsigned int FileTracker::Size( )
-{
- return list.size();
-}
-
-void FileTracker::Clear( )
-{
- while ( Size() > 0 )
- {
- free( list[ Size() - 1 ] );
- list.pop_back( );
- }
- this->mode = CAPTURE_MOVIE_APPEND;
-}
-
-FileHandler::FileHandler() : done( false ), autoSplit( false ), maxFrameCount( 999999 ),
- framesWritten( 0 ), filename( "" )
-{
- /* empty body */
-}
-
-
-FileHandler::~FileHandler()
-{
- /* empty body */
-}
-
-
-bool FileHandler::GetAutoSplit() const
-{
- return autoSplit;
-}
-
-
-bool FileHandler::GetTimeStamp() const
-{
- return timeStamp;
-}
-
-
-string FileHandler::GetBaseName() const
-{
- return base;
-}
-
-
-string FileHandler::GetExtension() const
-{
- return extension;
-}
-
-
-int FileHandler::GetMaxFrameCount() const
-{
- return maxFrameCount;
-}
-
-off_t FileHandler::GetMaxFileSize() const
-{
- return maxFileSize;
-}
-
-string FileHandler::GetFilename() const
-{
- return filename;
-}
-
-
-void FileHandler::SetAutoSplit( bool flag )
-{
- autoSplit = flag;
-}
-
-
-void FileHandler::SetTimeStamp( bool flag )
-{
- timeStamp = flag;
-}
-
-
-void FileHandler::SetBaseName( const string& s )
-{
- base = s;
-}
-
-
-void FileHandler::SetMaxFrameCount( int count )
-{
- assert( count >= 0 );
- maxFrameCount = count;
-}
-
-
-void FileHandler::SetEveryNthFrame( int every )
-{
- assert ( every > 0 );
-
- everyNthFrame = every;
-}
-
-
-void FileHandler::SetMaxFileSize( off_t size )
-{
- assert ( size >= 0 );
- maxFileSize = size;
-}
-
-
-#if 0
-void FileHandler::SetSampleFrame( const Frame& sample )
-{
- /* empty body */
-}
-#endif
-
-bool FileHandler::Done()
-{
- return done;
-}
-
-#if 0
-bool FileHandler::WriteFrame( const Frame& frame )
-{
- static TimeCode prevTimeCode;
- TimeCode timeCode;
-
- /* If the user wants autosplit, start a new file if a
- new recording is detected. */
- prevTimeCode.sec = -1;
- frame.GetTimeCode( timeCode );
- int time_diff = timeCode.sec - prevTimeCode.sec;
- bool discontinuity = prevTimeCode.sec != -1 && ( time_diff > 1 || ( time_diff < 0 && time_diff > -59 ) );
- if ( FileIsOpen() && GetAutoSplit() == true && ( frame.IsNewRecording() || discontinuity ) )
- {
- Close();
- }
-
- if ( FileIsOpen() == false )
- {
-
- string filename;
- static int counter = 0;
-
- if ( GetTimeStamp() == true )
- {
- ostringstream sb, sb2;
- struct tm date;
- string recDate;
-
- if ( ! frame.GetRecordingDate( date ) )
- {
- struct timeval tv;
- struct timezone tz;
- gettimeofday( &tv, &tz );
- localtime_r( static_cast< const time_t * >( &tv.tv_sec ), &date );
- }
- sb << setfill( '0' )
- << setw( 4 ) << date.tm_year + 1900 << '.'
- << setw( 2 ) << date.tm_mon + 1 << '.'
- << setw( 2 ) << date.tm_mday << '_'
- << setw( 2 ) << date.tm_hour << '-'
- << setw( 2 ) << date.tm_min << '-'
- << setw( 2 ) << date.tm_sec;
- recDate = sb.str();
- sb2 << GetBaseName() << recDate << GetExtension();
- filename = sb2.str();
- cerr << ">>> Trying " << filename << endl;
- }
- else
- {
- struct stat stats;
- do
- {
- ostringstream sb;
- sb << GetBaseName() << setfill( '0' ) << setw( 3 ) << ++ counter << GetExtension();
- filename = sb.str();
- cerr << ">>> Trying " << filename << endl;
- }
- while ( stat( filename.c_str(), &stats ) == 0 );
- }
-
- SetSampleFrame( frame );
- if ( Create( filename ) == false )
- {
- cerr << ">>> Error creating file!" << endl;
- return false;
- }
- framesWritten = 0;
- framesToSkip = 0;
- }
-
- /* write frame */
-
- if ( framesToSkip == 0 )
- {
- if ( 0 > Write( frame ) )
- {
- cerr << ">>> Error writing frame!" << endl;
- return false;
- }
- framesToSkip = everyNthFrame;
- ++framesWritten;
- }
- framesToSkip--;
-
- /* If the frame count is exceeded, close the current file.
- If the autosplit flag is set, a new file will be created in the next iteration.
- If the flag is not set, we are done. */
-
- if ( ( GetMaxFrameCount() > 0 ) &&
- ( framesWritten >= GetMaxFrameCount() ) )
- {
- Close();
- done = !GetAutoSplit();
- }
-
- /* If the file size could be exceeded by another frame, close the current file.
- If the autosplit flag is set, a new file will be created on the next iteration.
- If the flag is not set, we are done. */
- /* not exact, but should be good enough to prevent going over. */
- if ( FileIsOpen() )
- {
- AudioInfo info;
- frame.GetAudioInfo( info );
- if ( ( GetFileSize() > 0 ) && ( GetMaxFileSize() > 0 ) &&
- ( GetFileSize() + frame.GetFrameSize() + info.samples * 4 + 12 )
- >= GetMaxFileSize() )
- { // 12 = sizeof chunk metadata
- Close();
- done = !GetAutoSplit();
- }
- }
- prevTimeCode.sec = timeCode.sec;
- return true;
-}
-#endif
-
-RawHandler::RawHandler() : fd( -1 )
-{
- extension = ".dv";
-}
-
-
-RawHandler::~RawHandler()
-{
- Close();
-}
-
-
-bool RawHandler::FileIsOpen()
-{
- return fd != -1;
-}
-
-
-bool RawHandler::Create( const string& filename )
-{
- fd = open( filename.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_NONBLOCK, 0644 );
- if ( fd != -1 )
- {
- FileTracker::GetInstance().Add( filename.c_str() );
- this->filename = filename;
- }
- return ( fd != -1 );
-}
-
-
-#if 0
-int RawHandler::Write( const Frame& frame )
-{
- int result = write( fd, frame.data, frame.GetFrameSize() );
- return result;
-}
-#endif
-
-int RawHandler::Close()
-{
- if ( fd != -1 )
- {
- close( fd );
- fd = -1;
- }
- return 0;
-}
-
-
-off_t RawHandler::GetFileSize()
-{
- struct stat file_status;
- fstat( fd, &file_status );
- return file_status.st_size;
-}
-
-int RawHandler::GetTotalFrames()
-{
- return GetFileSize() / ( 480 * numBlocks );
-}
-
-
-bool RawHandler::Open( const char *s )
-{
- unsigned char data[ 4 ];
- assert( fd == -1 );
- fd = open( s, O_RDONLY | O_NONBLOCK );
- if ( fd < 0 )
- return false;
- if ( read( fd, data, 4 ) < 0 )
- return false;
- lseek( fd, 0, SEEK_SET );
- numBlocks = ( ( data[ 3 ] & 0x80 ) == 0 ) ? 250 : 300;
- filename = s;
- return true;
-
-}
-
-int RawHandler::GetFrame( uint8_t *data, int frameNum )
-{
- assert( fd != -1 );
- int size = 480 * numBlocks;
- if ( frameNum < 0 )
- return -1;
- off_t offset = ( ( off_t ) frameNum * ( off_t ) size );
- fail_if( lseek( fd, offset, SEEK_SET ) == ( off_t ) - 1 );
- if ( read( fd, data, size ) > 0 )
- return 0;
- else
- return -1;
-}
-
-
-/***************************************************************************/
-
-
-AVIHandler::AVIHandler( int format ) : avi( NULL ), aviFormat( format ), isOpenDML( false ),
- fccHandler( make_fourcc( "dvsd" ) ), channels( 2 ), isFullyInitialized( false ),
- audioBuffer( NULL )
-{
- extension = ".avi";
- for ( int c = 0; c < 4; c++ )
- audioChannels[ c ] = NULL;
-}
-
-
-AVIHandler::~AVIHandler()
-{
- if ( audioBuffer != NULL )
- {
- delete audioBuffer;
- audioBuffer = NULL;
- }
- for ( int c = 0; c < 4; c++ )
- {
- if ( audioChannels[ c ] != NULL )
- {
- delete audioChannels[ c ];
- audioChannels[ c ] = NULL;
- }
- }
-
- delete avi;
-}
-
-#if 0
-void AVIHandler::SetSampleFrame( const Frame& sample )
-{
- Pack pack;
- sample.GetAudioInfo( audioInfo );
- sample.GetVideoInfo( videoInfo );
-
- sample.GetAAUXPack( 0x50, pack );
- dvinfo.dwDVAAuxSrc = *( DWORD* ) ( pack.data + 1 );
- sample.GetAAUXPack( 0x51, pack );
- dvinfo.dwDVAAuxCtl = *( DWORD* ) ( pack.data + 1 );
-
- sample.GetAAUXPack( 0x52, pack );
- dvinfo.dwDVAAuxSrc1 = *( DWORD* ) ( pack.data + 1 );
- sample.GetAAUXPack( 0x53, pack );
- dvinfo.dwDVAAuxCtl1 = *( DWORD* ) ( pack.data + 1 );
-
- sample.GetVAUXPack( 0x60, pack );
- dvinfo.dwDVVAuxSrc = *( DWORD* ) ( pack.data + 1 );
- sample.GetVAUXPack( 0x61, pack );
- dvinfo.dwDVVAuxCtl = *( DWORD* ) ( pack.data + 1 );
-
-#ifdef WITH_LIBDV
-
- if ( sample.decoder->std == e_dv_std_smpte_314m )
- fccHandler = make_fourcc( "dv25" );
-#endif
-}
-#endif
-
-bool AVIHandler::FileIsOpen()
-{
- return avi != NULL;
-}
-
-
-bool AVIHandler::Create( const string& filename )
-{
- assert( avi == NULL );
-
- switch ( aviFormat )
- {
-
- case AVI_DV1_FORMAT:
- fail_null( avi = new AVI1File );
- if ( avi->Create( filename.c_str() ) == false )
- return false;
- //avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency, AVI_LARGE_INDEX );
- break;
-
- case AVI_DV2_FORMAT:
- fail_null( avi = new AVI2File );
- if ( avi->Create( filename.c_str() ) == false )
- return false;
- //if ( GetOpenDML() )
- //avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
- //( AVI_SMALL_INDEX | AVI_LARGE_INDEX ) );
- //else
- //avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
- //( AVI_SMALL_INDEX ) );
- break;
-
- default:
- assert( aviFormat == AVI_DV1_FORMAT || aviFormat == AVI_DV2_FORMAT );
- }
-
- avi->setDVINFO( dvinfo );
- avi->setFccHandler( make_fourcc( "iavs" ), fccHandler );
- avi->setFccHandler( make_fourcc( "vids" ), fccHandler );
- this->filename = filename;
- FileTracker::GetInstance().Add( filename.c_str() );
- return ( avi != NULL );
-}
-
-#if 0
-int AVIHandler::Write( const Frame& frame )
-{
- assert( avi != NULL );
- try
- {
- return avi->WriteFrame( frame ) ? 0 : -1;
- }
- catch (...)
- {
- return -1;
- }
-}
-#endif
-
-int AVIHandler::Close()
-{
- if ( avi != NULL )
- {
- avi->WriteRIFF();
- delete avi;
- avi = NULL;
- }
- if ( audioBuffer != NULL )
- {
- delete audioBuffer;
- audioBuffer = NULL;
- }
- for ( int c = 0; c < 4; c++ )
- {
- if ( audioChannels[ c ] != NULL )
- {
- delete audioChannels[ c ];
- audioChannels[ c ] = NULL;
- }
- }
- isFullyInitialized = false;
- return 0;
-}
-
-off_t AVIHandler::GetFileSize()
-{
- return avi->GetFileSize();
-}
-
-int AVIHandler::GetTotalFrames()
-{
- return avi->GetTotalFrames();
-}
-
-
-bool AVIHandler::Open( const char *s )
-{
- assert( avi == NULL );
- fail_null( avi = new AVI1File );
- if ( avi->Open( s ) )
- {
- avi->ParseRIFF();
- if ( ! (
- avi->verifyStreamFormat( make_fourcc( "dvsd" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "DVSD" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "dvcs" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "DVCS" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "dvcp" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "DVCP" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "CDVC" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "cdvc" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "DV25" ) ) ||
- avi->verifyStreamFormat( make_fourcc( "dv25" ) ) ) )
- return false;
- avi->ReadIndex();
- if ( avi->verifyStream( make_fourcc( "auds" ) ) )
- aviFormat = AVI_DV2_FORMAT;
- else
- aviFormat = AVI_DV1_FORMAT;
- isOpenDML = avi->isOpenDML();
- filename = s;
- return true;
- }
- else
- return false;
-
-}
-
-int AVIHandler::GetFrame( uint8_t *data, int frameNum )
-{
- int result = avi->GetDVFrame( data, frameNum );
-#if 0
- if ( result == 0 )
- {
- /* get the audio from the audio stream, if available */
- if ( aviFormat == AVI_DV2_FORMAT )
- {
- WAVEFORMATEX wav;
-
- if ( ! isFullyInitialized &&
- avi->getStreamFormat( ( void* ) &wav, make_fourcc( "auds" ) ) )
- {
- if ( channels > 0 && channels < 5 )
- {
- // Allocate interleaved audio buffer
- audioBuffer = new int16_t[ 2 * DV_AUDIO_MAX_SAMPLES * channels ];
-
- // Allocate non-interleaved audio buffers
- for ( int c = 0; c < channels; c++ )
- audioChannels[ c ] = new int16_t[ 2 * DV_AUDIO_MAX_SAMPLES ];
-
- // Get the audio parameters from AVI for subsequent calls to method
- audioInfo.channels = wav.nChannels;
- audioInfo.frequency = wav.nSamplesPerSec;
-
- // Skip initialization on subsequent calls to method
- isFullyInitialized = true;
- cerr << ">>> using audio from separate AVI audio stream" << endl;
- }
- }
-
- // Get the frame from AVI
- int n = avi->getFrame( audioBuffer, frameNum, make_fourcc( "01wb" ) );
- if ( n > 0 )
- {
- // Temporary pointer to audio scratch buffer
- int16_t * s = audioBuffer;
-
- // Determine samples in this frame
- audioInfo.samples = n / audioInfo.channels / sizeof( int16_t );
-
- // Convert interleaved audio into non-interleaved
- for ( int n = 0; n < audioInfo.samples; ++n )
- for ( int i = 0; i < audioInfo.channels; i++ )
- audioChannels[ i ][ n ] = *s++;
-
- // Write interleaved audio into frame
- frame.EncodeAudio( audioInfo, audioChannels );
- }
- }
-
- // Parse important metadata in DV bitstream
- frame.ExtractHeader();
- }
-#endif
- return result;
-}
-
-
-void AVIHandler::SetOpenDML( bool flag )
-{
- isOpenDML = flag;
-}
-
-
-bool AVIHandler::GetOpenDML() const
-{
- return isOpenDML;
-}
-
-
-/***************************************************************************/
-
-#ifdef HAVE_LIBQUICKTIME
-
-#ifndef HAVE_LIBDV
-#define DV_AUDIO_MAX_SAMPLES 1944
-#endif
-
-// Missing fourcc's in libquicktime (allows compilation)
-#ifndef QUICKTIME_DV_AVID
-#define QUICKTIME_DV_AVID "AVdv"
-#endif
-
-#ifndef QUICKTIME_DV_AVID_A
-#define QUICKTIME_DV_AVID_A "dvcp"
-#endif
-
-#ifndef QUICKTIME_DVCPRO
-#define QUICKTIME_DVCPRO "dvpp"
-#endif
-
-QtHandler::QtHandler() : fd( NULL )
-{
- extension = ".mov";
- Init();
-}
-
-
-QtHandler::~QtHandler()
-{
- Close();
-}
-
-void QtHandler::Init()
-{
- if ( fd != NULL )
- Close();
-
- fd = NULL;
- samplingRate = 0;
- samplesPerBuffer = 0;
- channels = 2;
- audioBuffer = NULL;
- audioChannelBuffer = NULL;
- isFullyInitialized = false;
-}
-
-
-bool QtHandler::FileIsOpen()
-{
- return fd != NULL;
-}
-
-
-bool QtHandler::Create( const string& filename )
-{
- Init();
-
- if ( open( filename.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_NONBLOCK, 0644 ) != -1 )
- {
- fd = quicktime_open( const_cast<char*>( filename.c_str() ), 0, 1 );
- if ( fd != NULL )
- FileTracker::GetInstance().Add( filename.c_str() );
- }
- else
- return false;
- this->filename = filename;
- return true;
-}
-
-void QtHandler::AllocateAudioBuffers()
-{
- if ( channels > 0 && channels < 5 )
- {
- audioBufferSize = DV_AUDIO_MAX_SAMPLES * 2;
- audioBuffer = new int16_t[ audioBufferSize * channels ];
-
- audioChannelBuffer = new short int * [ channels ];
- for ( int c = 0; c < channels; c++ )
- audioChannelBuffer[ c ] = new short int[ audioBufferSize ];
- isFullyInitialized = true;
- }
-}
-
-inline void QtHandler::DeinterlaceStereo16( void* pInput, int iBytes,
- void* pLOutput, void* pROutput )
-{
- short int * piSampleInput = ( short int* ) pInput;
- short int* piSampleLOutput = ( short int* ) pLOutput;
- short int* piSampleROutput = ( short int* ) pROutput;
-
- while ( ( char* ) piSampleInput < ( ( char* ) pInput + iBytes ) )
- {
- *piSampleLOutput++ = *piSampleInput++;
- *piSampleROutput++ = *piSampleInput++;
- }
-}
-
-#if 0
-int QtHandler::Write( const Frame& frame )
-{
- if ( ! isFullyInitialized )
- {
- AudioInfo audio;
-
- if ( frame.GetAudioInfo( audio ) )
- {
- channels = 2;
- quicktime_set_audio( fd, channels, audio.frequency, 16, QUICKTIME_TWOS );
- }
- else
- {
- channels = 0;
- }
-
- quicktime_set_video( fd, 1, 720, frame.IsPAL() ? 576 : 480,
- frame.GetFrameRate(), QUICKTIME_DV );
- AllocateAudioBuffers();
- }
-
- int result = quicktime_write_frame( fd, const_cast<unsigned char*>( frame.data ),
- frame.GetFrameSize(), 0 );
-
- if ( channels > 0 )
- {
- AudioInfo audio;
- if ( frame.GetAudioInfo( audio ) && ( unsigned int ) audio.samples < audioBufferSize )
- {
- long bytesRead = frame.ExtractAudio( audioBuffer );
-
- DeinterlaceStereo16( audioBuffer, bytesRead,
- audioChannelBuffer[ 0 ],
- audioChannelBuffer[ 1 ] );
-
- quicktime_encode_audio( fd, audioChannelBuffer, NULL, audio.samples );
- }
- }
- return result;
-}
-#endif
-
-int QtHandler::Close()
-{
- if ( fd != NULL )
- {
- quicktime_close( fd );
- fd = NULL;
- }
- if ( audioBuffer != NULL )
- {
- delete audioBuffer;
- audioBuffer = NULL;
- }
- if ( audioChannelBuffer != NULL )
- {
- for ( int c = 0; c < channels; c++ )
- delete audioChannelBuffer[ c ];
- delete audioChannelBuffer;
- audioChannelBuffer = NULL;
- }
- return 0;
-}
-
-
-off_t QtHandler::GetFileSize()
-{
- struct stat file_status;
- stat( filename.c_str(), &file_status );
- return file_status.st_size;
-}
-
-
-int QtHandler::GetTotalFrames()
-{
- return ( int ) quicktime_video_length( fd, 0 );
-}
-
-
-bool QtHandler::Open( const char *s )
-{
- Init();
-
- fd = quicktime_open( s, 1, 0 );
- if ( fd == NULL )
- {
- fprintf( stderr, "Error opening: %s\n", s );
- return false;
- }
-
- if ( quicktime_has_video( fd ) <= 0 )
- {
- fprintf( stderr, "There must be at least one video track in the input file (%s).\n",
- s );
- Close();
- return false;
- }
- char * fcc = quicktime_video_compressor( fd, 0 );
- if ( strncmp( fcc, QUICKTIME_DV, 4 ) != 0 &&
- strncmp( fcc, QUICKTIME_DV_AVID, 4 ) != 0 &&
- strncmp( fcc, QUICKTIME_DV_AVID_A, 4 ) != 0 &&
- strncmp( fcc, QUICKTIME_DVCPRO, 4 ) != 0 )
- {
- Close();
- return false;
- }
- if ( quicktime_has_audio( fd ) )
- channels = quicktime_track_channels( fd, 0 );
- filename = s;
- return true;
-}
-
-int QtHandler::GetFrame( uint8_t *data, int frameNum )
-{
- assert( fd != NULL );
-
- quicktime_set_video_position( fd, frameNum, 0 );
- quicktime_read_frame( fd, data, 0 );
-
-#ifdef HAVE_LIBDV
- if ( quicktime_has_audio( fd ) )
- {
- if ( ! isFullyInitialized )
- AllocateAudioBuffers();
-
- // Fetch the frequency of the audio track and calc number of samples needed
- int frequency = quicktime_sample_rate( fd, 0 );
- float fps = ( data[ 3 ] & 0x80 ) ? 25.0f : 29.97f;
- int samples = mlt_sample_calculator( fps, frequency, frameNum );
- int64_t seek = mlt_sample_calculator_to_now( fps, frequency, frameNum );
-
- // Obtain a dv encoder and initialise it with minimal info
- dv_encoder_t *encoder = dv_encoder_new( 0, 0, 0 );
- encoder->isPAL = ( data[ 3 ] & 0x80 );
- encoder->samples_this_frame = samples;
-
- // Seek to the calculated position and decode
- quicktime_set_audio_position( fd, seek, 0 );
- lqt_decode_audio( fd, audioChannelBuffer, NULL, (long) samples );
-
- // Encode the audio on the frame and done
- dv_encode_full_audio( encoder, audioChannelBuffer, channels, frequency, data );
- dv_encoder_free( encoder );
- }
-#endif
-
- return 0;
-}
-#endif
+++ /dev/null
-/*
-* filehandler.h
-* Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef _FILEHANDLER_H
-#define _FILEHANDLER_H
-
-// enum { PAL_FORMAT, NTSC_FORMAT, AVI_DV1_FORMAT, AVI_DV2_FORMAT, QT_FORMAT, RAW_FORMAT, TEST_FORMAT, UNDEFINED };
-
-#include <vector>
-using std::vector;
-
-#include <string>
-using std::string;
-
-#include "riff.h"
-#include "avi.h"
-#include <sys/types.h>
-#include <stdint.h>
-
-enum { AVI, PLAYLIST, RAW_DV, QT, UNKNOWN_FORMAT };
-enum { PAL_FORMAT, NTSC_FORMAT, AVI_DV1_FORMAT, AVI_DV2_FORMAT, QT_FORMAT, RAW_FORMAT, TEST_FORMAT, UNDEFINED };
-enum { DISPLAY_XX, DISPLAY_GDKRGB, DISPLAY_GDKRGB32, DISPLAY_XV, DISPLAY_SDL };
-
-enum { NORM_UNSPECIFIED=0, NORM_PAL=1, NORM_NTSC=2 };
-enum { AUDIO_32KHZ=0, AUDIO_44KHZ=1, AUDIO_48KHZ=2 };
-enum { ASPECT_43=0, ASPECT_169=1 };
-
-enum FileCaptureMode {
- CAPTURE_IGNORE,
- CAPTURE_FRAME_APPEND,
- CAPTURE_FRAME_INSERT,
- CAPTURE_MOVIE_APPEND
-};
-
-class FileTracker
-{
-protected:
- FileTracker();
- ~FileTracker();
-public:
- static FileTracker &GetInstance( );
- void SetMode( FileCaptureMode );
- FileCaptureMode GetMode( );
- unsigned int Size();
- char *Get( int );
- void Add( const char * );
- void Clear( );
-private:
- static FileTracker *instance;
- vector <char *> list;
- FileCaptureMode mode;
-};
-
-class FileHandler
-{
-public:
-
- FileHandler();
- virtual ~FileHandler();
-
- virtual bool GetAutoSplit() const;
- virtual bool GetTimeStamp() const;
- virtual string GetBaseName() const;
- virtual string GetExtension() const;
- virtual int GetMaxFrameCount() const;
- virtual off_t GetMaxFileSize() const;
- virtual off_t GetFileSize() = 0;
- virtual int GetTotalFrames() = 0;
- virtual string GetFilename() const;
-
- virtual void SetAutoSplit( bool );
- virtual void SetTimeStamp( bool );
- virtual void SetBaseName( const string& base );
- virtual void SetMaxFrameCount( int );
- virtual void SetEveryNthFrame( int );
- virtual void SetMaxFileSize( off_t );
- //virtual void SetSampleFrame( const Frame& sample );
-
- //virtual bool WriteFrame( const Frame& frame );
- virtual bool FileIsOpen() = 0;
- virtual bool Create( const string& filename ) = 0;
- //virtual int Write( const Frame& frame ) = 0;
- virtual int Close() = 0;
- virtual bool Done( void );
-
- virtual bool Open( const char *s ) = 0;
- virtual int GetFrame( uint8_t *data, int frameNum ) = 0;
- int GetFramesWritten() const
- {
- return framesWritten;
- }
-
-protected:
- bool done;
- bool autoSplit;
- bool timeStamp;
- int maxFrameCount;
- int framesWritten;
- int everyNthFrame;
- int framesToSkip;
- off_t maxFileSize;
- string base;
- string extension;
- string filename;
-};
-
-
-class RawHandler: public FileHandler
-{
-public:
- int fd;
-
- RawHandler();
- ~RawHandler();
-
- bool FileIsOpen();
- bool Create( const string& filename );
- //int Write( const Frame& frame );
- int Close();
- off_t GetFileSize();
- int GetTotalFrames();
- bool Open( const char *s );
- int GetFrame( uint8_t *data, int frameNum );
-private:
- int numBlocks;
-};
-
-
-class AVIHandler: public FileHandler
-{
-public:
- AVIHandler( int format = AVI_DV1_FORMAT );
- ~AVIHandler();
-
- //void SetSampleFrame( const Frame& sample );
- bool FileIsOpen();
- bool Create( const string& filename );
- //int Write( const Frame& frame );
- int Close();
- off_t GetFileSize();
- int GetTotalFrames();
- bool Open( const char *s );
- int GetFrame( uint8_t *data, int frameNum );
- bool GetOpenDML() const;
- void SetOpenDML( bool );
- int GetFormat() const
- {
- return aviFormat;
- }
-
-protected:
- AVIFile *avi;
- int aviFormat;
- //AudioInfo audioInfo;
- //VideoInfo videoInfo;
- bool isOpenDML;
- DVINFO dvinfo;
- FOURCC fccHandler;
- int channels;
- bool isFullyInitialized;
- int16_t *audioBuffer;
- int16_t *audioChannels[ 4 ];
-};
-
-
-#ifdef HAVE_LIBQUICKTIME
-#include <lqt.h>
-
-class QtHandler: public FileHandler
-{
-public:
- QtHandler();
- ~QtHandler();
-
- bool FileIsOpen();
- bool Create( const string& filename );
- //int Write( const Frame& frame );
- int Close();
- off_t GetFileSize();
- int GetTotalFrames();
- bool Open( const char *s );
- int GetFrame( uint8_t *data, int frameNum );
- void AllocateAudioBuffers();
-
-private:
- quicktime_t *fd;
- long samplingRate;
- int samplesPerBuffer;
- int channels;
- bool isFullyInitialized;
- unsigned int audioBufferSize;
- int16_t *audioBuffer;
- short int** audioChannelBuffer;
-
- void Init();
- inline void DeinterlaceStereo16( void* pInput, int iBytes, void* pLOutput, void* pROutput );
-
-};
-#endif
-
-#endif
+++ /dev/null
-/*
- * kino_wrapper.cc -- c wrapper for kino file handler
- * Copyright (C) 2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "kino_wrapper.h"
-#include "filehandler.h"
-
-extern "C"
-{
-
-#include <framework/mlt_pool.h>
-
-struct kino_wrapper_s
-{
- FileHandler *handler;
- int is_pal;
-};
-
-kino_wrapper kino_wrapper_init( )
-{
- kino_wrapper self = ( kino_wrapper )malloc( sizeof( kino_wrapper_s ) );
- if ( self != NULL )
- self->handler = NULL;
- return self;
-}
-
-int kino_wrapper_open( kino_wrapper self, char *src )
-{
- if ( self != NULL )
- {
- // Rough file determination based on file type
- if ( strncasecmp( strrchr( src, '.' ), ".avi", 4 ) == 0 )
- self->handler = new AVIHandler( );
- else if ( strncasecmp( strrchr( src, '.' ), ".dv", 3 ) == 0 || strncasecmp( strrchr( src, '.' ), ".dif", 4 ) == 0 )
- self->handler = new RawHandler( );
- #ifdef HAVE_LIBQUICKTIME
- else if ( strncasecmp( strrchr( src, '.' ), ".mov", 4 ) == 0 )
- self->handler = new QtHandler( );
- #endif
-
- // Open the file if we have a handler
- if ( self->handler != NULL )
- if ( !self->handler->Open( src ) )
- self = NULL;
-
- // Check the first frame to see if it's PAL or NTSC
- if ( self != NULL && self->handler != NULL )
- {
- uint8_t *data = ( uint8_t * )mlt_pool_alloc( 144000 );
- if ( self->handler->GetFrame( data, 0 ) == 0 )
- self->is_pal = data[3] & 0x80;
- else
- self = NULL;
- mlt_pool_release( data );
- }
- }
-
- return kino_wrapper_is_open( self );
-}
-
-int kino_wrapper_get_frame_count( kino_wrapper self )
-{
- return self != NULL && self->handler != NULL ? self->handler->GetTotalFrames( ) : 0;
-}
-
-int kino_wrapper_is_open( kino_wrapper self )
-{
- return self != NULL && self->handler != NULL ? self->handler->FileIsOpen( ) : 0;
-}
-
-int kino_wrapper_is_pal( kino_wrapper self )
-{
- return self != NULL ? self->is_pal : 0;
-}
-
-int kino_wrapper_get_frame( kino_wrapper self, uint8_t *data, int index )
-{
- return self != NULL && self->handler != NULL ? !self->handler->GetFrame( data, index ) : 0;
-}
-
-void kino_wrapper_close( kino_wrapper self )
-{
- if ( self )
- delete self->handler;
- free( self );
-}
-
-}
-
-
+++ /dev/null
-/*
- * kino_wrapper.h -- c wrapper for kino file handler
- * Copyright (C) 2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef MLT_PRODUCER_KINO_WRAPPER_H_
-#define MLT_PRODUCER_KINO_WRAPPER_H_
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef struct kino_wrapper_s *kino_wrapper;
-
-extern kino_wrapper kino_wrapper_init( );
-extern int kino_wrapper_open( kino_wrapper, char * );
-extern int kino_wrapper_is_open( kino_wrapper );
-extern int kino_wrapper_is_pal( kino_wrapper );
-extern int kino_wrapper_get_frame_count( kino_wrapper );
-extern int kino_wrapper_get_frame( kino_wrapper, uint8_t *, int );
-extern void kino_wrapper_close( kino_wrapper );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/*
- * producer_kino.c -- a DV file format parser
- * Copyright (C) 2005 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_deque.h>
-#include <framework/mlt_factory.h>
-#include "kino_wrapper.h"
-
-/* NB: This is an abstract producer - it provides no codec support whatsoever. */
-
-#define FRAME_SIZE_525_60 10 * 150 * 80
-#define FRAME_SIZE_625_50 12 * 150 * 80
-
-typedef struct producer_kino_s *producer_kino;
-
-struct producer_kino_s
-{
- struct mlt_producer_s parent;
- kino_wrapper wrapper;
-};
-
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_kino_init( mlt_profile profile, mlt_service_type type, const char *id, char *filename )
-{
- kino_wrapper wrapper = kino_wrapper_init( );
-
- if ( kino_wrapper_open( wrapper, filename ) )
- {
- producer_kino this = calloc( sizeof( struct producer_kino_s ), 1 );
-
- if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- mlt_producer producer = &this->parent;
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- double fps = kino_wrapper_is_pal( wrapper ) ? 25 : 30000.0 / 1001.0;
-
- // Assign the wrapper
- this->wrapper = wrapper;
-
- // Pass wrapper properties (frame rate, count etc)
- mlt_properties_set_position( properties, "length", kino_wrapper_get_frame_count( wrapper ) );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", kino_wrapper_get_frame_count( wrapper ) - 1 );
- mlt_properties_set_double( properties, "real_fps", fps );
- mlt_properties_set( properties, "resource", filename );
-
- // Register transport implementation with the producer
- producer->close = ( mlt_destructor )producer_close;
-
- // Register our get_frame implementation with the producer
- producer->get_frame = producer_get_frame;
-
- // Return the producer
- return producer;
- }
- free( this );
- }
-
- kino_wrapper_close( wrapper );
-
- return NULL;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- producer_kino this = producer->child;
- uint8_t *data = mlt_pool_alloc( FRAME_SIZE_625_50 );
-
- // Obtain the current frame number
- uint64_t position = mlt_producer_frame( producer );
-
- // Create an empty frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- // Seek and fetch
- if ( kino_wrapper_get_frame( this->wrapper, data, position ) )
- {
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Determine if we're PAL or NTSC
- int is_pal = kino_wrapper_is_pal( this->wrapper );
-
- // Pass the dv data
- mlt_properties_set_data( properties, "dv_data", data, FRAME_SIZE_625_50, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Update other info on the frame
- mlt_properties_set_int( properties, "width", 720 );
- mlt_properties_set_int( properties, "height", is_pal ? 576 : 480 );
- mlt_properties_set_int( properties, "top_field_first", is_pal ? 0 : ( data[ 5 ] & 0x07 ) == 0 ? 0 : 1 );
- }
- else
- {
- mlt_pool_release( data );
- }
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- if ( parent != NULL )
- {
- // Obtain this
- producer_kino this = parent->child;
-
- // Close the file
- if ( this != NULL )
- kino_wrapper_close( this->wrapper );
-
- // Close the parent
- parent->close = NULL;
- mlt_producer_close( parent );
-
- // Free the memory
- free( this );
- }
-}
+++ /dev/null
-/*
-* riff.cc library for RIFF file format i/o
-* Copyright (C) 2000 - 2002 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*
-* Tag: $Name$
-*
-* Change log:
-*
-* $Log$
-* Revision 1.3 2005/07/25 14:41:29 lilo_booter
-* + Minor correction for entry length being less than the data length
-*
-* Revision 1.2 2005/07/25 07:21:39 lilo_booter
-* + fixes for opendml dv avi
-*
-* Revision 1.1 2005/04/15 14:28:26 lilo_booter
-* Initial version
-*
-* Revision 1.18 2005/04/01 23:43:10 ddennedy
-* apply endian fixes from Daniel Kobras
-*
-* Revision 1.17 2004/10/11 01:37:11 ddennedy
-* mutex safety locks in RIFF and AVI classes, type 2 AVI optimization, mencoder export script
-*
-* Revision 1.16 2003/11/25 23:01:24 ddennedy
-* cleanup and a few bugfixes
-*
-* Revision 1.15 2003/10/21 16:34:34 ddennedy
-* GNOME2 port phase 1: initial checkin
-*
-* Revision 1.13.2.3 2003/08/26 20:39:00 ddennedy
-* relocate mutex unlock and add assert includes
-*
-* Revision 1.13.2.2 2003/01/28 12:54:13 lilo_booter
-* New 'no change' image transition
-*
-* Revision 1.13.2.1 2002/11/25 04:48:31 ddennedy
-* bugfix to report errors when loading files
-*
-* Revision 1.13 2002/09/13 06:49:49 ddennedy
-* build update, cleanup, bugfixes
-*
-* Revision 1.12 2002/04/21 06:36:40 ddennedy
-* kindler avc and 1394 bus reset support in catpure page, honor max file size
-*
-* Revision 1.11 2002/04/09 06:53:42 ddennedy
-* cleanup, new libdv 0.9.5, large AVI, dnd storyboard
-*
-* Revision 1.4 2002/03/25 21:34:25 arne
-* Support for large (64 bit) files mostly completed
-*
-* Revision 1.3 2002/03/10 21:28:29 arne
-* release 1.1b1, 64 bit support for type 1 avis
-*
-* Revision 1.2 2002/03/04 19:22:43 arne
-* updated to latest Kino avi code
-*
-* Revision 1.1.1.1 2002/03/03 19:08:08 arne
-* import of version 1.01
-*
-*/
-
-#include "config.h"
-
-// C++ includes
-
-#include <string>
-//#include <stdio.h>
-#include <iostream>
-#include <iomanip>
-#ifndef __FreeBSD__
-#include <byteswap.h>
-#endif /* __FreeBSD__ */
-
-using std::cout;
-using std::hex;
-using std::dec;
-using std::setw;
-using std::setfill;
-using std::endl;
-
-// C includes
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-
-// local includes
-
-#include "error.h"
-#include "riff.h"
-
-
-/** make a 32 bit "string-id"
-
- \param s a pointer to 4 chars
- \return the 32 bit "string id"
- \bugs It is not checked whether we really have 4 characters
-
- Some compilers understand constants like int id = 'ABCD'; but I
- could not get it working on the gcc compiler so I had to use this
- workaround. We can now use id = make_fourcc("ABCD") instead. */
-
-FOURCC make_fourcc( const char *s )
-{
- if ( s[ 0 ] == 0 )
- return 0;
- else
- return *( ( FOURCC* ) s );
-}
-
-
-RIFFDirEntry::RIFFDirEntry()
-{}
-
-
-RIFFDirEntry::RIFFDirEntry ( FOURCC t, FOURCC n, int l, int o, int p ) : type( t ), name( n ), length( l ), offset( o ), parent( p ), written( 0 )
-{}
-
-
-/** Creates the object without an output file.
-
-*/
-
-RIFFFile::RIFFFile() : fd( -1 )
-{
- pthread_mutex_init( &file_mutex, NULL );
-}
-
-
-/* Copy constructor
-
- Duplicate the file descriptor
-*/
-
-RIFFFile::RIFFFile( const RIFFFile& riff ) : fd( -1 )
-{
- if ( riff.fd != -1 )
- {
- fd = dup( riff.fd );
- }
- directory = riff.directory;
-}
-
-
-/** Destroys the object.
-
- If it has an associated opened file, close it. */
-
-RIFFFile::~RIFFFile()
-{
- Close();
- pthread_mutex_destroy( &file_mutex );
-}
-
-
-RIFFFile& RIFFFile::operator=( const RIFFFile& riff )
-{
- if ( fd != riff.fd )
- {
- Close();
- if ( riff.fd != -1 )
- {
- fd = dup( riff.fd );
- }
- directory = riff.directory;
- }
- return *this;
-}
-
-
-/** Creates or truncates the file.
-
- \param s the filename
-*/
-
-bool RIFFFile::Create( const char *s )
-{
- fd = open( s, O_RDWR | O_NONBLOCK | O_CREAT | O_TRUNC, 00644 );
-
- if ( fd == -1 )
- return false;
- else
- return true;
-}
-
-
-/** Opens the file read only.
-
- \param s the filename
-*/
-
-bool RIFFFile::Open( const char *s )
-{
- fd = open( s, O_RDONLY | O_NONBLOCK );
-
- if ( fd == -1 )
- return false;
- else
- return true;
-}
-
-
-/** Destroys the object.
-
- If it has an associated opened file, close it. */
-
-void RIFFFile::Close()
-{
- if ( fd != -1 )
- {
- close( fd );
- fd = -1;
- }
-}
-
-
-/** Adds an entry to the list of containers.
-
- \param type the type of this entry
- \param name the name
- \param length the length of the data in the container
- \param list the container in which this object is contained.
- \return the ID of the newly created entry
-
- The topmost object is not contained in any other container. Use
- the special ID RIFF_NO_PARENT to create the topmost object. */
-
-int RIFFFile::AddDirectoryEntry( FOURCC type, FOURCC name, off_t length, int list )
-{
- /* Put all parameters in an RIFFDirEntry object. The offset is
- currently unknown. */
-
- RIFFDirEntry entry( type, name, length, 0 /* offset */, list );
-
- /* If the new chunk is in a list, then get the offset and size
- of that list. The offset of this chunk is the end of the list
- (parent_offset + parent_length) plus the size of the chunk
- header. */
-
- if ( list != RIFF_NO_PARENT )
- {
- RIFFDirEntry parent = GetDirectoryEntry( list );
- entry.offset = parent.offset + parent.length + RIFF_HEADERSIZE;
- }
-
- /* The list which this new chunk is a member of has now increased in
- size. Get that directory entry and bump up its length by the size
- of the chunk. Since that list may also be contained in another
- list, walk up to the top of the tree. */
-
- while ( list != RIFF_NO_PARENT )
- {
- RIFFDirEntry parent = GetDirectoryEntry( list );
- parent.length += RIFF_HEADERSIZE + length;
- SetDirectoryEntry( list, parent );
- list = parent.parent;
- }
-
- directory.insert( directory.end(), entry );
-
- return directory.size() - 1;
-}
-
-
-/** Modifies an entry.
-
- \param i the ID of the entry which is to modify
- \param type the type of this entry
- \param name the name
- \param length the length of the data in the container
- \param list the container in which this object is contained.
- \note Do not change length, offset, or the parent container.
- \note Do not change an empty name ("") to a name and vice versa */
-
-void RIFFFile::SetDirectoryEntry( int i, FOURCC type, FOURCC name, off_t length, off_t offset, int list )
-{
- RIFFDirEntry entry( type, name, length, offset, list );
-
- assert( i >= 0 && i < ( int ) directory.size() );
-
- directory[ i ] = entry;
-}
-
-
-/** Modifies an entry.
-
- The entry.written flag is set to false because the contents has been modified
-
- \param i the ID of the entry which is to modify
- \param entry the new entry
- \note Do not change length, offset, or the parent container.
- \note Do not change an empty name ("") to a name and vice versa */
-
-void RIFFFile::SetDirectoryEntry( int i, RIFFDirEntry &entry )
-{
- assert( i >= 0 && i < ( int ) directory.size() );
-
- entry.written = false;
- directory[ i ] = entry;
-}
-
-
-/** Retrieves an entry.
-
- Gets the most important member variables.
-
- \param i the ID of the entry to retrieve
- \param type
- \param name
- \param length
- \param offset
- \param list */
-
-void RIFFFile::GetDirectoryEntry( int i, FOURCC &type, FOURCC &name, off_t &length, off_t &offset, int &list ) const
-{
- RIFFDirEntry entry;
-
- assert( i >= 0 && i < ( int ) directory.size() );
-
- entry = directory[ i ];
- type = entry.type;
- name = entry.name;
- length = entry.length;
- offset = entry.offset;
- list = entry.parent;
-}
-
-
-/** Retrieves an entry.
-
- Gets the whole RIFFDirEntry object.
-
- \param i the ID of the entry to retrieve
- \return the entry */
-
-RIFFDirEntry RIFFFile::GetDirectoryEntry( int i ) const
-{
- assert( i >= 0 && i < ( int ) directory.size() );
-
- return directory[ i ];
-}
-
-
-/** Calculates the total size of the file
-
- \return the size the file in bytes
-*/
-
-off_t RIFFFile::GetFileSize( void ) const
-{
-
- /* If we have at least one entry, return the length field
- of the FILE entry, which is the length of its contents,
- which is the actual size of whatever is currently in the
- AVI directory structure.
-
- Note that the first entry does not belong to the AVI
- file.
-
- If we don't have any entry, the file size is zero. */
-
- if ( directory.size() > 0 )
- return directory[ 0 ].length;
- else
- return 0;
-}
-
-
-/** prints the attributes of the entry
-
- \param i the ID of the entry to print
-*/
-
-void RIFFFile::PrintDirectoryEntry ( int i ) const
-{
- RIFFDirEntry entry;
- RIFFDirEntry parent;
- FOURCC entry_name;
- FOURCC list_name;
-
- /* Get all attributes of the chunk object. If it is contained
- in a list, get the name of the list too (otherwise the name of
- the list is blank). If the chunk object doesn´t have a name (only
- LISTs and RIFFs have a name), the name is blank. */
-
- entry = GetDirectoryEntry( i );
- if ( entry.parent != RIFF_NO_PARENT )
- {
- parent = GetDirectoryEntry( entry.parent );
- list_name = parent.name;
- }
- else
- {
- list_name = make_fourcc( " " );
- }
- if ( entry.name != 0 )
- {
- entry_name = entry.name;
- }
- else
- {
- entry_name = make_fourcc( " " );
- }
-
- /* Print out the ascii representation of type and name, as well as
- length and file offset. */
-
- cout << hex << setfill( '0' ) << "type: "
- << ((char *)&entry.type)[0]
- << ((char *)&entry.type)[1]
- << ((char *)&entry.type)[2]
- << ((char *)&entry.type)[3]
- << " name: "
- << ((char *)&entry_name)[0]
- << ((char *)&entry_name)[1]
- << ((char *)&entry_name)[2]
- << ((char *)&entry_name)[3]
- << " length: 0x" << setw( 12 ) << entry.length
- << " offset: 0x" << setw( 12 ) << entry.offset
- << " list: "
- << ((char *)&list_name)[0]
- << ((char *)&list_name)[1]
- << ((char *)&list_name)[2]
- << ((char *)&list_name)[3] << dec << endl;
-
- /* print the content itself */
-
- PrintDirectoryEntryData( entry );
-}
-
-
-/** prints the contents of the entry
-
- Prints a readable representation of the contents of an index.
- Override this to print out any objects you store in the RIFF file.
-
- \param entry the entry to print */
-
-void RIFFFile::PrintDirectoryEntryData( const RIFFDirEntry &entry ) const
- {}
-
-
-/** prints the contents of the whole directory
-
- Prints a readable representation of the contents of an index.
- Override this to print out any objects you store in the RIFF file.
-
- \param entry the entry to print */
-
-void RIFFFile::PrintDirectory() const
-{
- int i;
- int count = directory.size();
-
- for ( i = 0; i < count; ++i )
- PrintDirectoryEntry( i );
-}
-
-
-/** finds the index
-
- finds the index of a given directory entry type
-
- \todo inefficient if the directory has lots of items
- \param type the type of the entry to find
- \param n the zero-based instance of type to locate
- \return the index of the found object in the directory, or -1 if not found */
-
-int RIFFFile::FindDirectoryEntry ( FOURCC type, int n ) const
-{
- int i, j = 0;
- int count = directory.size();
-
- for ( i = 0; i < count; ++i )
- if ( directory[ i ].type == type )
- {
- if ( j == n )
- return i;
- j++;
- }
-
- return -1;
-}
-
-
-/** Reads all items that are contained in one list
-
- Read in one chunk and add it to the directory. If the chunk
- happens to be of type LIST, then call ParseList recursively for
- it.
-
- \param parent The id of the item to process
-*/
-
-void RIFFFile::ParseChunk( int parent )
-{
- FOURCC type;
- DWORD length;
- int typesize;
-
- /* Check whether it is a LIST. If so, let ParseList deal with it */
-
- fail_if( read( fd, &type, sizeof( type ) ) != sizeof( type ));
- if ( type == make_fourcc( "LIST" ) )
- {
- typesize = (int) -sizeof( type );
- fail_if( lseek( fd, typesize, SEEK_CUR ) == ( off_t ) - 1 );
- ParseList( parent );
- }
-
- /* it is a normal chunk, create a new directory entry for it */
-
- else
- {
- fail_neg( read( fd, &length, sizeof( length ) ) );
- if ( length & 1 )
- length++;
- AddDirectoryEntry( type, 0, length, parent );
- fail_if( lseek( fd, length, SEEK_CUR ) == ( off_t ) - 1 );
- }
-}
-
-
-/** Reads all items that are contained in one list
-
- \param parent The id of the list to process
-
-*/
-
-void RIFFFile::ParseList( int parent )
-{
- FOURCC type;
- FOURCC name;
- int list;
- DWORD length;
- off_t pos;
- off_t listEnd;
-
- /* Read in the chunk header (type and length). */
- fail_neg( read( fd, &type, sizeof( type ) ) );
- fail_neg( read( fd, &length, sizeof( length ) ) );
-
- if ( length & 1 )
- length++;
-
- /* The contents of the list starts here. Obtain its offset. The list
- name (4 bytes) is already part of the contents). */
-
- pos = lseek( fd, 0, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- fail_neg( read( fd, &name, sizeof( name ) ) );
-
- /* Add an entry for this list. */
-
- list = AddDirectoryEntry( type, name, sizeof( name ), parent );
-
- /* Read in any chunks contained in this list. This list is the
- parent for all chunks it contains. */
-
- listEnd = pos + length;
- while ( pos < listEnd )
- {
- ParseChunk( list );
- pos = lseek( fd, 0, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- }
-}
-
-
-/** Reads the directory structure of the whole RIFF file
-
-*/
-
-void RIFFFile::ParseRIFF( void )
-{
- FOURCC type;
- DWORD length;
- off_t filesize;
- off_t pos;
- int container = AddDirectoryEntry( make_fourcc( "FILE" ), make_fourcc( "FILE" ), 0, RIFF_NO_PARENT );
-
- pos = lseek( fd, 0, SEEK_SET );
-
- /* calculate file size from RIFF header instead from physical file. */
-
- while ( ( read( fd, &type, sizeof( type ) ) > 0 ) &&
- ( read( fd, &length, sizeof( length ) ) > 0 ) &&
- ( type == make_fourcc( "RIFF" ) ) )
- {
-
- filesize += length + RIFF_HEADERSIZE;
-
- fail_if( lseek( fd, pos, SEEK_SET ) == ( off_t ) - 1 );
- ParseList( container );
- pos = lseek( fd, 0, SEEK_CUR );
- fail_if( pos == ( off_t ) - 1 );
- }
-}
-
-
-/** Reads one item including its contents from the RIFF file
-
- \param chunk_index The index of the item to write
- \param data A pointer to the data
-
-*/
-
-void RIFFFile::ReadChunk( int chunk_index, void *data, off_t data_len )
-{
- RIFFDirEntry entry;
-
- entry = GetDirectoryEntry( chunk_index );
- pthread_mutex_lock( &file_mutex );
- fail_if( lseek( fd, entry.offset, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( read( fd, data, entry.length > data_len ? data_len : entry.length ) );
- pthread_mutex_unlock( &file_mutex );
-}
-
-
-/** Writes one item including its contents to the RIFF file
-
- \param chunk_index The index of the item to write
- \param data A pointer to the data
-
-*/
-
-void RIFFFile::WriteChunk( int chunk_index, const void *data )
-{
- RIFFDirEntry entry;
-
- entry = GetDirectoryEntry( chunk_index );
- pthread_mutex_lock( &file_mutex );
- fail_if( lseek( fd, entry.offset - RIFF_HEADERSIZE, SEEK_SET ) == ( off_t ) - 1 );
- fail_neg( write( fd, &entry.type, sizeof( entry.type ) ) );
- DWORD length = entry.length;
- fail_neg( write( fd, &length, sizeof( length ) ) );
- fail_neg( write( fd, data, entry.length ) );
- pthread_mutex_unlock( &file_mutex );
-
- /* Remember that this entry already has been written. */
-
- directory[ chunk_index ].written = true;
-}
-
-
-/** Writes out the directory structure
-
- For all items in the directory list that have not been written
- yet, it seeks to the file position where that item should be
- stored and writes the type and length field. If the item has a
- name, it will also write the name field.
-
- \note It does not write the contents of any item. Use WriteChunk to do that. */
-
-void RIFFFile::WriteRIFF( void )
-{
- int i;
- RIFFDirEntry entry;
- int count = directory.size();
-
- /* Start at the second entry (RIFF), since the first entry (FILE)
- is needed only for internal purposes and is not written to the
- file. */
-
- for ( i = 1; i < count; ++i )
- {
-
- /* Only deal with entries that haven´t been written */
-
- entry = GetDirectoryEntry( i );
- if ( entry.written == false )
- {
-
- /* A chunk entry consist of its type and length, a list
- entry has an additional name. Look up the entry, seek
- to the start of the header, which is at the offset of
- the data start minus the header size and write out the
- items. */
-
- fail_if( lseek( fd, entry.offset - RIFF_HEADERSIZE, SEEK_SET ) == ( off_t ) - 1 ) ;
- fail_neg( write( fd, &entry.type, sizeof( entry.type ) ) );
- DWORD length = entry.length;
- fail_neg( write( fd, &length, sizeof( length ) ) );
-
- /* If it has a name, it is a list. Write out the extra name
- field. */
-
- if ( entry.name != 0 )
- {
- fail_neg( write( fd, &entry.name, sizeof( entry.name ) ) );
- }
-
- /* Remember that this entry already has been written. */
-
- directory[ i ].written = true;
- }
- }
-}
+++ /dev/null
-/*
-* riff.h library for RIFF file format i/o
-* Copyright (C) 2000 - 2002 Arne Schirmacher <arne@schirmacher.de>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*
-* Tag: $Name$
-*
-* Change log:
-*
-* $Log$
-* Revision 1.2 2005/07/25 07:21:39 lilo_booter
-* + fixes for opendml dv avi
-*
-* Revision 1.1 2005/04/15 14:28:26 lilo_booter
-* Initial version
-*
-* Revision 1.14 2005/04/01 23:43:10 ddennedy
-* apply endian fixes from Daniel Kobras
-*
-* Revision 1.13 2004/10/11 01:37:11 ddennedy
-* mutex safety locks in RIFF and AVI classes, type 2 AVI optimization, mencoder export script
-*
-* Revision 1.12 2004/01/06 22:53:42 ddennedy
-* metadata editing tweaks and bugfixes, new ui elements in preparation for publish functions
-*
-* Revision 1.11 2003/11/25 23:01:25 ddennedy
-* cleanup and a few bugfixes
-*
-* Revision 1.10 2003/10/21 16:34:34 ddennedy
-* GNOME2 port phase 1: initial checkin
-*
-* Revision 1.8.4.1 2002/11/25 04:48:31 ddennedy
-* bugfix to report errors when loading files
-*
-* Revision 1.8 2002/04/21 06:36:40 ddennedy
-* kindler avc and 1394 bus reset support in catpure page, honor max file size
-*
-* Revision 1.7 2002/04/09 06:53:42 ddennedy
-* cleanup, new libdv 0.9.5, large AVI, dnd storyboard
-*
-* Revision 1.3 2002/03/25 21:34:25 arne
-* Support for large (64 bit) files mostly completed
-*
-* Revision 1.2 2002/03/04 19:22:43 arne
-* updated to latest Kino avi code
-*
-* Revision 1.1.1.1 2002/03/03 19:08:08 arne
-* import of version 1.01
-*
-*/
-
-#ifndef _RIFF_H
-#define _RIFF_H 1
-
-#include <vector>
-using std::vector;
-
-#include <pthread.h>
-
-#include "endian_types.h"
-
-#define QUADWORD int64_le_t
-#define DWORD int32_le_t
-#define LONG u_int32_le_t
-#define WORD int16_le_t
-#define BYTE u_int8_le_t
-#define FOURCC u_int32_t // No endian conversion needed.
-
-#define RIFF_NO_PARENT (-1)
-#define RIFF_LISTSIZE (4)
-#define RIFF_HEADERSIZE (8)
-
-#ifdef __cplusplus
-extern "C"
-{
- FOURCC make_fourcc( const char * s );
-}
-#endif
-
-class RIFFDirEntry
-{
-public:
- FOURCC type;
- FOURCC name;
- off_t length;
- off_t offset;
- int parent;
- int written;
-
- RIFFDirEntry();
- RIFFDirEntry( FOURCC t, FOURCC n, int l, int o, int p );
-};
-
-
-class RIFFFile
-{
-public:
- RIFFFile();
- RIFFFile( const RIFFFile& );
- virtual ~RIFFFile();
- RIFFFile& operator=( const RIFFFile& );
-
- virtual bool Open( const char *s );
- virtual bool Create( const char *s );
- virtual void Close();
- virtual int AddDirectoryEntry( FOURCC type, FOURCC name, off_t length, int list );
- virtual void SetDirectoryEntry( int i, FOURCC type, FOURCC name, off_t length, off_t offset, int list );
- virtual void SetDirectoryEntry( int i, RIFFDirEntry &entry );
- virtual void GetDirectoryEntry( int i, FOURCC &type, FOURCC &name, off_t &length, off_t &offset, int &list ) const;
- virtual RIFFDirEntry GetDirectoryEntry( int i ) const;
- virtual off_t GetFileSize( void ) const;
- virtual void PrintDirectoryEntry( int i ) const;
- virtual void PrintDirectoryEntryData( const RIFFDirEntry &entry ) const;
- virtual void PrintDirectory( void ) const;
- virtual int FindDirectoryEntry( FOURCC type, int n = 0 ) const;
- virtual void ParseChunk( int parent );
- virtual void ParseList( int parent );
- virtual void ParseRIFF( void );
- virtual void ReadChunk( int chunk_index, void *data, off_t data_len );
- virtual void WriteChunk( int chunk_index, const void *data );
- virtual void WriteRIFF( void );
-
-protected:
- int fd;
- pthread_mutex_t file_mutex;
-
-private:
- vector<RIFFDirEntry> directory;
-};
-#endif
+++ /dev/null
-include ../../../config.mak
-LDFLAGS=
-
-all: luma create_lumas
- @./create_lumas
-
-luma: luma.c
-
-create_lumas:
-
-depend:
-
-distclean:
- rm -rf PAL NTSC luma
-
-clean:
- rm -f luma
-
-install: all
- install -d $(DESTDIR)$(prefix)/share/mlt/lumas/PAL
- install -d $(DESTDIR)$(prefix)/share/mlt/lumas/NTSC
- install -m 644 PAL/* $(DESTDIR)$(prefix)/share/mlt/lumas/PAL
- install -m 644 NTSC/* $(DESTDIR)$(prefix)/share/mlt/lumas/NTSC
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" = "1" ]
-then
- cat << EOF
-Luma options:
-
- --luma-compress - Produce compressed (png) lumas
- --luma-8bpp - Produce 8 bit pgm lumas (defaut is 16 bit)
-
-EOF
-
-else
-
- rm -f .8bit .compress .executed
-
- for i in "$@"
- do
- case $i in
- --luma-compress ) touch .compress ;;
- --luma-8bit ) touch .8bit ;;
- esac
- done
-
-fi
-
+++ /dev/null
-#!/bin/sh
-
-[ \( -d PAL \) -a \( ! $0 -nt .executed \) ] && exit 0
-
-bpp=16
-[ -f .8bit ] && bpp=8
-
-for i in PAL NTSC
-do
- mkdir -p $i
- rm -f $i/*.pgm $i/*.png
-
- [ "$i" = "PAL" ] && h=576 || h=480
- ./luma -h $h -bpp $bpp > $i/luma01.pgm
- ./luma -h $h -bpp $bpp -bands $h > $i/luma02.pgm
- ./luma -h $h -bpp $bpp -hmirror 1 > $i/luma03.pgm
- ./luma -h $h -bpp $bpp -bands $h -vmirror 1 > $i/luma04.pgm
- ./luma -h $h -bpp $bpp -offset 32768 -dmirror 1 > $i/luma05.pgm
- ./luma -h $h -bpp $bpp -offset 32768 -dmirror 1 -flip 1 > $i/luma06.pgm
- ./luma -h $h -bpp $bpp -offset 32768 -dmirror 1 -quart 1 > $i/luma07.pgm
- ./luma -h $h -bpp $bpp -offset 32768 -dmirror 1 -quart 1 -flip 1 > $i/luma08.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 0 > $i/luma09.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 0 -rotate 1 -flop 1 > $i/luma10.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 1 > $i/luma11.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 1 -vmirror 1 > $i/luma12.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 1 -rotate 1 -flop 1 > $i/luma13.pgm
- ./luma -h $h -bpp $bpp -bands 12 -rband 1 -rotate 1 -vmirror 1 > $i/luma14.pgm
- ./luma -h $h -bpp $bpp -offset 32768 -dmirror 1 -hmirror 1 > $i/luma15.pgm
- ./luma -h $h -bpp $bpp -type 1 > $i/luma16.pgm
- ./luma -h $h -bpp $bpp -type 1 -bands 2 -rband 1 > $i/luma17.pgm
- ./luma -h $h -bpp $bpp -type 2 > $i/luma18.pgm
- ./luma -h $h -bpp $bpp -type 2 -quart 1 > $i/luma19.pgm
- ./luma -h $h -bpp $bpp -type 2 -quart 1 -flip 1 > $i/luma20.pgm
- ./luma -h $h -bpp $bpp -type 2 -quart 1 -bands 2 > $i/luma21.pgm
- ./luma -h $h -bpp $bpp -type 3 > $i/luma22.pgm
-
- if [ -f .compress ]
- then
- for f in $i/*.pgm
- do
- convert $f $f.png
- rm -f $f
- done
- fi
-done
-
-touch .executed
-
+++ /dev/null
-/*
- * luma.c -- image generator for transition_luma
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-typedef struct
-{
- int type;
- int w;
- int h;
- int bands;
- int rband;
- int vmirror;
- int hmirror;
- int dmirror;
- int invert;
- int offset;
- int flip;
- int flop;
- int pflip;
- int pflop;
- int quart;
- int rotate;
-}
-luma;
-
-void luma_init( luma *this )
-{
- memset( this, 0, sizeof( luma ) );
- this->type = 0;
- this->w = 720;
- this->h = 576;
- this->bands = 1;
- this->rband = 0;
- this->vmirror = 0;
- this->hmirror = 0;
- this->dmirror = 0;
- this->invert = 0;
- this->offset = 0;
- this->flip = 0;
- this->flop = 0;
- this->quart = 0;
- this->pflop = 0;
- this->pflip = 0;
-}
-
-static inline int sqrti( int n )
-{
- int p = 0;
- int q = 1;
- int r = n;
- int h = 0;
-
- while( q <= n )
- q = 4 * q;
-
- while( q != 1 )
- {
- q = q / 4;
- h = p + q;
- p = p / 2;
- if ( r >= h )
- {
- p = p + q;
- r = r - h;
- }
- }
-
- return p;
-}
-
-uint16_t *luma_render( luma *this )
-{
- int i = 0;
- int j = 0;
- int k = 0;
-
- if ( this->quart )
- {
- this->w *= 2;
- this->h *= 2;
- }
-
- if ( this->rotate )
- {
- int t = this->w;
- this->w = this->h;
- this->h = t;
- }
-
- int max = ( 1 << 16 ) - 1;
- uint16_t *image = malloc( this->w * this->h * sizeof( uint16_t ) );
- uint16_t *end = image + this->w * this->h;
- uint16_t *p = image;
- uint16_t *r = image;
- int lower = 0;
- int lpb = this->h / this->bands;
- int rpb = max / this->bands;
- int direction = 1;
-
- int half_w = this->w / 2;
- int half_h = this->h / 2;
-
- if ( !this->dmirror && ( this->hmirror || this->vmirror ) )
- rpb *= 2;
-
- for ( i = 0; i < this->bands; i ++ )
- {
- lower = i * rpb;
- direction = 1;
-
- if ( this->rband && i % 2 == 1 )
- {
- direction = -1;
- lower += rpb;
- }
-
- switch( this->type )
- {
- case 1:
- {
- int length = sqrti( half_w * half_w + lpb * lpb / 4 );
- int value;
- int x = 0;
- int y = 0;
- for ( j = 0; j < lpb; j ++ )
- {
- y = j - lpb / 2;
- for ( k = 0; k < this->w; k ++ )
- {
- x = k - half_w;
- value = sqrti( x * x + y * y );
- *p ++ = lower + ( direction * rpb * ( ( max * value ) / length ) / max ) + ( j * this->offset * 2 / lpb ) + ( j * this->offset / lpb );
- }
- }
- }
- break;
-
- case 2:
- {
- for ( j = 0; j < lpb; j ++ )
- {
- int value = ( ( j * this->w ) / lpb ) - half_w;
- if ( value > 0 )
- value = - value;
- for ( k = - half_w; k < value; k ++ )
- *p ++ = lower + ( direction * rpb * ( ( max * abs( k ) ) / half_w ) / max );
- for ( k = value; k < abs( value ); k ++ )
- *p ++ = lower + ( direction * rpb * ( ( max * abs( value ) ) / half_w ) / max ) + ( j * this->offset * 2 / lpb ) + ( j * this->offset / lpb );
- for ( k = abs( value ); k < half_w; k ++ )
- *p ++ = lower + ( direction * rpb * ( ( max * abs( k ) ) / half_w ) / max );
- }
- }
- break;
-
- case 3:
- {
- int length;
- for ( j = -half_h; j < half_h; j ++ )
- {
- if ( j < 0 )
- {
- for ( k = - half_w; k < half_w; k ++ )
- {
- length = sqrti( k * k + j * j );
- *p ++ = ( max / 4 * k ) / ( length + 1 );
- }
- }
- else
- {
- for ( k = half_w; k > - half_w; k -- )
- {
- length = sqrti( k * k + j * j );
- *p ++ = ( max / 2 ) + ( max / 4 * k ) / ( length + 1 );
- }
- }
- }
- }
- break;
-
- default:
- for ( j = 0; j < lpb; j ++ )
- for ( k = 0; k < this->w; k ++ )
- *p ++ = lower + ( direction * ( rpb * ( ( k * max ) / this->w ) / max ) ) + ( j * this->offset * 2 / lpb );
- break;
- }
- }
-
- if ( this->quart )
- {
- this->w /= 2;
- this->h /= 2;
- for ( i = 1; i < this->h; i ++ )
- {
- p = image + i * this->w;
- r = image + i * 2 * this->w;
- j = this->w;
- while ( j -- > 0 )
- *p ++ = *r ++;
- }
- }
-
- if ( this->dmirror )
- {
- for ( i = 0; i < this->h; i ++ )
- {
- p = image + i * this->w;
- r = end - i * this->w;
- j = ( this->w * ( this->h - i ) ) / this->h;
- while ( j -- )
- *( -- r ) = *p ++;
- }
- }
-
- if ( this->flip )
- {
- uint16_t t;
- for ( i = 0; i < this->h; i ++ )
- {
- p = image + i * this->w;
- r = p + this->w;
- while( p != r )
- {
- t = *p;
- *p ++ = *( -- r );
- *r = t;
- }
- }
- }
-
- if ( this->flop )
- {
- uint16_t t;
- r = end;
- for ( i = 1; i < this->h / 2; i ++ )
- {
- p = image + i * this->w;
- j = this->w;
- while( j -- )
- {
- t = *( -- p );
- *p = *( -- r );
- *r = t;
- }
- }
- }
-
- if ( this->hmirror )
- {
- p = image;
- while ( p < end )
- {
- r = p + this->w;
- while ( p != r )
- *( -- r ) = *p ++;
- p += this->w / 2;
- }
- }
-
- if ( this->vmirror )
- {
- p = image;
- r = end;
- while ( p != r )
- *( -- r ) = *p ++;
- }
-
- if ( this->invert )
- {
- p = image;
- r = image;
- while ( p < end )
- *p ++ = max - *r ++;
- }
-
- if ( this->pflip )
- {
- uint16_t t;
- for ( i = 0; i < this->h; i ++ )
- {
- p = image + i * this->w;
- r = p + this->w;
- while( p != r )
- {
- t = *p;
- *p ++ = *( -- r );
- *r = t;
- }
- }
- }
-
- if ( this->pflop )
- {
- uint16_t t;
- end = image + this->w * this->h;
- r = end;
- for ( i = 1; i < this->h / 2; i ++ )
- {
- p = image + i * this->w;
- j = this->w;
- while( j -- )
- {
- t = *( -- p );
- *p = *( -- r );
- *r = t;
- }
- }
- }
-
- if ( this->rotate )
- {
- uint16_t *image2 = malloc( this->w * this->h * sizeof( uint16_t ) );
- for ( i = 0; i < this->h; i ++ )
- {
- p = image + i * this->w;
- r = image2 + this->h - i - 1;
- for ( j = 0; j < this->w; j ++ )
- {
- *r = *( p ++ );
- r += this->h;
- }
- }
- i = this->w;
- this->w = this->h;
- this->h = i;
- free( image );
- image = image2;
- }
-
- return image;
-}
-
-int main( int argc, char **argv )
-{
- int arg = 1;
- int bpp = 8;
-
- luma this;
- uint16_t *image = NULL;
-
- luma_init( &this );
-
- for ( arg = 1; arg < argc - 1; arg ++ )
- {
- if ( !strcmp( argv[ arg ], "-bpp" ) )
- bpp = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-type" ) )
- this.type = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-w" ) )
- this.w = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-h" ) )
- this.h = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-bands" ) )
- this.bands = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-rband" ) )
- this.rband = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-hmirror" ) )
- this.hmirror = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-vmirror" ) )
- this.vmirror = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-dmirror" ) )
- this.dmirror = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-offset" ) )
- this.offset = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-invert" ) )
- this.invert = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-flip" ) )
- this.flip = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-flop" ) )
- this.flop = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-pflip" ) )
- this.pflip = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-pflop" ) )
- this.pflop = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-quart" ) )
- this.quart = atoi( argv[ ++ arg ] );
- else if ( !strcmp( argv[ arg ], "-rotate" ) )
- this.rotate = atoi( argv[ ++ arg ] );
- else
- fprintf( stderr, "ignoring %s\n", argv[ arg ] );
- }
-
- if ( bpp != 8 && bpp != 16 )
- {
- fprintf( stderr, "Invalid bpp %d\n", bpp );
- return 1;
- }
-
- image = luma_render( &this );
-
- if ( bpp == 16 )
- {
- uint16_t *end = image + this.w * this.h;
- uint16_t *p = image;
- uint8_t *q = ( uint8_t * )image;
- while ( p < end )
- {
- *p ++ = ( *q << 8 ) + *( q + 1 );
- q += 2;
- }
- printf( "P5\n" );
- printf( "%d %d\n", this.w, this.h );
- printf( "65535\n" );
- fwrite( image, this.w * this.h * sizeof( uint16_t ), 1, stdout );
- }
- else
- {
- uint16_t *end = image + this.w * this.h;
- uint16_t *p = image;
- uint8_t *q = ( uint8_t * )image;
- while ( p < end )
- *q ++ = ( uint8_t )( *p ++ >> 8 );
- printf( "P5\n" );
- printf( "%d %d\n", this.w, this.h );
- printf( "255\n" );
- fwrite( image, this.w * this.h, 1, stdout );
- }
-
- return 0;
-}
-
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltmotion_est.so
-
-OBJS = factory.o \
- filter_motion_est.o \
- filter_crop_detect.o \
- filter_autotrack_rectangle.o \
- arrow_code.o \
- filter_vismv.o \
- producer_slowmotion.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-test: $(TARGET)
- ~/mlt-devel/mlt/src/inigo/inigo -filter motion_est -filter vismv -filter benchmark -consumer sdl rescale=none real_time=0 audio_off=1 silent=1 /media/cdrecorder/BBC.The.Private.Life.Of.Plants.Pt5.Living.Together.DivX505.AC3.www.MVGroup.org.uk.avi in=50000
-
-hist: $(TARGET)
- ~/mlt-devel/mlt/src/inigo/inigo -filter motion_est -filter histogram -consumer sdl rescale=none real_time=0 audio_off=1 silent=1 /media/cdrecorder/BBC.The.Private.Life.Of.Plants.Pt5.Living.Together.DivX505.AC3.www.MVGroup.org.uk.avi in=40000
-
-
-test2: $(TARGET)
- inigo colour:black -filter watermark:"+mello.txt" composite.geometry="0,0:10%x10%;99=90%,90%" composite.out=99 -filter crop_detect -filter motion_est -filter vismv
-
-realtime: $(TARGET)
- ~/mlt-devel/mlt/src/inigo/inigo -filter motion_est -filter vismv -consumer sdl rescale=none /media/cdrecorder/BBC.The.Private.Life.Of.Plants.Pt5.Living.Together.DivX505.AC3.www.MVGroup.org.uk.avi in=30000
-
-testhist: $(TARGET)
- ~/mlt-devel/mlt/src/inigo/inigo -consumer sdl rescale=none silent=1 -filter motion_est -filter histogram -filter vismv /media/cdrecorder/BBC.The.Private.Life.Of.Plants.Pt5.Living.Together.DivX505.AC3.www.MVGroup.org.uk.avi in=10000
-
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-INTRO:
-
-This module is designed to provide application agnostic motion estimation.
-I wrote it from scratch because I found the other Open Source code to be
-limited by their difficulty of reuse.
-
-
-COMPILE:
-
-To compile this module, you must supply these options to the root configure script:
-
---enable-gpl --enable-motion-est
-
-
-EXAMPLES:
-
-Estimate the motion:
-
- > inigo -filter motion_est <movie_file>
-
-To display the motion vectors as pretty arrows:
-
- > inigo -filter motion_est -filter vismv <movie_file>
-
-If your using a movie file that contains a crop, you will get better results with this:
-
- > inigo -filter crop_detect -filter motion_est -filter vismv <movie_file>
-
-If your computer is unable to do the above examples in real time, try this:
-
- > inigo -filter motion_est -filter vismv -consumer inigo real_time=0 <movie_file>
-
-If you'd like to see the motion vectors without the median denoising function, do this:
-
- > inigo -filter motion_est denoise=0 -filter vismv <movie_file>
-
-To reconstruct each frame by applying the motion to the previous frame:
-
- > inigo -filter motion_est show_reconstruction=1 <movie_file>
-
-To compare the reconstructed frame and the real frame (while paused):
-
- > inigo -filter motion_est show_reconstruction=1 toggle_when_paused=1 <movie_file>
-
-To show the difference (residual) between the reconstructed frame the real frame:
-
- > inigo -filter motion_est show_residual=1 <movie_file>
-
-To automatically track an object in the frame, try this:
-
- > inigo -filter autotrack_rectangle:X,Y:WxH debug=1 <movie_file>
-
-(Where X,Y is the origin of the rectangle indexed from upper left and WxH is the dimensions of the rectangle.)
-
-To obscure that same object in the frame, try this:
-
- > inigo -filter autotrack_rectangle:X,Y:WxH obscure=1 <movie_file>
-
-There is now a slow motion producer that does interpolation based on the motion vectors:
-
- > inigo slowmotion:<movie_file> _speed=0.1 method=1 debug=1
-
-NOTES (and deficiencies):
-
-1. Ignore shot change detection when your using the autotrack_rectangle filter.
-
-2. Don't assume motion vectors displayed while stepping backwards and forward are that same vectors
- that would be calculated while playing the footage from start to finish, nonstop. Stepping forward
- should be fine after a few frames, however.
-
-3. SSE instructions are lazily assumed. MMX, Altivec, and SIMD-less would be good too.
-
-4. Motion estimation is only performed in the luma color space.
-
-5. Motion vectors should have sub-pixel accuracy.
-
-6. Motion vectors are not serializable yet.
-
-7. A diligent test suite is needed. (show_reconstruction & show_residual are a start)
-
-8. Multithreaded code will see HUGE benefits on multi-CPU systems. Donations of a multi-core cpu or a
- multi-cpu system to the author will encourage development.
-
-9. Macroblock sizes are not dynamic (Though settable at runtime.)
-
-10. Notes (5), (7), and (9) would go a long ways to making this code suitable for a modern video encoder.
-
-11. Shot change works well but arbitrarily chosen thresholds need to be tuned.
-
-12. Given the documentation of other motion estimation code bases, I will GLADLY clarify and
- document any piece of code upon request.
-
-13. Considerable effort has been put into the speed. I usually experience 10ms or less per frame for PAL on 2.8GHZ p4.
-
-Zachary Drew
-drew0054@tc.umn.edu
-
+++ /dev/null
-/*
- * /brief Draw arrows
- * /author Zachary Drew, Copyright 2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_frame.h>
-#include "arrow_code.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#define MIN(a,b) ((a) > (b) ? (b) : (a))
-
-#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-
-static int w;
-static int h;
-static int xstride;
-static int ystride;
-static mlt_image_format format;
-
-int init_arrows( mlt_image_format *image_format, int width, int height )
-{
- w = width;
- h = height;
- format = *image_format;
- switch( *image_format ) {
- case mlt_image_yuv422:
- xstride = 2;
- ystride = xstride * w;
- break;
- default:
- // I don't know
- return 0;
- }
- return 1;
-
-}
-
-// ffmpeg borrowed
-static inline int clip(int a, int amin, int amax)
-{
- if (a < amin)
- return amin;
- else if (a > amax)
- return amax;
- else
- return a;
-}
-
-
-/**
- * draws an line from (ex, ey) -> (sx, sy).
- * Credits: modified from ffmpeg project
- * @param ystride stride/linesize of the image
- * @param xstride stride/element size of the image
- * @param color color of the arrow
- */
-void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int color)
-{
- int t, x, y, fr, f;
-
-
- sx= clip(sx, 0, w-1);
- sy= clip(sy, 0, h-1);
- ex= clip(ex, 0, w-1);
- ey= clip(ey, 0, h-1);
-
- buf[sy*ystride + sx*xstride]+= color;
-
- if(ABS(ex - sx) > ABS(ey - sy)){
- if(sx > ex){
- t=sx; sx=ex; ex=t;
- t=sy; sy=ey; ey=t;
- }
- buf+= sx*xstride + sy*ystride;
- ex-= sx;
- f= ((ey-sy)<<16)/ex;
- for(x= 0; x <= ex; x++){
- y = (x*f)>>16;
- fr= (x*f)&0xFFFF;
- buf[ y *ystride + x*xstride]+= (color*(0x10000-fr))>>16;
- buf[(y+1)*ystride + x*xstride]+= (color* fr )>>16;
- }
- }else{
- if(sy > ey){
- t=sx; sx=ex; ex=t;
- t=sy; sy=ey; ey=t;
- }
- buf+= sx*xstride + sy*ystride;
- ey-= sy;
- if(ey) f= ((ex-sx)<<16)/ey;
- else f= 0;
- for(y= 0; y <= ey; y++){
- x = (y*f)>>16;
- fr= (y*f)&0xFFFF;
- buf[y*ystride + x *xstride]+= (color*(0x10000-fr))>>16;;
- buf[y*ystride + (x+1)*xstride]+= (color* fr )>>16;;
- }
- }
-}
-
-void draw_rectangle_fill(uint8_t *buf, int x, int y, int w, int h, int color)
-{
- int i,j;
- for ( i = 0; i < w; i++ )
- for ( j = 0; j < h; j++ )
- buf[ (y+j)*ystride + (x+i)*xstride] = color;
-}
-
-void draw_rectangle_outline(uint8_t *buf, int x, int y, int w, int h, int color)
-{
- int i,j;
- for ( i = 0; i < w; i++ ) {
- buf[ y*ystride + (x+i)*xstride ] += color;
- buf[ (y+h)*ystride + (x+i)*xstride ] += color;
- }
- for ( j = 1; j < h+1; j++ ) {
- buf[ (y+j)*ystride + x*xstride ] += color;
- buf[ (y+j)*ystride + (x+w)*xstride ] += color;
- }
-}
-/**
- * draws an arrow from (ex, ey) -> (sx, sy).
- * Credits: modified from ffmpeg project
- * @param stride stride/linesize of the image
- * @param color color of the arrow
- */
-void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int color){
-
- int dx,dy;
- dx= ex - sx;
- dy= ey - sy;
-
- if(dx*dx + dy*dy > 3*3){
- int rx= dx + dy;
- int ry= -dx + dy;
- int length= sqrt((rx*rx + ry*ry)<<8);
-
- rx= ROUNDED_DIV(rx*3<<4, length);
- ry= ROUNDED_DIV(ry*3<<4, length);
-
- draw_line(buf, sx, sy, sx + rx, sy + ry, color);
- draw_line(buf, sx, sy, sx - ry, sy + rx, color);
- }
- draw_line(buf, sx, sy, ex, ey, color);
-}
+++ /dev/null
-/**
- * file: arrow_code.h
- *
- * /brief Misc functions to draw arrows
- * /author Zachary Drew, Copyright 2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-extern int init_arrows( mlt_image_format *image_format, int width, int height );
-extern void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int color);
-extern void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int color);
-extern void draw_rectangle_fill(uint8_t *buf, int x, int y, int w, int h, int color);
-extern void draw_rectangle_outline(uint8_t *buf, int x, int y, int w, int h, int color);
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_motion_est_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_vismv_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_crop_detect_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_autotrack_rectangle_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_slowmotion_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "motion_est", filter_motion_est_init );
- MLT_REGISTER( filter_type, "vismv", filter_vismv_init );
- MLT_REGISTER( filter_type, "crop_detect", filter_crop_detect_init );
- MLT_REGISTER( filter_type, "autotrack_rectangle", filter_autotrack_rectangle_init );
- MLT_REGISTER( producer_type, "slowmotion", producer_slowmotion_init );
-}
+++ /dev/null
-/*
- * filter_autotrack_rectangle.c
- *
- * /brief
- * /author Zachary Drew, Copyright 2005
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "filter_motion_est.h"
-#include "arrow_code.h"
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#define MIN(a,b) ((a) > (b) ? (b) : (a))
-
-#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-void caculate_motion( struct motion_vector_s *vectors,
- mlt_geometry_item boundry,
- int macroblock_width,
- int macroblock_height,
- int mv_buffer_width,
- int method,
- int width,
- int height )
-{
-
-
- // translate pixel units (from bounds) to macroblock units
- // make sure whole macroblock stay within bounds
- int left_mb = ( boundry->x + macroblock_width - 1 ) / macroblock_width;
- int top_mb = ( boundry->y + macroblock_height - 1 ) / macroblock_height;
- int right_mb = ( boundry->x + boundry->w ) / macroblock_width - 1;
- int bottom_mb = ( boundry->y + boundry->h ) / macroblock_height - 1;
-
- int i, j, n = 0;
-
- int average_x = 0, average_y = 0;
-
- #define CURRENT ( vectors + j*mv_buffer_width + i )
-
- for( i = left_mb; i <= right_mb; i++ ){
- for( j = top_mb; j <= bottom_mb; j++ )
- {
- n++;
- average_x += CURRENT->dx;
- average_y += CURRENT->dy;
- }
- }
-
- if ( n == 0 ) return;
-
- average_x /= n;
- average_y /= n;
-
- n = 0;
- int average2_x = 0, average2_y = 0;
- for( i = left_mb; i <= right_mb; i++ ){
- for( j = top_mb; j <= bottom_mb; j++ ){
-
- if( ABS(CURRENT->dx - average_x) < 3 &&
- ABS(CURRENT->dy - average_y) < 3 )
- {
- n++;
- average2_x += CURRENT->dx;
- average2_y += CURRENT->dy;
- }
- }
- }
-
- if ( n == 0 ) return;
-
- boundry->x -= (double)average2_x / (double)n;
- boundry->y -= (double)average2_y / (double)n;
-
- if ( boundry->x < 0 )
- boundry->x = 0;
-
- if ( boundry->y < 0 )
- boundry->y = 0;
-
- if ( boundry->x + boundry->w > width )
- boundry->x = width - boundry->w;
-
- if ( boundry->y + boundry->h > height )
- boundry->y = height - boundry->h;
-}
-
-// Image stack(able) method
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- // Get the filter object
- mlt_filter filter = mlt_frame_pop_service( frame );
-
- // Get the filter's property object
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
-
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);
-
- // Get the frame position
- mlt_position position = mlt_frame_get_position( frame );
-
- // Get the new image
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- if( error != 0 )
- mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle", stderr );
-
- // Get the geometry object
- mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL);
-
- // Get the current geometry item
- struct mlt_geometry_item_s boundry;
- mlt_geometry_fetch(geometry, &boundry, position);
-
- // Get the motion vectors
- struct motion_vector_s *vectors = mlt_properties_get_data( frame_properties, "motion_est.vectors", NULL );
-
- // How did the rectangle move?
- if( vectors != NULL &&
- boundry.key != 1 ) // Paused?
- {
-
- int method = mlt_properties_get_int( filter_properties, "method" );
-
- // Get the size of macroblocks in pixel units
- int macroblock_height = mlt_properties_get_int( frame_properties, "motion_est.macroblock_height" );
- int macroblock_width = mlt_properties_get_int( frame_properties, "motion_est.macroblock_width" );
- int mv_buffer_width = *width / macroblock_width;
-
- caculate_motion( vectors, &boundry, macroblock_width, macroblock_height, mv_buffer_width, method, *width, *height );
-
-
- // Make the geometry object a real boy
- boundry.key = 1;
- boundry.f[0] = 1;
- boundry.f[1] = 1;
- boundry.f[2] = 1;
- boundry.f[3] = 1;
- boundry.f[4] = 1;
- mlt_geometry_insert(geometry, &boundry);
- }
-
- if( mlt_properties_get_int( filter_properties, "debug" ) == 1 )
- {
- init_arrows( format, *width, *height );
- draw_rectangle_outline(*image, boundry.x, boundry.y, boundry.w, boundry.h, 100);
- }
-
- if( mlt_properties_get_int( filter_properties, "obscure" ) == 1 )
- {
- mlt_filter obscure = mlt_properties_get_data( filter_properties, "_obscure", NULL );
-
- mlt_properties_pass_list( MLT_FILTER_PROPERTIES(obscure), filter_properties, "in, out");
-
- // Because filter_obscure needs to be rewritten to use mlt_geometry
- char geom[100];
- sprintf( geom, "%d,%d:%dx%d", (int)boundry.x, (int)boundry.y, (int)boundry.w, (int)boundry.h );
- mlt_properties_set( MLT_FILTER_PROPERTIES( obscure ), "start", geom );
- mlt_properties_set( MLT_FILTER_PROPERTIES( obscure ), "end", geom );
- }
-
- if( mlt_properties_get_int( filter_properties, "collect" ) == 1 )
- {
- printf( "%d,%d,%d,%d\n", (int)boundry.x, (int)boundry.y, (int)boundry.w, (int)boundry.h );
- fflush( stdout );
- }
-
- return error;
-}
-
-static int attach_boundry_to_frame( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter object
- mlt_filter filter = mlt_frame_pop_service( frame );
-
- // Get the filter's property object
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
-
- // Get the frame properties
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES(frame);
-
- // Get the frame position
- mlt_position position = mlt_frame_get_position( frame );
-
- // Get the geometry object
- mlt_geometry geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL);
- if (geometry == NULL) {
- mlt_geometry geom = mlt_geometry_init();
- char *arg = mlt_properties_get(filter_properties, "geometry");
-
- // Initialize with the supplied geometry
- struct mlt_geometry_item_s item;
- mlt_geometry_parse_item( geom, &item, arg );
-
- item.frame = 0;
- item.key = 1;
- item.mix = 100;
-
- mlt_geometry_insert( geom, &item );
- mlt_properties_set_data( filter_properties, "filter_geometry", geom, 0, (mlt_destructor)mlt_geometry_close, (mlt_serialiser)mlt_geometry_serialise );
- geometry = mlt_properties_get_data(filter_properties, "filter_geometry", NULL);
- }
-
- // Get the current geometry item
- mlt_geometry_item geometry_item = mlt_pool_alloc( sizeof( struct mlt_geometry_item_s ) );
- mlt_geometry_fetch(geometry, geometry_item, position);
-
- mlt_properties_set_data( frame_properties, "bounds", geometry_item, sizeof( struct mlt_geometry_item_s ), mlt_pool_release, NULL );
-
- // Get the new image
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- if( error != 0 )
- mlt_properties_debug( frame_properties, "error after mlt_frame_get_image() in autotrack_rectangle attach_boundry_to_frame", stderr );
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- /* modify the frame with the current geometry */
- mlt_frame_push_service( frame, this);
- mlt_frame_push_get_image( frame, attach_boundry_to_frame );
-
-
-
- /* apply the motion estimation filter */
- mlt_filter motion_est = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_motion_est", NULL );
- mlt_filter_process( motion_est, frame);
-
-
-
- /* calculate the new geometry based on the motion */
- mlt_frame_push_service( frame, this);
- mlt_frame_push_get_image( frame, filter_get_image );
-
-
- /* visualize the motion vectors */
- if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(this), "debug" ) == 1 )
- {
- mlt_filter vismv = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_vismv", NULL );
- if( vismv == NULL )
- {
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- vismv = mlt_factory_filter( profile, "vismv", NULL );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_vismv", vismv, 0, (mlt_destructor)mlt_filter_close, NULL );
- }
-
- mlt_filter_process( vismv, frame );
- }
-
- if( mlt_properties_get_int( MLT_FILTER_PROPERTIES(this), "obscure" ) == 1 )
- {
- mlt_filter obscure = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_obscure", NULL );
- if( obscure == NULL )
- {
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- obscure = mlt_factory_filter( profile, "obscure", NULL );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_obscure", obscure, 0, (mlt_destructor)mlt_filter_close, NULL );
- }
-
- mlt_filter_process( obscure, frame );
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-
-mlt_filter filter_autotrack_rectangle_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
-
- // Initialize with the supplied geometry if ther is one
- if( arg != NULL )
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "geometry", arg );
- else
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "geometry", "100,100:100x100" );
-
- // create an instance of the motion_est and obscure filter
- mlt_filter motion_est = mlt_factory_filter( profile, "motion_est", NULL );
- if( motion_est != NULL )
- mlt_properties_set_data( MLT_FILTER_PROPERTIES(this), "_motion_est", motion_est, 0, (mlt_destructor)mlt_filter_close, NULL );
- else {
- mlt_filter_close( this );
- return NULL;
- }
-
-
- }
-
- return this;
-}
-
-/** This source code will self destruct in 5...4...3...
-*/
+++ /dev/null
-/**
- * /brief Crop Detection filter
- *
- * /author Zachary Drew, Copyright 2005
- *
- * inspired by mplayer's cropdetect filter
- *
- * Note: The goemetry generated is zero-indexed and is inclusive of the end values
- *
- * Options:
- * -filter crop_detect debug=1 // Visualize crop
- * -filter crop_detect frequency=25 // Detect the crop once a second
- * -filter crop_detect frequency=0 // Never detect unless the producer changes
- * -filter crop_detect thresh=100 // Changes the threshold (default = 25)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define DEBUG
-#define DEFAULT_THRESH 20
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include "arrow_code.h"
-
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-// Image stack(able) method
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- // Get the filter object and properties
- mlt_filter filter = mlt_frame_pop_service( this );
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the new image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if( error != 0 ) {
- mlt_properties_debug( MLT_FRAME_PROPERTIES(this), "error after mlt_frame_get_image()", stderr );
- return error;
- }
-
- // Parameter that describes how often to check for the crop
- int frequency = mlt_properties_get_int( properties, "frequency");
-
- // Producers may start with blank footage, by default we will skip, oh, 5 frames unless overridden
- int skip = mlt_properties_get_int( properties, "skip");
-
- // The result
- mlt_geometry_item bounds = mlt_properties_get_data( properties, "bounds", NULL );
-
- // Initialize if needed
- if( bounds == NULL ) {
- bounds = calloc( 1, sizeof( struct mlt_geometry_item_s ) );
- bounds->w = *width;
- bounds->h = *height;
- mlt_properties_set_data( properties, "bounds", bounds, sizeof( struct mlt_geometry_item_s ), free, NULL );
- }
-
- // For periodic detection (with offset of 'skip')
- if( frequency == 0 || (int)(mlt_frame_get_position(this)+skip) % frequency != 0)
- {
- // Inject in stream
- mlt_properties_set_data( MLT_FRAME_PROPERTIES(this), "bounds", bounds, sizeof( struct mlt_geometry_item_s ), NULL, NULL );
-
- return 0;
- }
-
-
- // There is no way to detect a crop for sure, so make up an arbitrary one
- int thresh = mlt_properties_get_int( properties, "thresh" );
-
- int xstride, ystride;
-
- switch( *format ) {
- case mlt_image_yuv422:
- xstride = 2;
- ystride = 2 * *width;
- break;
- default:
- fprintf(stderr, "image format not supported by filter_crop_detect\n");
- return -1;
- }
-
- int x, y, average_brightness, deviation; // Scratch variables
- uint8_t *q;
-
- // Top crop
- for( y = 0; y < *height/2; y++ ) {
- bounds->y = y;
- average_brightness = 0;
- deviation = 0;
- q = *image + y*ystride;
- for( x = 0; x < *width; x++ )
- average_brightness += q[x*xstride];
-
- average_brightness /= *width;
-
- for( x = 0; x < *width; x++ )
- deviation += abs(average_brightness - q[x*xstride]);
-
- if( deviation*10 >= thresh * *width )
- break;
- }
-
- // Bottom crop
- for( y = *height - 1; y >= *height/2; y-- ) {
- bounds->h = y;
- average_brightness = 0;
- deviation = 0;
- q = *image + y*ystride;
- for( x = 0; x < *width; x++ )
- average_brightness += q[x*xstride];
-
- average_brightness /= *width;
-
- for( x = 0; x < *width; x++ )
- deviation += abs(average_brightness - q[x*xstride]);
-
- if( deviation*10 >= thresh * *width)
- break;
- }
-
- // Left crop
- for( x = 0; x < *width/2; x++ ) {
- bounds->x = x;
- average_brightness = 0;
- deviation = 0;
- q = *image + x*xstride;
- for( y = 0; y < *height; y++ )
- average_brightness += q[y*ystride];
-
- average_brightness /= *height;
-
- for( y = 0; y < *height; y++ )
- deviation += abs(average_brightness - q[y*ystride]);
-
- if( deviation*10 >= thresh * *width )
- break;
- }
-
- // Right crop
- for( x = *width - 1; x >= *width/2; x-- ) {
- bounds->w = x;
- average_brightness = 0;
- deviation = 0;
- q = *image + x*xstride;
- for( y = 0; y < *height; y++ )
- average_brightness += q[y*ystride];
-
- average_brightness /= *height;
-
- for( y = 0; y < *height; y++ )
- deviation += abs(average_brightness - q[y*ystride]);
-
- if( deviation*10 >= thresh * *width )
- break;
- }
-
- /* Debug: Draw arrows to show crop */
- if( mlt_properties_get_int( properties, "debug") == 1 )
- {
- init_arrows( format, *width, *height );
-
- draw_arrow(*image, bounds->x, *height/2, bounds->x+50, *height/2, 100);
- draw_arrow(*image, *width/2, bounds->y, *width/2, bounds->y+50, 100);
- draw_arrow(*image, bounds->w, *height/2, bounds->w-50, *height/2, 100);
- draw_arrow(*image, *width/2, bounds->h, *width/2, bounds->h-50, 100);
- draw_arrow(*image, bounds->x, bounds->y, bounds->x+40, bounds->y+30, 100);
- draw_arrow(*image, bounds->x, bounds->h, bounds->x+40, bounds->h-30, 100);
- draw_arrow(*image, bounds->w, bounds->y, bounds->w-40, bounds->y+30, 100);
- draw_arrow(*image, bounds->w, bounds->h, bounds->w-40, bounds->h-30, 100);
- }
-
- // Convert to width and correct indexing
- bounds->w -= bounds->x - 1;
- bounds->h -= bounds->y - 1;
-
- if( mlt_properties_get_int( properties, "debug") == 1 )
- fprintf(stderr, "Top:%f Left:%f Width:%f Height:%f\n", bounds->y, bounds->x, bounds->w, bounds->h);
-
- /* inject into frame */
- mlt_properties_set_data( MLT_FRAME_PROPERTIES(this), "bounds", bounds, sizeof( struct mlt_geometry_item_s ), NULL, NULL );
-
- return error;
-}
-
-
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- // Put the filter object somewhere we can find it
- mlt_frame_push_service( frame, this);
-
- // Push the frame filter
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-mlt_filter filter_crop_detect_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
-
- /* defaults */
- mlt_properties_set_int( MLT_FILTER_PROPERTIES(this), "frequency", 1);
- mlt_properties_set_int( MLT_FILTER_PROPERTIES(this), "thresh", 5);
- mlt_properties_set_int( MLT_FILTER_PROPERTIES(this), "clip", 5);
- mlt_properties_set_int( MLT_FILTER_PROPERTIES(this), "former_producer_id", -1);
-
- }
-
- return this;
-}
-
-/** This source code will self destruct in 5...4...3...
-*/
-
+++ /dev/null
-/*
- * /brief fast motion estimation filter
- * /author Zachary Drew, Copyright 2005
- *
- * Currently only uses Gamma data for comparisonon (bug or feature?)
- * SSE optimized where available.
- *
- * Vector orientation: The vector data that is generated for the current frame specifies
- * the motion from the previous frame to the current frame. To know how a macroblock
- * in the current frame will move in the future, the next frame is needed.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-#include "filter_motion_est.h"
-#include <framework/mlt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#ifdef USE_SSE
-#include "sad_sse.h"
-#endif
-
-#define NDEBUG
-#include <assert.h>
-
-#undef DEBUG
-#undef DEBUG_ASM
-#undef BENCHMARK
-#undef COUNT_COMPARES
-
-#define DIAMOND_SEARCH 0x0
-#define FULL_SEARCH 0x1
-#define SHIFT 8
-#define MIN(a,b) ((a) > (b) ? (b) : (a))
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-
-struct motion_est_context_s
-{
- int initialized; // true if filter has been initialized
-
-#ifdef COUNT_COMPARES
- int compares;
-#endif
-
- /* same as mlt_frame's parameters */
- int width, height;
-
- /* Operational details */
- int mb_w, mb_h;
- int xstride, ystride;
- uint8_t *cache_image; // Copy of current frame
- uint8_t *former_image; // Copy of former frame
- int search_method;
- int skip_prediction;
- int shot_change;
- int limit_x, limit_y; // max x and y of a motion vector
- int initial_thresh;
- int check_chroma; // if check_chroma == 1 then compare chroma
- int denoise;
- int previous_msad;
- int show_reconstruction;
- int toggle_when_paused;
- int show_residual;
-
- /* bounds */
- struct mlt_geometry_item_s bounds; // Current bounds (from filters crop_detect, autotrack rectangle, or other)
-
- /* bounds in macroblock units; macroblocks are completely contained within the boundry */
- int left_mb, prev_left_mb, right_mb, prev_right_mb;
- int top_mb, prev_top_mb, bottom_mb, prev_bottom_mb;
-
- /* size of our vector buffers */
- int mv_buffer_height, mv_buffer_width, mv_size;
-
- /* vector buffers */
- int former_vectors_valid; //<! true if the previous frame's buffered motion vector data is valid
- motion_vector *former_vectors;
- motion_vector *current_vectors;
- motion_vector *denoise_vectors;
- mlt_position former_frame_position, current_frame_position;
-
- /* diagnostic metrics */
- float predictive_misses; // How often do the prediction motion vectors fail?
- int comparison_average; // How far does the best estimation deviate from a perfect comparison?
- int bad_comparisons;
- int average_length;
- int average_x, average_y;
-
- /* run-time configurable comparison functions */
- int (*compare_reference)(uint8_t *, uint8_t *, int, int, int, int);
- int (*compare_optimized)(uint8_t *, uint8_t *, int, int, int, int);
-
-};
-
-// This is used to constrains pixel operations between two blocks to be within the image boundry
-inline static int constrain( int *x, int *y, int *w, int *h,
- const int dx, const int dy,
- const int left, const int right,
- const int top, const int bottom)
-{
- uint32_t penalty = 1 << SHIFT; // Retain a few extra bits of precision
- int x2 = *x + dx;
- int y2 = *y + dy;
- int w_remains = *w;
- int h_remains = *h;
-
- // Origin of macroblock moves left of image boundy
- if( *x < left || x2 < left ) {
- w_remains = *w - left + ((*x < x2) ? *x : x2);
- *x += *w - w_remains;
- }
- // Portion of macroblock moves right of image boundry
- else if( *x + *w > right || x2 + *w > right )
- w_remains = right - ((*x > x2) ? *x : x2);
-
- // Origin of macroblock moves above image boundy
- if( *y < top || y2 < top ) {
- h_remains = *h - top + ((*y < y2) ? *y : y2);
- *y += *h - h_remains;
- }
- // Portion of macroblock moves bellow image boundry
- else if( *y + *h > bottom || y2 + *h > bottom )
- h_remains = bottom - ((*y > y2) ? *y : y2);
-
- if( w_remains == *w && h_remains == *h ) return penalty;
- if( w_remains <= 0 || h_remains <= 0) return 0; // Block is clipped out of existance
- penalty = (*w * *h * penalty)
- / ( w_remains * h_remains); // Recipricol of the fraction of the block that remains
-
- assert(*x >= left); assert(x2 + *w - w_remains >= left);
- assert(*y >= top); assert(y2 + *h - h_remains >= top);
- assert(*x + w_remains <= right); assert(x2 + w_remains <= right);
- assert(*y + h_remains <= bottom); assert(y2 + h_remains <= bottom);
-
- *w = w_remains; // Update the width and height
- *h = h_remains;
-
- return penalty;
-}
-
-/** /brief Reference Sum of Absolute Differences comparison function
-*
-*/
-static int sad_reference( uint8_t *block1, uint8_t *block2, const int xstride, const int ystride, const int w, const int h )
-{
- int i, j, score = 0;
- for ( j = 0; j < h; j++ ){
- for ( i = 0; i < w; i++ ){
- score += ABS( block1[i*xstride] - block2[i*xstride] );
- }
- block1 += ystride;
- block2 += ystride;
- }
-
- return score;
-}
-
-
-/** /brief Abstracted block comparison function
-*/
-inline static int block_compare( uint8_t *block1,
- uint8_t *block2,
- int x,
- int y,
- int dx,
- int dy,
- struct motion_est_context_s *c)
-{
-
-#ifdef COUNT_COMPARES
- c->compares++;
-#endif
-
- int score;
-
- // Default comparison may be overridden by the slower, more capable reference comparison
- int (*cmp)(uint8_t *, uint8_t *, int, int, int, int) = c->compare_optimized;
-
- // vector displacement limited has been exceeded
- if( ABS( dx ) >= c->limit_x || ABS( dy ) >= c->limit_y )
- return MAX_MSAD;
-
- int mb_w = c->mb_w; // Some writeable local copies
- int mb_h = c->mb_h;
-
- // Determine if either macroblock got clipped
- int penalty = constrain( &x, &y, &mb_w, &mb_h, dx, dy, 0, c->width, 0, c->height);
-
- // Some gotchas
- if( penalty == 0 ) // Clipped out of existance: Return worst score
- return MAX_MSAD;
- else if( penalty != 1<<SHIFT ) // Nonstandard macroblock dimensions: Disable SIMD optimizizations.
- cmp = c->compare_reference;
-
- // Calculate the memory locations of the macroblocks
- block1 += x * c->xstride + y * c->ystride;
- block2 += (x+dx) * c->xstride + (y+dy) * c->ystride;
-
- #ifdef DEBUG_ASM
- if( penalty == 1<<SHIFT ){
- score = c->compare_reference( block1, block2, c->xstride, c->ystride, mb_w, mb_h );
- int score2 = c->compare_optimized( block1, block2, c->xstride, c->ystride, mb_w, mb_h );
- if ( score != score2 )
- fprintf(stderr, "Your assembly doesn't work! Reference: %d Asm: %d\n", score, score2);
- }
- else
- #endif
-
- score = cmp( block1, block2, c->xstride, c->ystride, mb_w, mb_h );
-
- return ( score * penalty ) >> SHIFT; // Ditch the extra precision
-}
-
-static inline void check_candidates ( uint8_t *ref,
- uint8_t *candidate_base,
- const int x,
- const int y,
- const motion_vector *candidates,// Contains to_x & to_y
- const int count, // Number of candidates
- const int unique, // Sometimes we know the candidates are unique
- motion_vector *result,
- struct motion_est_context_s *c )
-{
- int score, i, j;
- /* Scan for the best candidate */
- for ( i = 0; i < count; i++ )
- {
- // this little dohicky ignores duplicate candidates, if they are possible
- if ( unique == 0 ) {
- j = 0;
- while ( j < i )
- {
- if ( candidates[j].dx == candidates[i].dx &&
- candidates[j].dy == candidates[i].dy )
- goto next_for_loop;
-
- j++;
- }
- }
-
- // Luma
- score = block_compare( ref, candidate_base,
- x, y,
- candidates[i].dx, // from
- candidates[i].dy,
- c);
-
- if ( score < result->msad ) { // New minimum
- result->dx = candidates[i].dx;
- result->dy = candidates[i].dy;
- result->msad = score;
- }
- next_for_loop:;
- }
-}
-
-/* /brief Diamond search
-* Operates on a single macroblock
-*/
-static inline void diamond_search(
- uint8_t *ref, //<! Image data from previous frame
- uint8_t *candidate_base, //<! Image data in current frame
- const int x, //<! X upper left corner of macroblock
- const int y, //<! U upper left corner of macroblock
- struct motion_vector_s *result, //<! Best predicted mv and eventual result
- struct motion_est_context_s *c) //<! motion estimation context
-{
-
- // diamond search pattern
- motion_vector candidates[4];
-
- // Keep track of best and former best candidates
- motion_vector best, former;
- best.dx = 0;
- best.dy = 0;
- former.dx = 0;
- former.dy = 0;
-
- // The direction of the refinement needs to be known
- motion_vector current;
-
- int i, first = 1;
-
- // Loop through the search pattern
- while( 1 ) {
-
- current.dx = result->dx;
- current.dy = result->dy;
-
- if ( first == 1 ) // Set the initial pattern
- {
- candidates[0].dx = result->dx + 1; candidates[0].dy = result->dy + 0;
- candidates[1].dx = result->dx + 0; candidates[1].dy = result->dy + 1;
- candidates[2].dx = result->dx - 1; candidates[2].dy = result->dy + 0;
- candidates[3].dx = result->dx + 0; candidates[3].dy = result->dy - 1;
- i = 4;
- }
- else // Construct the next portion of the search pattern
- {
- candidates[0].dx = result->dx + best.dx;
- candidates[0].dy = result->dy + best.dy;
- if (best.dx == former.dx && best.dy == former.dy) {
- candidates[1].dx = result->dx + best.dy;
- candidates[1].dy = result->dy + best.dx; // Yes, the wires
- candidates[2].dx = result->dx - best.dy; // are crossed
- candidates[2].dy = result->dy - best.dx;
- i = 3;
- } else {
- candidates[1].dx = result->dx + former.dx;
- candidates[1].dy = result->dy + former.dy;
- i = 2;
- }
-
- former.dx = best.dx; former.dy = best.dy; // Keep track of new former best
- }
-
- check_candidates ( ref, candidate_base, x, y, candidates, i, 1, result, c );
-
- // Which candidate was the best?
- best.dx = result->dx - current.dx;
- best.dy = result->dy - current.dy;
-
- // A better canidate was not found
- if ( best.dx == 0 && best.dy == 0 )
- return;
-
- if ( first == 1 ){
- first = 0;
- former.dx = best.dx; former.dy = best.dy; // First iteration, sensible value for former.d*
- }
- }
-}
-
-/* /brief Full (brute) search
-* Operates on a single macroblock
-*/
-__attribute__((used))
-static void full_search(
- uint8_t *ref, //<! Image data from previous frame
- uint8_t *candidate_base, //<! Image data in current frame
- int x, //<! X upper left corner of macroblock
- int y, //<! U upper left corner of macroblock
- struct motion_vector_s *result, //<! Best predicted mv and eventual result
- struct motion_est_context_s *c) //<! motion estimation context
-{
- // Keep track of best candidate
- int i,j,score;
-
- // Go loopy
- for( i = -c->mb_w; i <= c->mb_w; i++ ){
- for( j = -c->mb_h; j <= c->mb_h; j++ ){
-
- score = block_compare( ref, candidate_base,
- x,
- y,
- x + i,
- y + j,
- c);
-
- if ( score < result->msad ) {
- result->dx = i;
- result->dy = j;
- result->msad = score;
- }
- }
- }
-}
-
-// Macros for pointer calculations
-#define CURRENT(i,j) ( c->current_vectors + (j)*c->mv_buffer_width + (i) )
-#define FORMER(i,j) ( c->former_vectors + (j)*c->mv_buffer_width + (i) )
-#define DENOISE(i,j) ( c->denoise_vectors + (j)*c->mv_buffer_width + (i) )
-
-int ncompare (const void * a, const void * b)
-{
- return ( *(const int*)a - *(const int*)b );
-}
-
-// motion vector denoising
-// for x and y components seperately,
-// change the vector to be the median value of the 9 adjacent vectors
-static void median_denoise( motion_vector *v, struct motion_est_context_s *c )
-{
- int xvalues[9], yvalues[9];
-
- int i,j,n;
- for( j = c->top_mb; j <= c->bottom_mb; j++ )
- for( i = c->left_mb; i <= c->right_mb; i++ ){
- {
- n = 0;
-
- xvalues[n ] = CURRENT(i,j)->dx; // Center
- yvalues[n++] = CURRENT(i,j)->dy;
-
- if( i > c->left_mb ) // Not in First Column
- {
- xvalues[n ] = CURRENT(i-1,j)->dx; // Left
- yvalues[n++] = CURRENT(i-1,j)->dy;
-
- if( j > c->top_mb ) {
- xvalues[n ] = CURRENT(i-1,j-1)->dx; // Upper Left
- yvalues[n++] = CURRENT(i-1,j-1)->dy;
- }
-
- if( j < c->bottom_mb ) {
- xvalues[n ] = CURRENT(i-1,j+1)->dx; // Bottom Left
- yvalues[n++] = CURRENT(i-1,j+1)->dy;
- }
- }
- if( i < c->right_mb ) // Not in Last Column
- {
- xvalues[n ] = CURRENT(i+1,j)->dx; // Right
- yvalues[n++] = CURRENT(i+1,j)->dy;
-
-
- if( j > c->top_mb ) {
- xvalues[n ] = CURRENT(i+1,j-1)->dx; // Upper Right
- yvalues[n++] = CURRENT(i+1,j-1)->dy;
- }
-
- if( j < c->bottom_mb ) {
- xvalues[n ] = CURRENT(i+1,j+1)->dx; // Bottom Right
- yvalues[n++] = CURRENT(i+1,j+1)->dy;
- }
- }
- if( j > c->top_mb ) // Not in First Row
- {
- xvalues[n ] = CURRENT(i,j-1)->dx; // Top
- yvalues[n++] = CURRENT(i,j-1)->dy;
- }
-
- if( j < c->bottom_mb ) // Not in Last Row
- {
- xvalues[n ] = CURRENT(i,j+1)->dx; // Bottom
- yvalues[n++] = CURRENT(i,j+1)->dy;
- }
-
- qsort (xvalues, n, sizeof(int), ncompare);
- qsort (yvalues, n, sizeof(int), ncompare);
-
- if( n % 2 == 1 ) {
- DENOISE(i,j)->dx = xvalues[n/2];
- DENOISE(i,j)->dy = yvalues[n/2];
- }
- else {
- DENOISE(i,j)->dx = (xvalues[n/2] + xvalues[n/2+1])/2;
- DENOISE(i,j)->dy = (yvalues[n/2] + yvalues[n/2+1])/2;
- }
- }
- }
-
- motion_vector *t = c->current_vectors;
- c->current_vectors = c->denoise_vectors;
- c->denoise_vectors = t;
-
-}
-
-// Credits: ffmpeg
-// return the median
-static inline int median_predictor(int a, int b, int c) {
- if ( a > b ){
- if ( c > b ){
- if ( c > a ) b = a;
- else b = c;
- }
- } else {
- if ( b > c ){
- if ( c > a ) b = c;
- else b = a;
- }
- }
- return b;
-}
-
-
-/** /brief Motion search
-*
-* For each macroblock in the current frame, estimate the block from the last frame that
-* matches best.
-*
-* Vocab: Colocated - the pixel in the previous frame at the current position
-*
-* Based on enhanced predictive zonal search. [Tourapis 2002]
-*/
-static void motion_search( uint8_t *from, //<! Image data.
- uint8_t *to, //<! Image data. Rigid grid.
- struct motion_est_context_s *c) //<! The context
-{
-
-#ifdef COUNT_COMPARES
- compares = 0;
-#endif
-
- motion_vector candidates[10];
- motion_vector *here; // This one gets used alot (about 30 times per macroblock)
- int n = 0;
-
- int i, j, count=0;
-
- // For every macroblock, perform motion vector estimation
- for( i = c->left_mb; i <= c->right_mb; i++ ){
- for( j = c->top_mb; j <= c->bottom_mb; j++ ){
-
- here = CURRENT(i,j);
- here->valid = 1;
- here->color = 100;
- here->msad = MAX_MSAD;
- count++;
- n = 0;
-
-
- /* Stack the predictors [i.e. checked in reverse order] */
-
- /* Adjacent to collocated */
- if( c->former_vectors_valid )
- {
- // Top of colocated
- if( j > c->prev_top_mb ){// && COL_TOP->valid ){
- candidates[n ].dx = FORMER(i,j-1)->dx;
- candidates[n++].dy = FORMER(i,j-1)->dy;
- }
-
- // Left of colocated
- if( i > c->prev_left_mb ){// && COL_LEFT->valid ){
- candidates[n ].dx = FORMER(i-1,j)->dx;
- candidates[n++].dy = FORMER(i-1,j)->dy;
- }
-
- // Right of colocated
- if( i < c->prev_right_mb ){// && COL_RIGHT->valid ){
- candidates[n ].dx = FORMER(i+1,j)->dx;
- candidates[n++].dy = FORMER(i+1,j)->dy;
- }
-
- // Bottom of colocated
- if( j < c->prev_bottom_mb ){// && COL_BOTTOM->valid ){
- candidates[n ].dx = FORMER(i,j+1)->dx;
- candidates[n++].dy = FORMER(i,j+1)->dy;
- }
-
- // And finally, colocated
- candidates[n ].dx = FORMER(i,j)->dx;
- candidates[n++].dy = FORMER(i,j)->dy;
- }
-
- // For macroblocks not in the top row
- if ( j > c->top_mb) {
-
- // Top if ( TOP->valid ) {
- candidates[n ].dx = CURRENT(i,j-1)->dx;
- candidates[n++].dy = CURRENT(i,j-1)->dy;
- //}
-
- // Top-Right, macroblocks not in the right row
- if ( i < c->right_mb ){// && TOP_RIGHT->valid ) {
- candidates[n ].dx = CURRENT(i+1,j-1)->dx;
- candidates[n++].dy = CURRENT(i+1,j-1)->dy;
- }
- }
-
- // Left, Macroblocks not in the left column
- if ( i > c->left_mb ){// && LEFT->valid ) {
- candidates[n ].dx = CURRENT(i-1,j)->dx;
- candidates[n++].dy = CURRENT(i-1,j)->dy;
- }
-
- /* Median predictor vector (median of left, top, and top right adjacent vectors) */
- if ( i > c->left_mb && j > c->top_mb && i < c->right_mb
- )//&& LEFT->valid && TOP->valid && TOP_RIGHT->valid )
- {
- candidates[n ].dx = median_predictor( CURRENT(i-1,j)->dx, CURRENT(i,j-1)->dx, CURRENT(i+1,j-1)->dx);
- candidates[n++].dy = median_predictor( CURRENT(i-1,j)->dy, CURRENT(i,j-1)->dy, CURRENT(i+1,j-1)->dy);
- }
-
- // Zero vector
- candidates[n ].dx = 0;
- candidates[n++].dy = 0;
-
- int x = i * c->mb_w;
- int y = j * c->mb_h;
- check_candidates ( to, from, x, y, candidates, n, 0, here, c );
-
-
-#ifndef FULLSEARCH
- diamond_search( to, from, x, y, here, c);
-#else
- full_search( to, from, x, y, here, c);
-#endif
-
- assert( x + c->mb_w + here->dx > 0 ); // All macroblocks must have area > 0
- assert( y + c->mb_h + here->dy > 0 );
- assert( x + here->dx < c->width );
- assert( y + here->dy < c->height );
-
- } /* End column loop */
- } /* End row loop */
-
-#ifdef USE_SSE
- asm volatile ( "emms" );
-#endif
-
-#ifdef COUNT_COMPARES
- fprintf(stderr, "%d comparisons per block were made", compares/count);
-#endif
- return;
-}
-
-void collect_post_statistics( struct motion_est_context_s *c ) {
-
- c->comparison_average = 0;
- c->average_length = 0;
- c->average_x = 0;
- c->average_y = 0;
-
- int i, j, count = 0;
-
- for ( i = c->left_mb; i <= c->right_mb; i++ ){
- for ( j = c->top_mb; j <= c->bottom_mb; j++ ){
-
- count++;
- c->comparison_average += CURRENT(i,j)->msad;
- c->average_x += CURRENT(i,j)->dx;
- c->average_y += CURRENT(i,j)->dy;
-
-
- }
- }
-
- if ( count > 0 )
- {
- c->comparison_average /= count;
- c->average_x /= count;
- c->average_y /= count;
- c->average_length = sqrt( c->average_x * c->average_x + c->average_y * c->average_y );
- }
-
-}
-
-static void init_optimizations( struct motion_est_context_s *c )
-{
- switch(c->mb_w){
-#ifdef USE_SSE
- case 4: if(c->mb_h == 4) c->compare_optimized = sad_sse_422_luma_4x4;
- else c->compare_optimized = sad_sse_422_luma_4w;
- break;
- case 8: if(c->mb_h == 8) c->compare_optimized = sad_sse_422_luma_8x8;
- else c->compare_optimized = sad_sse_422_luma_8w;
- break;
- case 16: if(c->mb_h == 16) c->compare_optimized = sad_sse_422_luma_16x16;
- else c->compare_optimized = sad_sse_422_luma_16w;
- break;
- case 32: if(c->mb_h == 32) c->compare_optimized = sad_sse_422_luma_32x32;
- else c->compare_optimized = sad_sse_422_luma_32w;
- break;
- case 64: c->compare_optimized = sad_sse_422_luma_64w;
- break;
-#endif
- default: c->compare_optimized = sad_reference;
- break;
- }
-}
-
-inline static void set_red(uint8_t *image, struct motion_est_context_s *c)
-{
- int n;
- for( n = 0; n < c->width * c->height * 2; n+=4 )
- {
- image[n] = 79;
- image[n+1] = 91;
- image[n+2] = 79;
- image[n+3] = 237;
- }
-
-}
-
-static void show_residual( uint8_t *result, struct motion_est_context_s *c )
-{
- int i, j;
- int x,y,w,h;
- int dx, dy;
- int tx,ty;
- uint8_t *b, *r;
-
-// set_red(result,c);
-
- for( j = c->top_mb; j <= c->bottom_mb; j++ ){
- for( i = c->left_mb; i <= c->right_mb; i++ ){
-
- dx = CURRENT(i,j)->dx;
- dy = CURRENT(i,j)->dy;
- w = c->mb_w;
- h = c->mb_h;
- x = i * w;
- y = j * h;
-
- // Denoise function caused some blocks to be completely clipped, ignore them
- if (constrain( &x, &y, &w, &h, dx, dy, 0, c->width, 0, c->height) == 0 )
- continue;
-
- for( ty = y; ty < y + h ; ty++ ){
- for( tx = x; tx < x + w ; tx++ ){
-
- b = c->former_image + (tx+dx)*c->xstride + (ty+dy)*c->ystride;
- r = result + tx*c->xstride + ty*c->ystride;
-
- r[0] = 16 + ABS( r[0] - b[0] );
-
- if( dx % 2 == 0 )
- r[1] = 128 + ABS( r[1] - b[1] );
- else
- // FIXME: may exceed boundies
- r[1] = 128 + ABS( r[1] - ( *(b-1) + b[3] ) /2 );
- }
- }
- }
- }
-}
-
-static void show_reconstruction( uint8_t *result, struct motion_est_context_s *c )
-{
- int i, j;
- int x,y,w,h;
- int dx,dy;
- uint8_t *r, *s;
- int tx,ty;
-
- for( i = c->left_mb; i <= c->right_mb; i++ ){
- for( j = c->top_mb; j <= c->bottom_mb; j++ ){
-
- dx = CURRENT(i,j)->dx;
- dy = CURRENT(i,j)->dy;
- w = c->mb_w;
- h = c->mb_h;
- x = i * w;
- y = j * h;
-
- // Denoise function caused some blocks to be completely clipped, ignore them
- if (constrain( &x, &y, &w, &h, dx, dy, 0, c->width, 0, c->height) == 0 )
- continue;
-
- for( ty = y; ty < y + h ; ty++ ){
- for( tx = x; tx < x + w ; tx++ ){
-
- r = result + tx*c->xstride + ty*c->ystride;
- s = c->former_image + (tx+dx)*c->xstride + (ty+dy)*c->ystride;
-
- r[0] = s[0];
-
- if( dx % 2 == 0 )
- r[1] = s[1];
- else
- // FIXME: may exceed boundies
- r[1] = ( *(s-1) + s[3] ) /2;
- }
- }
- }
- }
-}
-
-// Image stack(able) method
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter
- mlt_filter filter = mlt_frame_pop_service( frame );
-
- // Get the motion_est context object
- struct motion_est_context_s *c = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "context", NULL);
-
-
- // Get the new image and frame number
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- #ifdef BENCHMARK
- struct timeval start; gettimeofday(&start, NULL );
- #endif
-
-
- if( error != 0 )
- mlt_properties_debug( MLT_FRAME_PROPERTIES(frame), "error after mlt_frame_get_image() in motion_est", stderr );
-
- c->current_frame_position = mlt_frame_get_position( frame );
-
- /* Context Initialization */
- if ( c->initialized == 0 ) {
-
- // Get the filter properties object
- mlt_properties properties = mlt_filter_properties( filter );
-
- c->width = *width;
- c->height = *height;
-
- /* Get parameters that may have been overridden */
- if( mlt_properties_get( properties, "macroblock_width") != NULL )
- c->mb_w = mlt_properties_get_int( properties, "macroblock_width");
-
- if( mlt_properties_get( properties, "macroblock_height") != NULL )
- c->mb_h = mlt_properties_get_int( properties, "macroblock_height");
-
- if( mlt_properties_get( properties, "prediction_thresh") != NULL )
- c->initial_thresh = mlt_properties_get_int( properties, "prediction_thresh" );
- else
- c->initial_thresh = c->mb_w * c->mb_h;
-
- if( mlt_properties_get( properties, "search_method") != NULL )
- c->search_method = mlt_properties_get_int( properties, "search_method");
-
- if( mlt_properties_get( properties, "skip_prediction") != NULL )
- c->skip_prediction = mlt_properties_get_int( properties, "skip_prediction");
-
- if( mlt_properties_get( properties, "limit_x") != NULL )
- c->limit_x = mlt_properties_get_int( properties, "limit_x");
-
- if( mlt_properties_get( properties, "limit_y") != NULL )
- c->limit_y = mlt_properties_get_int( properties, "limit_y");
-
- if( mlt_properties_get( properties, "check_chroma" ) != NULL )
- c->check_chroma = mlt_properties_get_int( properties, "check_chroma" );
-
- if( mlt_properties_get( properties, "denoise" ) != NULL )
- c->denoise = mlt_properties_get_int( properties, "denoise" );
-
- if( mlt_properties_get( properties, "show_reconstruction" ) != NULL )
- c->show_reconstruction = mlt_properties_get_int( properties, "show_reconstruction" );
-
- if( mlt_properties_get( properties, "show_residual" ) != NULL )
- c->show_residual = mlt_properties_get_int( properties, "show_residual" );
-
- if( mlt_properties_get( properties, "toggle_when_paused" ) != NULL )
- c->toggle_when_paused = mlt_properties_get_int( properties, "toggle_when_paused" );
-
- init_optimizations( c );
-
- // Calculate the dimensions in macroblock units
- c->mv_buffer_width = (*width / c->mb_w);
- c->mv_buffer_height = (*height / c->mb_h);
-
- // Size of the motion vector buffer
- c->mv_size = c->mv_buffer_width * c->mv_buffer_height * sizeof(struct motion_vector_s);
-
- // Allocate the motion vector buffers
- c->former_vectors = mlt_pool_alloc( c->mv_size );
- c->current_vectors = mlt_pool_alloc( c->mv_size );
- c->denoise_vectors = mlt_pool_alloc( c->mv_size );
-
- // Register motion buffers for destruction
- mlt_properties_set_data( properties, "current_motion_vectors", (void *)c->current_vectors, 0, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "former_motion_vectors", (void *)c->former_vectors, 0, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "denoise_motion_vectors", (void *)c->denoise_vectors, 0, mlt_pool_release, NULL );
-
- c->former_vectors_valid = 0;
- memset( c->former_vectors, 0, c->mv_size );
-
- // Calculate the size of our steps (the number of bytes that seperate adjacent pixels in X and Y direction)
- switch( *format ) {
- case mlt_image_yuv422:
- c->xstride = 2;
- c->ystride = c->xstride * *width;
- break;
- default:
- // I don't know
- fprintf(stderr, "\"I am unfamiliar with your new fangled pixel format!\" -filter_motion_est\n");
- return -1;
- }
-
- // Allocate a cache for the previous frame's image
- c->former_image = mlt_pool_alloc( *width * *height * 2 );
- c->cache_image = mlt_pool_alloc( *width * *height * 2 );
-
- // Register for destruction
- mlt_properties_set_data( properties, "cache_image", (void *)c->cache_image, 0, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "former_image", (void *)c->former_image, 0, mlt_pool_release, NULL );
-
- c->former_frame_position = c->current_frame_position;
- c->previous_msad = 0;
-
- c->initialized = 1;
- }
-
- /* Check to see if somebody else has given us bounds */
- struct mlt_geometry_item_s *bounds = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "bounds", NULL );
-
- if( bounds != NULL ) {
- // translate pixel units (from bounds) to macroblock units
- // make sure whole macroblock stays within bounds
- c->left_mb = ( bounds->x + c->mb_w - 1 ) / c->mb_w;
- c->top_mb = ( bounds->y + c->mb_h - 1 ) / c->mb_h;
- c->right_mb = ( bounds->x + bounds->w ) / c->mb_w - 1;
- c->bottom_mb = ( bounds->y + bounds->h ) / c->mb_h - 1;
- c->bounds.x = bounds->x;
- c->bounds.y = bounds->y;
- c->bounds.w = bounds->w;
- c->bounds.h = bounds->h;
- } else {
- c->left_mb = c->prev_left_mb = 0;
- c->top_mb = c->prev_top_mb = 0;
- c->right_mb = c->prev_right_mb = c->mv_buffer_width - 1; // Zero indexed
- c->bottom_mb = c->prev_bottom_mb = c->mv_buffer_height - 1;
- c->bounds.x = 0;
- c->bounds.y = 0;
- c->bounds.w = *width;
- c->bounds.h = *height;
- }
-
- // If video is advancing, run motion vector algorithm and etc...
- if( c->former_frame_position + 1 == c->current_frame_position )
- {
-
- // Swap the motion vector buffers and reuse allocated memory
- struct motion_vector_s *temp = c->current_vectors;
- c->current_vectors = c->former_vectors;
- c->former_vectors = temp;
-
- // This is done because filter_vismv doesn't pay attention to frame boundry
- memset( c->current_vectors, 0, c->mv_size );
-
- // Perform the motion search
- motion_search( c->cache_image, *image, c );
-
- collect_post_statistics( c );
-
-
- // Detect shot changes
- if( c->comparison_average > 10 * c->mb_w * c->mb_h &&
- c->comparison_average > c->previous_msad * 2 )
- {
- fprintf(stderr, " - SAD: %d <<Shot change>>\n", c->comparison_average);
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "shot_change", 1);
- // c->former_vectors_valid = 0; // Invalidate the previous frame's predictors
- c->shot_change = 1;
- }
- else {
- c->former_vectors_valid = 1;
- c->shot_change = 0;
- //fprintf(stderr, " - SAD: %d\n", c->comparison_average);
- }
-
- c->previous_msad = c->comparison_average;
-
- if( c->comparison_average != 0 ) { // If the frame is not a duplicate of the previous frame
-
- // denoise the vector buffer
- if( c->denoise )
- median_denoise( c->current_vectors, c );
-
- // Pass the new vector data into the frame
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "motion_est.vectors",
- (void*)c->current_vectors, c->mv_size, NULL, NULL );
-
- // Cache the frame's image. Save the old cache. Reuse memory.
- // After this block, exactly two unique frames will be cached
- uint8_t *timg = c->cache_image;
- c->cache_image = c->former_image;
- c->former_image = timg;
- memcpy( c->cache_image, *image, *width * *height * c->xstride );
-
-
- }
- else {
- // Undo the Swap, This fixes the ugliness caused by a duplicate frame
- temp = c->current_vectors;
- c->current_vectors = c->former_vectors;
- c->former_vectors = temp;
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "motion_est.vectors",
- (void*)c->former_vectors, c->mv_size, NULL, NULL );
- }
-
-
- if( c->shot_change == 1)
- ;
- else if( c->show_reconstruction )
- show_reconstruction( *image, c );
- else if( c->show_residual )
- show_residual( *image, c );
-
- }
- // paused
- else if( c->former_frame_position == c->current_frame_position )
- {
- // Pass the old vector data into the frame if it's valid
- if( c->former_vectors_valid == 1 ) {
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "motion_est.vectors",
- (void*)c->current_vectors, c->mv_size, NULL, NULL );
-
- if( c->shot_change == 1)
- ;
- else if( c->toggle_when_paused == 1 ) {
- if( c->show_reconstruction )
- show_reconstruction( *image, c );
- else if( c->show_residual )
- show_residual( *image, c );
- c->toggle_when_paused = 2;
- }
- else if( c->toggle_when_paused == 2 )
- c->toggle_when_paused = 1;
- else {
- if( c->show_reconstruction )
- show_reconstruction( *image, c );
- else if( c->show_residual )
- show_residual( *image, c );
- }
-
- }
-
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "shot_change", c->shot_change);
- }
- // there was jump in frame number
- else {
-// fprintf(stderr, "Warning: there was a frame number jumped from %d to %d.\n", c->former_frame_position, c->current_frame_position);
- c->former_vectors_valid = 0;
- }
-
-
- // Cache our bounding geometry for the next frame's processing
- c->prev_left_mb = c->left_mb;
- c->prev_top_mb = c->top_mb;
- c->prev_right_mb = c->right_mb;
- c->prev_bottom_mb = c->bottom_mb;
-
- // Remember which frame this is
- c->former_frame_position = c->current_frame_position;
-
-
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.macroblock_width", c->mb_w );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.macroblock_height", c->mb_h );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.left_mb", c->left_mb );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.right_mb", c->right_mb );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.top_mb", c->top_mb );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "motion_est.bottom_mb", c->bottom_mb );
-
- #ifdef BENCHMARK
- struct timeval finish; gettimeofday(&finish, NULL ); int difference = (finish.tv_sec - start.tv_sec) * 1000000 + (finish.tv_usec - start.tv_usec);
- fprintf(stderr, " in frame %d:%d usec\n", c->current_frame_position, difference);
- #endif
-
-
- return error;
-}
-
-
-
-/** filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- // Keeps tabs on the filter object
- mlt_frame_push_service( frame, this);
-
- // Push the frame filter
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-mlt_filter filter_motion_est_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- // Get the properties object
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- // Initialize the motion estimation context
- struct motion_est_context_s *context;
- context = mlt_pool_alloc( sizeof(struct motion_est_context_s) );
- mlt_properties_set_data( properties, "context", (void *)context, sizeof( struct motion_est_context_s ),
- mlt_pool_release, NULL );
-
-
- // Register the filter
- this->process = filter_process;
-
- /* defaults that may be overridden */
- context->mb_w = 16;
- context->mb_h = 16;
- context->skip_prediction = 0;
- context->limit_x = 64;
- context->limit_y = 64;
- context->search_method = DIAMOND_SEARCH; // FIXME: not used
- context->check_chroma = 0;
- context->denoise = 1;
- context->show_reconstruction = 0;
- context->show_residual = 0;
- context->toggle_when_paused = 0;
-
- /* reference functions that may have optimized versions */
- context->compare_reference = sad_reference;
-
- // The rest of the buffers will be initialized when the filter is first processed
- context->initialized = 0;
- }
- return this;
-}
+++ /dev/null
-/*
- * Perform motion estimation
- * Zachary K Drew, Copyright 2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _FILTER_MOTION_EST_H_
-#define _FILTER_MOTION_EST_H_
-
-#include <framework/mlt_filter.h>
-
-extern mlt_filter filter_motion_est_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-#define MAX_MSAD 0xffff
-
-struct motion_vector_s
-{
- int msad; //<! Sum of Absolute Differences for this vector
- int dx; //<! integer X displacement
- int dy; //<! integer Y displacement
- int vert_dev; //<! a measure of vertical color deviation
- int horiz_dev; //<! a measure of horizontal color deviation
- int valid;
- int quality;
- uint8_t color; //<! The color
-};
-
-typedef struct motion_vector_s motion_vector;
-#endif
+++ /dev/null
-/*
- * /brief Draw motion vectors
- * /author Zachary Drew, Copyright 2004
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "filter_motion_est.h"
-#include "arrow_code.h"
-
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-static void paint_arrows( uint8_t *image, struct motion_vector_s *vectors, int w, int h, int mb_w, int mb_h )
-{
- int i, j, x, y;
- struct motion_vector_s *p;
- for( i = 0; i < w/mb_w; i++ ){
- for( j = 0; j < h/mb_h; j++ ){
- x = i*mb_w;
- y = j*mb_h;
- p = vectors + (w/mb_w)*j + i;
-
- if ( p->valid == 1 ) {
- //draw_rectangle_outline(image, x-1, y-1, mb_w+1, mb_h+1,100);
- //x += mb_w/4;
- //y += mb_h/4;
- //draw_rectangle_outline(image, x + p->dx, y + p->dy, mb_w, mb_h,100);
- x += mb_w/2;
- y += mb_h/2;
- draw_arrow(image, x, y, x + p->dx, y + p->dy, 100);
- //draw_rectangle_fill(image, x + p->dx, y + p->dy, mb_w, mb_h, 100);
- }
- else if ( p->valid == 2 ) {
- draw_rectangle_outline(image, x+1, y+1, mb_w-2, mb_h-2,100);
- }
- else if ( p->valid == 3 ) {
- draw_rectangle_fill(image, x-p->dx, y-p->dy, mb_w, mb_h,0);
- }
- else if ( p->valid == 4 ) {
- draw_line(image, x, y, x + 4, y, 100);
- draw_line(image, x, y, x, y + 4, 100);
- draw_line(image, x + 4, y, x, y + 4, 100);
-
- draw_line(image, x+mb_w-1, y+mb_h-1, x+mb_w-5, y+mb_h-1, 100);
- draw_line(image, x+mb_w-1, y+mb_h-1, x+mb_w-1, y+mb_h-5, 100);
- draw_line(image, x+mb_w-5, y+mb_h-1, x+mb_w-1, y+mb_h-5, 100);
- }
- }
- }
-}
-
-// Image stack(able) method
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the frame properties
- mlt_properties properties = MLT_FRAME_PROPERTIES(frame);
-
- // Get the new image
- int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
-
- if( error != 0 )
- mlt_properties_debug( MLT_FRAME_PROPERTIES(frame), "error after mlt_frame_get_image()", stderr );
-
-
- // Get the size of macroblocks in pixel units
- int macroblock_height = mlt_properties_get_int( properties, "motion_est.macroblock_height" );
- int macroblock_width = mlt_properties_get_int( properties, "motion_est.macroblock_width" );
-
- // Get the motion vectors
- struct motion_vector_s *current_vectors = mlt_properties_get_data( properties, "motion_est.vectors", NULL );
-
- init_arrows( format, *width, *height );
-
- if ( mlt_properties_get_int( properties, "shot_change" ) == 1 )
- {
- draw_line(*image, 0, 0, *width, *height, 100);
- draw_line(*image, 0, *height, *width, 0, 100);
- }
- if( current_vectors != NULL ) {
- paint_arrows( *image, current_vectors, *width, *height, macroblock_width, macroblock_height);
- }
-
- return error;
-}
-
-
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the frame filter
- mlt_frame_push_get_image( frame, filter_get_image );
-
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-
-mlt_filter filter_vismv_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
-
- }
-
- return this;
-}
-
-/** This source code will self destruct in 5...4...3...
-*/
-
-
-
-
-
-
-
-
+++ /dev/null
-/*
- * producer_slowmotion.c -- create subspeed frames
- * Author: Zachary Drew
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "filter_motion_est.h"
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <sys/time.h>
-#include <assert.h>
-#define SHIFT 8
-#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
-
-// This is used to constrains pixel operations between two blocks to be within the image boundry
-inline static int constrain( int *x, int *y, int *w, int *h,
- const int dx, const int dy,
- const int left, const int right,
- const int top, const int bottom)
-{
- uint32_t penalty = 1 << SHIFT; // Retain a few extra bits of precision
- int x2 = *x + dx;
- int y2 = *y + dy;
- int w_remains = *w;
- int h_remains = *h;
-
- // Origin of macroblock moves left of image boundy
- if( *x < left || x2 < left ) {
- w_remains = *w - left + ((*x < x2) ? *x : x2);
- *x += *w - w_remains;
- }
- // Portion of macroblock moves right of image boundry
- else if( *x + *w > right || x2 + *w > right )
- w_remains = right - ((*x > x2) ? *x : x2);
-
- // Origin of macroblock moves above image boundy
- if( *y < top || y2 < top ) {
- h_remains = *h - top + ((*y < y2) ? *y : y2);
- *y += *h - h_remains;
- }
- // Portion of macroblock moves bellow image boundry
- else if( *y + *h > bottom || y2 + *h > bottom )
- h_remains = bottom - ((*y > y2) ? *y : y2);
-
- if( w_remains == *w && h_remains == *h ) return penalty;
- if( w_remains <= 0 || h_remains <= 0) return 0; // Block is clipped out of existance
- penalty = (*w * *h * penalty)
- / ( w_remains * h_remains); // Recipricol of the fraction of the block that remains
-
- *w = w_remains; // Update the width and height
- *h = h_remains;
-
- return penalty;
-}
-
-static void motion_interpolate( uint8_t *first_image, uint8_t *second_image, uint8_t *output,
- int top_mb, int bottom_mb, int left_mb, int right_mb,
- int mb_w, int mb_h,
- int width, int height,
- int xstride, int ystride,
- double scale,
- motion_vector *vectors )
-{
- assert ( scale >= 0.0 && scale <= 1.0 );
-
- int i, j;
- int x,y,w,h;
- int dx, dy;
- int scaled_dx, scaled_dy;
- int tx,ty;
- uint8_t *f,*s,*r;
- motion_vector *here;
- int mv_width = width / mb_w;
-
- for( j = top_mb; j <= bottom_mb; j++ ){
- for( i = left_mb; i <= right_mb; i++ ){
-
- here = vectors + j*mv_width + i;
- scaled_dx = (1.0 - scale) * (double)here->dx;
- scaled_dy = (1.0 - scale) * (double)here->dy;
- dx = here->dx;
- dy = here->dy;
- w = mb_w; h = mb_h;
- x = i * w; y = j * h;
-
- // Denoise function caused some blocks to be completely clipped, ignore them
- if (constrain( &x, &y, &w, &h, dx, dy, 0, width, 0, height) == 0 )
- continue;
-
- for( ty = y; ty < y + h ; ty++ ){
- for( tx = x; tx < x + w ; tx++ ){
-
- f = first_image + (tx + dx )*xstride + (ty + dy )*ystride;
- s = second_image + (tx )*xstride + (ty )*ystride;
- r = output + (tx+scaled_dx)*xstride + (ty+scaled_dy)*ystride;
-/*
- if( ABS(f[0] - s[0]) > 3 * here->msad / (mb_w * mb_h * 2) )
- {
- r[0] = f[0];
- r[1] = f[1];
- }
-
- else
- {
-
-*/
- r[0] = ( 1.0 - scale ) * (double)f[0] + scale * (double)s[0];
-
- if( dx % 2 == 0 )
- {
- if( scaled_dx % 2 == 0 )
- r[1] = ( 1.0 - scale ) * (double)f[1] + scale * (double) s[1];
- else
- *(r-1) = ( 1.0 - scale ) * (double)f[1] + scale * (double) s[1];
- }
- else
- {
- if( scaled_dx %2 == 0 )
- // FIXME: may exceed boundies
- r[1] = ( 1.0 - scale ) * ( (double)(*(f-1) + (double)f[3]) / 2.0 ) + scale * (double) s[1];
- else
- // FIXME: may exceed boundies
- *(r-1) = ( 1.0 - scale ) * ( (double)(*(f-1) + (double)f[3]) / 2.0 ) + scale * (double) s[1];
- }
-// }
- }
- }
- }
- }
-}
-
-// Image stack(able) method
-static int slowmotion_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- // Get the filter object and properties
- mlt_producer producer = mlt_frame_pop_service( this );
- mlt_frame second_frame = mlt_frame_pop_service( this );
- mlt_frame first_frame = mlt_frame_pop_service( this );
-
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Frame properties objects
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( this );
- mlt_properties first_frame_properties = MLT_FRAME_PROPERTIES( first_frame );
- mlt_properties second_frame_properties = MLT_FRAME_PROPERTIES( second_frame );
-
- // image stride
- int size, xstride, ystride;
- switch( *format ){
- case mlt_image_yuv422:
- size = *width * *height * 2;
- xstride = 2;
- ystride = 2 * *width;
- break;
- default:
- fprintf(stderr, "Unsupported image format\n");
- return -1;
- }
-
- uint8_t *output = mlt_properties_get_data( producer_properties, "output_buffer", 0 );
- if( output == NULL )
- {
- output = mlt_pool_alloc( size );
-
- // Let someone else clean up
- mlt_properties_set_data( producer_properties, "output_buffer", output, size, mlt_pool_release, NULL );
- }
-
- uint8_t *first_image = mlt_properties_get_data( first_frame_properties, "image", NULL );
- uint8_t *second_image = mlt_properties_get_data( second_frame_properties, "image", NULL );
-
- // which frames are buffered?
-
- int error = 0;
-
- if( first_image == NULL )
- {
- error = mlt_frame_get_image( first_frame, &first_image, format, width, height, writable );
-
- if( error != 0 ) {
- fprintf(stderr, "first_image == NULL get image died\n");
- return error;
- }
- }
-
- if( second_image == NULL )
- {
- error = mlt_frame_get_image( second_frame, &second_image, format, width, height, writable );
-
- if( error != 0 ) {
- fprintf(stderr, "second_image == NULL get image died\n");
- return error;
- }
- }
-
- // These need to passed onto the frame for other
- mlt_properties_pass_list( frame_properties, second_frame_properties,
- "motion_est.left_mb, motion_est.right_mb, \
- motion_est.top_mb, motion_est.bottom_mb, \
- motion_est.macroblock_width, motion_est.macroblock_height" );
-
- // Pass the pointer to the vectors without serializing
- mlt_properties_set_data( frame_properties, "motion_est.vectors",
- mlt_properties_get_data( second_frame_properties, "motion_est.vectors", NULL ),
- 0, NULL, NULL );
-
-
- // Start with a base image
- memcpy( output, first_image, size );
-
- if( mlt_properties_get_int( producer_properties, "method" ) == 1 ) {
-
- mlt_position first_position = mlt_frame_get_position( first_frame );
- double actual_position = mlt_producer_get_speed( producer ) * (double)mlt_frame_get_position( this );
- double scale = actual_position - first_position;
-
- motion_interpolate
- (
- first_image, second_image, output,
- mlt_properties_get_int( second_frame_properties, "motion_est.top_mb" ),
- mlt_properties_get_int( second_frame_properties, "motion_est.bottom_mb" ),
- mlt_properties_get_int( second_frame_properties, "motion_est.left_mb" ),
- mlt_properties_get_int( second_frame_properties, "motion_est.right_mb" ),
- mlt_properties_get_int( second_frame_properties, "motion_est.macroblock_width" ),
- mlt_properties_get_int( second_frame_properties, "motion_est.macroblock_height" ),
- *width, *height,
- xstride, ystride,
- scale,
- mlt_properties_get_data( second_frame_properties, "motion_est.vectors", NULL )
- );
-
- if( mlt_properties_get_int( producer_properties, "debug" ) == 1 ) {
- mlt_filter watermark = mlt_properties_get_data( producer_properties, "watermark", NULL );
-
- if( watermark == NULL ) {
- mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) );
- watermark = mlt_factory_filter( profile, "watermark", NULL );
- mlt_properties_set_data( producer_properties, "watermark", watermark, 0, (mlt_destructor)mlt_filter_close, NULL );
- mlt_producer_attach( producer, watermark );
- }
-
- mlt_properties wm_properties = MLT_FILTER_PROPERTIES( watermark );
-
- char disp[30];
- sprintf(disp, "+%10.2f.txt", actual_position);
- mlt_properties_set( wm_properties, "resource", disp );
-
- }
-
- }
-
- *image = output;
- mlt_properties_set_data( frame_properties, "image", output, size, NULL, NULL );
-
- // Make sure that no further scaling is done
- mlt_properties_set( frame_properties, "rescale.interps", "none" );
- mlt_properties_set( frame_properties, "scale", "off" );
-
- mlt_frame_close( first_frame );
- mlt_frame_close( second_frame );
-
- return 0;
-}
-
-static int slowmotion_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Construct a new frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-
- mlt_properties properties = MLT_PRODUCER_PROPERTIES(this);
-
-
- if( frame != NULL )
- {
-
- mlt_frame first_frame = mlt_properties_get_data( properties, "first_frame", NULL );
- mlt_frame second_frame = mlt_properties_get_data( properties, "second_frame", NULL );
-
- mlt_position first_position = (first_frame != NULL) ? mlt_frame_get_position( first_frame ) : -1;
- mlt_position second_position = (second_frame != NULL) ? mlt_frame_get_position( second_frame ) : -1;
-
- // Get the real producer
- mlt_producer real_producer = mlt_properties_get_data( properties, "producer", NULL );
-
- // Our "in" needs to be the same, keep it so
- mlt_properties_pass_list( MLT_PRODUCER_PROPERTIES( real_producer ), properties, "in" );
-
- // Calculate our positions
- double actual_position = mlt_producer_get_speed( this ) * (double)mlt_producer_position( this );
- mlt_position need_first = floor( actual_position );
- mlt_position need_second = need_first + 1;
-
- if( need_first != first_position )
- {
- mlt_frame_close( first_frame );
- first_position = -1;
- first_frame = NULL;
- }
-
- if( need_second != second_position)
- {
- mlt_frame_close( second_frame );
- second_position = -1;
- second_frame = NULL;
- }
-
- if( first_frame == NULL )
- {
- // Seek the producer to the correct place
- mlt_producer_seek( real_producer, need_first );
-
- // Get the frame
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( real_producer ), &first_frame, index );
- }
-
- if( second_frame == NULL )
- {
- // Seek the producer to the correct place
- mlt_producer_seek( real_producer, need_second );
-
- // Get the frame
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( real_producer ), &second_frame, index );
- }
-
- // Make sure things are in their place
- mlt_properties_set_data( properties, "first_frame", first_frame, 0, NULL, NULL );
- mlt_properties_set_data( properties, "second_frame", second_frame, 0, NULL, NULL );
-
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( *frame ), "test_image", 0 );
-
- // Stack the producer and producer's get image
- mlt_frame_push_service( *frame, first_frame );
- mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( first_frame ) );
-
- mlt_frame_push_service( *frame, second_frame );
- mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( second_frame ) );
-
- mlt_frame_push_service( *frame, this );
- mlt_frame_push_service( *frame, slowmotion_get_image );
-
- // Give the returned frame temporal identity
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
- }
-
- return 0;
-}
-
-mlt_producer producer_slowmotion_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_producer this = mlt_producer_new( );
-
- // Wrap fezzik
- mlt_producer real_producer = mlt_factory_producer( profile, "fezzik", arg );
-
- // We need to apply the motion estimation filter manually
- mlt_filter filter = mlt_factory_filter( profile, "motion_est", NULL );
-
- if ( this != NULL && real_producer != NULL && filter != NULL)
- {
- // attach the motion_est filter to the real producer
- mlt_producer_attach( real_producer, filter );
-
- // Get the properties of this producer
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Fezzik normalised it for us already
- mlt_properties_set_int( properties, "fezzik_normalised", 1);
-
- // Store the producer and fitler
- mlt_properties_set_data( properties, "producer", real_producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
- mlt_properties_set_data( properties, "motion_est", filter, 0, ( mlt_destructor )mlt_filter_close, NULL );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "macroblock_width", 16 );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "macroblock_height", 16 );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "denoise", 0 );
-
- // Grap some stuff from the real_producer
- mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( real_producer ),
- "in, out, length, resource" );
-
- // Since we control the seeking, prevent it from seeking on its own
- mlt_producer_set_speed( real_producer, 0 );
-
- //mlt_properties_set( properties, "method", "onefield" );
-
- // Override the get_frame method
- this->get_frame = slowmotion_get_frame;
-
- }
- else
- {
- if ( this )
- mlt_producer_close( this );
- if ( real_producer )
- mlt_producer_close( real_producer );
- if ( filter )
- mlt_filter_close( filter );
-
- this = NULL;
- }
- return this;
-}
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-
-#define SAD_SSE_INIT \
- asm volatile ( "pxor %%mm6,%%mm6\n\t" :: );\
-
-// Sum two 8x1 pixel blocks
-#define SAD_SSE_SUM_8(OFFSET) \
- "movq " #OFFSET "(%0),%%mm0 \n\t"\
- "movq " #OFFSET "(%1),%%mm1 \n\t"\
- "psadbw %%mm1,%%mm0 \n\t"\
- "paddw %%mm0,%%mm6 \n\t"\
-
-#define SAD_SSE_FINISH(RESULT) \
- asm volatile( "movd %%mm6,%0" : "=r" (RESULT) : );
-
-// Advance by ystride
-#define SAD_SSE_NEXTROW \
- "add %2,%0 \n\t"\
- "add %2,%1 \n\t"\
-
-// BROKEN!
-inline static int sad_sse_4x4( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_INIT
- #define ROW SAD_SSE_SUM_8(0) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-inline static int sad_sse_8x8( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_INIT
- #define ROW SAD_SSE_SUM_8(0) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-inline static int sad_sse_16x16( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_INIT
- #define ROW SAD_SSE_SUM_8(0) SAD_SSE_SUM_8(8) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-inline static int sad_sse_32x32( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_INIT
- #define ROW SAD_SSE_SUM_8(0) SAD_SSE_SUM_8(8) SAD_SSE_SUM_8(16) SAD_SSE_SUM_8(24)\
- SAD_SSE_NEXTROW
-
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-// BROKEN!
-inline static int sad_sse_4w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_SUM_8(0)
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-inline static int sad_sse_8w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_SUM_8(0)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-inline static int sad_sse_16w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_SUM_8(0)
- SAD_SSE_SUM_8(8)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-inline static int sad_sse_32w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_SUM_8(0)
- SAD_SSE_SUM_8(8)
- SAD_SSE_SUM_8(16)
- SAD_SSE_SUM_8(24)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-inline static int sad_sse_64w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_SUM_8(0)
- SAD_SSE_SUM_8(8)
- SAD_SSE_SUM_8(16)
- SAD_SSE_SUM_8(24)
- SAD_SSE_SUM_8(32)
- SAD_SSE_SUM_8(40)
- SAD_SSE_SUM_8(48)
- SAD_SSE_SUM_8(56)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-static __attribute__((used)) __attribute__((aligned(8))) uint64_t sad_sse_422_mask_chroma = 0x00ff00ff00ff00ffULL;
-
-#define SAD_SSE_422_LUMA_INIT \
- asm volatile ( "movq %0,%%mm7\n\t"\
- "pxor %%mm6,%%mm6\n\t" :: "m" (sad_sse_422_mask_chroma) );\
-
-// Sum two 4x1 pixel blocks
-#define SAD_SSE_422_LUMA_SUM_4(OFFSET) \
- "movq " #OFFSET "(%0),%%mm0 \n\t"\
- "movq " #OFFSET "(%1),%%mm1 \n\t"\
- "pand %%mm7,%%mm0 \n\t"\
- "pand %%mm7,%%mm1 \n\t"\
- "psadbw %%mm1,%%mm0 \n\t"\
- "paddw %%mm0,%%mm6 \n\t"\
-
-static int sad_sse_422_luma_4x4( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_422_LUMA_INIT
- #define ROW SAD_SSE_422_LUMA_SUM_4(0) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-static int sad_sse_422_luma_8x8( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_422_LUMA_INIT
- #define ROW SAD_SSE_422_LUMA_SUM_4(0) SAD_SSE_422_LUMA_SUM_4(8) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-static int sad_sse_422_luma_16x16( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_422_LUMA_INIT
- #define ROW SAD_SSE_422_LUMA_SUM_4(0) SAD_SSE_422_LUMA_SUM_4(8) SAD_SSE_422_LUMA_SUM_4(16) SAD_SSE_422_LUMA_SUM_4(24) SAD_SSE_NEXTROW
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-static int sad_sse_422_luma_32x32( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
- SAD_SSE_422_LUMA_INIT
- #define ROW SAD_SSE_422_LUMA_SUM_4(0) SAD_SSE_422_LUMA_SUM_4(8) SAD_SSE_422_LUMA_SUM_4(16) SAD_SSE_422_LUMA_SUM_4(24)\
- SAD_SSE_422_LUMA_SUM_4(32) SAD_SSE_422_LUMA_SUM_4(40) SAD_SSE_422_LUMA_SUM_4(48) SAD_SSE_422_LUMA_SUM_4(56)\
- SAD_SSE_NEXTROW
-
- asm volatile ( ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- ROW ROW ROW ROW ROW ROW ROW ROW
- :: "r" (block1), "r" (block2), "r" ((long int)(ystride)));
-
- SAD_SSE_FINISH(result)
- return result;
- #undef ROW
-
-}
-
-static int sad_sse_422_luma_4w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_422_LUMA_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_422_LUMA_SUM_4(0)
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-static int sad_sse_422_luma_8w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_422_LUMA_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_422_LUMA_SUM_4(0)
- SAD_SSE_422_LUMA_SUM_4(8)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-static int sad_sse_422_luma_16w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_422_LUMA_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_422_LUMA_SUM_4(0)
- SAD_SSE_422_LUMA_SUM_4(8)
- SAD_SSE_422_LUMA_SUM_4(16)
- SAD_SSE_422_LUMA_SUM_4(24)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-static int sad_sse_422_luma_32w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_422_LUMA_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_422_LUMA_SUM_4(0)
- SAD_SSE_422_LUMA_SUM_4(8)
- SAD_SSE_422_LUMA_SUM_4(16)
- SAD_SSE_422_LUMA_SUM_4(24)
- SAD_SSE_422_LUMA_SUM_4(32)
- SAD_SSE_422_LUMA_SUM_4(40)
- SAD_SSE_422_LUMA_SUM_4(48)
- SAD_SSE_422_LUMA_SUM_4(56)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-
-}
-
-static int sad_sse_422_luma_64w( uint8_t *block1, uint8_t *block2, int xstride, int ystride, int w, int h )
-{
- int result;
-
- SAD_SSE_422_LUMA_INIT
-
- while( h != 0 ) {
- asm volatile (
- SAD_SSE_422_LUMA_SUM_4(0)
- SAD_SSE_422_LUMA_SUM_4(8)
- SAD_SSE_422_LUMA_SUM_4(16)
- SAD_SSE_422_LUMA_SUM_4(24)
- SAD_SSE_422_LUMA_SUM_4(32)
- SAD_SSE_422_LUMA_SUM_4(40)
- SAD_SSE_422_LUMA_SUM_4(48)
- SAD_SSE_422_LUMA_SUM_4(56)
- SAD_SSE_422_LUMA_SUM_4(64)
- SAD_SSE_422_LUMA_SUM_4(72)
- SAD_SSE_422_LUMA_SUM_4(80)
- SAD_SSE_422_LUMA_SUM_4(88)
- SAD_SSE_422_LUMA_SUM_4(96)
- SAD_SSE_422_LUMA_SUM_4(104)
- SAD_SSE_422_LUMA_SUM_4(112)
- SAD_SSE_422_LUMA_SUM_4(120)
-
- :: "r" (block1), "r" (block2)
- );
-
- h--;
- block1 += ystride;
- block2 += ystride;
- }
- SAD_SSE_FINISH(result)
- return result;
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltnormalize$(LIBSUF)
-
-OBJS = factory.o \
- filter_volume.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_volume_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "volume", filter_volume_init );
-}
+++ /dev/null
-/*
- * filter_volume.c -- adjust audio volume
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <ctype.h>
-#include <string.h>
-
-#define MAX_CHANNELS 6
-#define EPSILON 0.00001
-
-/* The following normalise functions come from the normalize utility:
- Copyright (C) 1999--2002 Chris Vaill */
-
-#define samp_width 16
-
-#ifndef ROUND
-# define ROUND(x) floor((x) + 0.5)
-#endif
-
-#define DBFSTOAMP(x) pow(10,(x)/20.0)
-
-/** Return nonzero if the two strings are equal, ignoring case, up to
- the first n characters.
-*/
-int strncaseeq(const char *s1, const char *s2, size_t n)
-{
- for ( ; n > 0; n--)
- {
- if (tolower(*s1++) != tolower(*s2++))
- return 0;
- }
- return 1;
-}
-
-/** Limiter function.
-
- / tanh((x + lev) / (1-lev)) * (1-lev) - lev (for x < -lev)
- |
- x' = | x (for |x| <= lev)
- |
- \ tanh((x - lev) / (1-lev)) * (1-lev) + lev (for x > lev)
-
- With limiter level = 0, this is equivalent to a tanh() function;
- with limiter level = 1, this is equivalent to clipping.
-*/
-static inline double limiter( double x, double lmtr_lvl )
-{
- double xp = x;
-
- if (x < -lmtr_lvl)
- xp = tanh((x + lmtr_lvl) / (1-lmtr_lvl)) * (1-lmtr_lvl) - lmtr_lvl;
- else if (x > lmtr_lvl)
- xp = tanh((x - lmtr_lvl) / (1-lmtr_lvl)) * (1-lmtr_lvl) + lmtr_lvl;
-
-// if ( x != xp )
-// fprintf( stderr, "filter_volume: sample %f limited %f\n", x, xp );
-
- return xp;
-}
-
-
-/** Takes a full smoothing window, and returns the value of the center
- element, smoothed.
-
- Currently, just does a mean filter, but we could do a median or
- gaussian filter here instead.
-*/
-static inline double get_smoothed_data( double *buf, int count )
-{
- int i, j;
- double smoothed = 0;
-
- for ( i = 0, j = 0; i < count; i++ )
- {
- if ( buf[ i ] != -1.0 )
- {
- smoothed += buf[ i ];
- j++;
- }
- }
- smoothed /= j;
-// fprintf( stderr, "smoothed over %d values, result %f\n", j, smoothed );
-
- return smoothed;
-}
-
-/** Get the max power level (using RMS) and peak level of the audio segment.
- */
-double signal_max_power( int16_t *buffer, int channels, int samples, int16_t *peak )
-{
- // Determine numeric limits
- int bytes_per_samp = (samp_width - 1) / 8 + 1;
- int16_t max = (1 << (bytes_per_samp * 8 - 1)) - 1;
- int16_t min = -max - 1;
-
- double *sums = (double *) calloc( channels, sizeof(double) );
- int c, i;
- int16_t sample;
- double pow, maxpow = 0;
-
- /* initialize peaks to effectively -inf and +inf */
- int16_t max_sample = min;
- int16_t min_sample = max;
-
- for ( i = 0; i < samples; i++ )
- {
- for ( c = 0; c < channels; c++ )
- {
- sample = *buffer++;
- sums[ c ] += (double) sample * (double) sample;
-
- /* track peak */
- if ( sample > max_sample )
- max_sample = sample;
- else if ( sample < min_sample )
- min_sample = sample;
- }
- }
- for ( c = 0; c < channels; c++ )
- {
- pow = sums[ c ] / (double) samples;
- if ( pow > maxpow )
- maxpow = pow;
- }
-
- free( sums );
-
- /* scale the pow value to be in the range 0.0 -- 1.0 */
- maxpow /= ( (double) min * (double) min);
-
- if ( -min_sample > max_sample )
- *peak = min_sample / (double) min;
- else
- *peak = max_sample / (double) max;
-
- return sqrt( maxpow );
-}
-
-/* ------ End normalize functions --------------------------------------- */
-
-/** Get the audio.
-*/
-
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the a frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- double gain = mlt_properties_get_double( properties, "volume.gain" );
- double max_gain = mlt_properties_get_double( properties, "volume.max_gain" );
- double limiter_level = 0.5; /* -6 dBFS */
- int normalise = mlt_properties_get_int( properties, "volume.normalise" );
- double amplitude = mlt_properties_get_double( properties, "volume.amplitude" );
- int i, j;
- double sample;
- int16_t peak;
-
- // Get the filter from the frame
- mlt_filter this = mlt_properties_get_data( properties, "filter_volume", NULL );
-
- // Get the properties from the filter
- mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
-
- if ( mlt_properties_get( properties, "volume.limiter" ) != NULL )
- limiter_level = mlt_properties_get_double( properties, "volume.limiter" );
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
-// fprintf( stderr, "filter_volume: frequency %d\n", *frequency );
-
- // Determine numeric limits
- int bytes_per_samp = (samp_width - 1) / 8 + 1;
- int samplemax = (1 << (bytes_per_samp * 8 - 1)) - 1;
- int samplemin = -samplemax - 1;
-
- if ( normalise )
- {
- int window = mlt_properties_get_int( filter_props, "window" );
- double *smooth_buffer = mlt_properties_get_data( filter_props, "smooth_buffer", NULL );
-
- if ( window > 0 && smooth_buffer != NULL )
- {
- int smooth_index = mlt_properties_get_int( filter_props, "_smooth_index" );
-
- // Compute the signal power and put into smoothing buffer
- smooth_buffer[ smooth_index ] = signal_max_power( *buffer, *channels, *samples, &peak );
-// fprintf( stderr, "filter_volume: raw power %f ", smooth_buffer[ smooth_index ] );
- if ( smooth_buffer[ smooth_index ] > EPSILON )
- {
- mlt_properties_set_int( filter_props, "_smooth_index", ( smooth_index + 1 ) % window );
-
- // Smooth the data and compute the gain
-// fprintf( stderr, "smoothed %f over %d frames\n", get_smoothed_data( smooth_buffer, window ), window );
- gain *= amplitude / get_smoothed_data( smooth_buffer, window );
- }
- }
- else
- {
- gain *= amplitude / signal_max_power( *buffer, *channels, *samples, &peak );
- }
- }
-
-// if ( gain > 1.0 && normalise )
-// fprintf(stderr, "filter_volume: limiter level %f gain %f\n", limiter_level, gain );
-
- if ( max_gain > 0 && gain > max_gain )
- gain = max_gain;
-
- // Initialise filter's previous gain value to prevent an inadvertant jump from 0
- mlt_position last_position = mlt_properties_get_position( filter_props, "_last_position" );
- mlt_position current_position = mlt_frame_get_position( frame );
- if ( mlt_properties_get( filter_props, "_previous_gain" ) == NULL
- || current_position != last_position + 1 )
- mlt_properties_set_double( filter_props, "_previous_gain", gain );
-
- // Start the gain out at the previous
- double previous_gain = mlt_properties_get_double( filter_props, "_previous_gain" );
-
- // Determine ramp increment
- double gain_step = ( gain - previous_gain ) / *samples;
-// fprintf( stderr, "filter_volume: previous gain %f current gain %f step %f\n", previous_gain, gain, gain_step );
-
- // Save the current gain for the next iteration
- mlt_properties_set_double( filter_props, "_previous_gain", gain );
- mlt_properties_set_position( filter_props, "_last_position", current_position );
-
- // Ramp from the previous gain to the current
- gain = previous_gain;
-
- int16_t *p = *buffer;
-
- // Apply the gain
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- sample = *p * gain;
- *p = ROUND( sample );
-
- if ( gain > 1.0 )
- {
- /* use limiter function instead of clipping */
- if ( normalise )
- *p = ROUND( samplemax * limiter( sample / (double) samplemax, limiter_level ) );
-
- /* perform clipping */
- else if ( sample > samplemax )
- *p = samplemax;
- else if ( sample < samplemin )
- *p = samplemin;
- }
- p++;
- }
- gain += gain_step;
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
-
- // Parse the gain property
- if ( mlt_properties_get( properties, "gain" ) == NULL )
- {
- double gain = 1.0; // no adjustment
-
- if ( mlt_properties_get( filter_props, "gain" ) != NULL )
- {
- char *p = mlt_properties_get( filter_props, "gain" );
-
- if ( strncaseeq( p, "normalise", 9 ) )
- mlt_properties_set( filter_props, "normalise", "" );
- else
- {
- if ( strcmp( p, "" ) != 0 )
- gain = fabs( strtod( p, &p) );
-
- while ( isspace( *p ) )
- p++;
-
- /* check if "dB" is given after number */
- if ( strncaseeq( p, "db", 2 ) )
- gain = DBFSTOAMP( gain );
-
- // If there is an end adjust gain to the range
- if ( mlt_properties_get( filter_props, "end" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
- mlt_position time = mlt_frame_get_position( frame );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
-
- double end = -1;
- char *p = mlt_properties_get( filter_props, "end" );
- if ( strcmp( p, "" ) != 0 )
- end = fabs( strtod( p, &p) );
-
- while ( isspace( *p ) )
- p++;
-
- /* check if "dB" is given after number */
- if ( strncaseeq( p, "db", 2 ) )
- end = DBFSTOAMP( gain );
-
- if ( end != -1 )
- gain += ( end - gain ) * position;
- }
- }
- }
- mlt_properties_set_double( properties, "volume.gain", gain );
- }
-
- // Parse the maximum gain property
- if ( mlt_properties_get( filter_props, "max_gain" ) != NULL )
- {
- char *p = mlt_properties_get( filter_props, "max_gain" );
- double gain = fabs( strtod( p, &p) ); // 0 = no max
-
- while ( isspace( *p ) )
- p++;
-
- /* check if "dB" is given after number */
- if ( strncaseeq( p, "db", 2 ) )
- gain = DBFSTOAMP( gain );
-
- mlt_properties_set_double( properties, "volume.max_gain", gain );
- }
-
- // Parse the limiter property
- if ( mlt_properties_get( filter_props, "limiter" ) != NULL )
- {
- char *p = mlt_properties_get( filter_props, "limiter" );
- double level = 0.5; /* -6dBFS */
- if ( strcmp( p, "" ) != 0 )
- level = strtod( p, &p);
-
- while ( isspace( *p ) )
- p++;
-
- /* check if "dB" is given after number */
- if ( strncaseeq( p, "db", 2 ) )
- {
- if ( level > 0 )
- level = -level;
- level = DBFSTOAMP( level );
- }
- else
- {
- if ( level < 0 )
- level = -level;
- }
- mlt_properties_set_double( properties, "volume.limiter", level );
- }
-
- // Parse the normalise property
- if ( mlt_properties_get( filter_props, "normalise" ) != NULL )
- {
- char *p = mlt_properties_get( filter_props, "normalise" );
- double amplitude = 0.2511886431509580; /* -12dBFS */
- if ( strcmp( p, "" ) != 0 )
- amplitude = strtod( p, &p);
-
- while ( isspace( *p ) )
- p++;
-
- /* check if "dB" is given after number */
- if ( strncaseeq( p, "db", 2 ) )
- {
- if ( amplitude > 0 )
- amplitude = -amplitude;
- amplitude = DBFSTOAMP( amplitude );
- }
- else
- {
- if ( amplitude < 0 )
- amplitude = -amplitude;
- if ( amplitude > 1.0 )
- amplitude = 1.0;
- }
-
- // If there is an end adjust gain to the range
- if ( mlt_properties_get( filter_props, "end" ) != NULL )
- {
- // Determine the time position of this frame in the transition duration
- mlt_position in = mlt_filter_get_in( this );
- mlt_position out = mlt_filter_get_out( this );
- mlt_position time = mlt_frame_get_position( frame );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- amplitude *= position;
- }
- mlt_properties_set_int( properties, "volume.normalise", 1 );
- mlt_properties_set_double( properties, "volume.amplitude", amplitude );
- }
-
- // Parse the window property and allocate smoothing buffer if needed
- int window = mlt_properties_get_int( filter_props, "window" );
- if ( mlt_properties_get( filter_props, "smooth_buffer" ) == NULL && window > 1 )
- {
- // Create a smoothing buffer for the calculated "max power" of frame of audio used in normalisation
- double *smooth_buffer = (double*) calloc( window, sizeof( double ) );
- int i;
- for ( i = 0; i < window; i++ )
- smooth_buffer[ i ] = -1.0;
- mlt_properties_set_data( filter_props, "smooth_buffer", smooth_buffer, 0, free, NULL );
- }
-
- // Put a filter reference onto the frame
- mlt_properties_set_data( properties, "filter_volume", this, 0, NULL, NULL );
-
- // Override the get_audio method
- mlt_frame_push_audio( frame, filter_get_audio );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_volume_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
- if ( this != NULL && mlt_filter_init( this, NULL ) == 0 )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set( properties, "gain", arg );
-
- mlt_properties_set_int( properties, "window", 75 );
- mlt_properties_set( properties, "max_gain", "20dB" );
- }
- return this;
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltoldfilm$(LIBSUF)
-
-OBJS = factory.o \
- filter_oldfilm.o \
- filter_dust.o \
- filter_lines.o \
- filter_grain.o \
- filter_tcolor.o \
- filter_vignette.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += -lm
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
- install -d $(DESTDIR)$(prefix)/share/mlt/oldfilm
- install -m 644 *.svg "$(DESTDIR)$(prefix)/share/mlt/oldfilm"
- install -m 644 *.yml "$(DESTDIR)$(prefix)/share/mlt/oldfilm"
-
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="240"
- height="217.14285"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dust1.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="291.42857"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="436"
- inkscape:window-y="136" />
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient3134">
- <stop
- offset="0"
- style="stop-color:#000000;stop-opacity:1;"
- id="stop3136" />
- <stop
- offset="1"
- style="stop-color:#001b00;stop-opacity:0;"
- id="stop3138" />
- </linearGradient>
- <radialGradient
- r="120"
- id="radialGradient3140"
- fx="314.28571"
- fy="352.36218"
- gradientUnits="userSpaceOnUse"
- inkscape:collect="always"
- cy="352.36218"
- cx="314.28571"
- xlink:href="#linearGradient3134"
- gradientTransform="matrix(1,0,0,3.824003,0,-899.71827)" />
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- transform="translate(-194.28571,-243.79076)"
- inkscape:label="Ebene 1"
- id="layer1"
- inkscape:groupmode="layer">
- <path
- id="path2171"
- d="M 434.28571,447.71572 L 430.39845,446.98174 L 426.51105,447.70281 L 422.63086,444.95151 L 418.7369,447.33 L 415.17888,439.03832 L 412.09038,427.88049 L 408.04927,427.373 L 404.01654,426.16139 L 399.94798,424.73438 L 396.42874,433.48045 L 392.63006,438.51018 L 388.67834,436.48311 L 385.04569,429.98727 L 381.14982,427.38011 L 377.22038,430.04453 L 373.32102,426.68233 L 369.57046,421.84943 L 366.19199,413.43864 L 362.28568,414.01743 L 358.41557,411.70186 L 354.37205,414.23864 L 350.36416,417.63832 L 346.46571,411.53673 L 343.35113,399.8993 L 339.53706,393.48698 L 335.97202,384.88788 L 331.83892,385.51799 L 327.91078,390.9871 L 323.71372,391.53811 L 319.89063,384.19765 L 316.99236,371.9895 L 314.28571,359.01937 L 310.03453,356.25903 L 306.24091,347.69311 L 302.06907,343.31261 L 297.78709,344.91141 L 293.67116,336.67107 L 291.59835,319.53116 L 287.10897,318.6664 L 283.4444,307.67153 L 280.04266,294.45327 L 276.07896,284.41415 L 271.53901,279.72473 L 266.90066,282.14486 L 262.2405,285.1173 L 257.57444,282.31501 L 253.08029,290.12947 L 250.29693,306.96613 L 245.94295,304.25049 L 241.56118,305.99325 L 236.95654,305.68247 L 233.22692,317.10051 L 228.78363,307.65672 L 224.00778,313.52323 L 220.67578,327.30269 L 216.67116,337.38838 L 216.28682,356.83475 L 214.77646,375.27519 L 210.68738,385.66713 L 208.55789,403.71361 L 204.2669,410.01158 L 200.22848,418.80047 L 195.90418,428.29105 L 194.28571,447.71572 L 198.62042,451.1118 L 202.83258,456.61128 L 207.52564,457.54492 L 211.21379,445.24351 L 215.01113,434.95466 L 219.46816,432.02441 L 222.58281,418.55997 L 224.71894,402.03506 L 228.28989,393.27594 L 232.3716,390.64936 L 235.43763,377.86937 L 239.72488,376.16203 L 243.34806,366.44008 L 247.61567,368.35802 L 251.57005,364.6111 L 255.55167,361.42094 L 259.82848,362.36269 L 263.77023,355.28606 L 267.94113,354.12226 L 272.11574,355.01674 L 274.69118,340.04655 L 278.35161,329.88559 L 282.69754,328.43278 L 286.73607,321.49359 L 290.72647,316.70065 L 294.42096,308.72595 L 298.44502,301.8398 L 300.7415,286.26813 L 303.33482,272.24893 L 307.18187,265.01712 L 311.16529,259.69604 L 314.28571,247.95603 L 317.70857,259.01241 L 321.90346,263.15776 L 324.16016,278.97807 L 328.02132,287.63463 L 330.16565,304.13419 L 334.23472,311.78945 L 337.48222,325.11445 L 342.00603,325.72722 L 343.08521,344.83013 L 346.64696,357.4439 L 351.04337,360.80678 L 354.97171,369.80216 L 358.55898,378.84144 L 362.09284,388.24908 L 364.20762,404.75745 L 368.33325,411.71191 L 372.37551,402.09016 L 376.70855,395.08488 L 381.38937,392.28894 L 385.94136,397.67996 L 390.80528,391.4668 L 395.50331,399.6484 L 399.72846,389.6019 L 402.99765,374.47207 L 407.33054,381.30715 L 410.66368,394.85799 L 415.33507,395.57009 L 419.35168,405.67599 L 421.4868,423.88654 L 425.40104,435.69199 L 430.12905,437.93294 L 434.28571,447.71572"
- style="opacity:1;fill:url(#radialGradient3140);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:9.80000019;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="194.28572"
- height="257.14285"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dust2.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <sodipodi:namedview
- id="base"
- pagecolor="#ff4f64"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.43137255"
- inkscape:pageshadow="2"
- inkscape:zoom="5.248863"
- inkscape:cx="100.71553"
- inkscape:cy="161.55164"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1043"
- inkscape:window-height="804"
- inkscape:window-x="387"
- inkscape:window-y="16" />
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient3147">
- <stop
- offset="0"
- style="stop-color:#fffdff;stop-opacity:1;"
- id="stop3149" />
- <stop
- offset="1"
- style="stop-color:#ffffff;stop-opacity:0.30222222;"
- id="stop3151" />
- </linearGradient>
- <radialGradient
- r="97.14286"
- id="radialGradient3155"
- fx="274.28571"
- fy="335.21933"
- gradientUnits="userSpaceOnUse"
- inkscape:collect="always"
- cy="335.21933"
- cx="274.28571"
- xlink:href="#linearGradient3147"
- gradientTransform="matrix(1,0,0,1.3235293,0,-108.45329)" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3147"
- id="radialGradient4250"
- cx="277.85837"
- cy="302.23911"
- fx="277.85837"
- fy="302.23911"
- r="91.162598"
- gradientTransform="matrix(1,0,0,0.4733379,0,159.17788)"
- gradientUnits="userSpaceOnUse"
- spreadMethod="reflect" />
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- transform="translate(-177.14285,-206.6479)"
- inkscape:label="Ebene 1"
- id="layer1"
- inkscape:groupmode="layer">
- <path
- style="opacity:1;stroke-opacity:1;fill-rule:nonzero;fill-opacity:1;stroke:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:9.80000019;fill:url(#radialGradient3155)"
- id="path2261"
- d="M-463.907729645 59.4947232865L-465.88997919 53.0618899264L-467.549378959 46.5383133996L-469.743557035 39.9685086158L-468.666248439 33.1262751708L-466.83275019 26.2872473927L-464.142489942 19.7377041588L-464.524207184 12.4160838201L-468.615066603 6.33194857812L-468.910847311 -0.683251608856L-470.528779939 -7.51573387404L-475.092658479 -12.8099924273L-479.739067212 -18.0319697201L-485.73817452 -21.945195162L-491.476673252 -26.2314819186L-495.419964008 -32.6422392782L-494.847794523 -40.1469027611L-492.480636045 -47.3546670613L-491.9760398 -54.9243888592L-487.59770564 -61.5755338577L-480.048594523 -64.1090020642L-480.681659877 -71.3075932316L-483.088938826 -78.121218889L-482.704413791 -85.3251250446L-480.732250787 -92.2644835516L-480.193664405 -99.1533349308L-480.563047873 -106.053328008L-481.025575984 -113.263921496L-485.519721132 -118.921593287L-487.829778625 -125.3369764L-488.982048988 -132.057525418L-490.622429463 -138.759025882L-494.477291489 -144.481000656L-490.017834216 -150.068529921L-486.181732441 -156.10107214L-488.547366928 -163.013327043L-487.825680898 -170.283448339L-483.680993685 -176.261759704L-477.054071133 -179.262182402L-473.931082668 -185.714303117L-473.702723282 -192.878852696L-475.469781914 -199.784629318L-477.829700823 -206.510923223L-477.23499722 -214.07026968L-471.904284019 -219.46293952L-465.900025338 -223.606434671L-462.736688564 -230.180092316L-460.270934889 -237.140901407L-462.186942229 -244.272641747L-466.091911117 -251.164436042L-473.420709869 -254.170150512L-476.639538032 -261.370949763L-474.91411937 -269.067396674L-476.902252287 -276.267891846L-473.768056392 -283.048497964L-471.927801573 -289.824732823L-469.462772581 -296.399497362L-473.63808065 -302.194623254L-473.385435919 -309.332749914L-470.992019665 -316.077927348L-473.315226176 -322.847607657L-469.159901772 -328.49003245L-468.226046876 -335.434929388L-466.477069188 -342.175668962L-467.83251643 -349.006427025L-468.619692204 -342.861624953L-469.232433338 -336.696984939L-469.270127678 -330.399469569L-471.539300702 -324.52486537L-469.175868919 -318.623388776L-469.451228748 -312.272214651L-469.494680958 -305.649307059L-465.230740834 -300.581407327L-466.848690529 -294.42110035L-465.396556407 -288.219612646L-464.671633164 -282.020530147L-462.277656517 -276.256589365L-457.32019267 -272.060157806L-455.620890942 -265.791277581L-452.61976616 -260.162976606L-452.506823585 -253.785534658L-448.590863545 -248.313985908L-442.40244285 -245.67276686L-436.775329639 -241.776492435L-434.694933516 -235.255962589L-430.649188281 -230.08736824L-426.360593181 -225.118427295L-426.522251677 -218.24464111L-422.736390033 -212.505100921L-421.184044907 -205.52226576L-416.037969794 -200.553596602L-414.115707783 -193.510946069L-417.221248935 -186.904159263L-417.863146941 -180.340520036L-419.806708769 -174.038460026L-423.287581644 -168.296267035L-424.069044195 -161.627041247L-428.887255151 -156.278326662L-434.045287782 -151.256513851L-433.326629484 -143.830959692L-436.493579921 -137.076276188L-437.682349818 -130.098447357L-437.141816316 -123.040749956L-435.698813185 -116.074162685L-432.15564799 -109.90475618L-436.107369158 -104.582431036L-441.225344756 -100.369407072L-445.873539454 -95.7110641291L-450.663205747 -91.1983077948L-456.689257495 -87.7139504068L-460.611723363 -81.9634454213L-460.944089225 -74.9120245456L-464.955139375 -69.103024621L-465.072247513 -62.0229138732L-462.619857147 -55.3800632798L-466.83973372 -49.3915250869L-466.686726973 -42.06714546L-471.932610662 -36.8701051203L-472.475682082 -29.5057587537L-475.351295643 -22.6593122799L-472.818255363 -15.6788617489L-468.420393858 -10.3894993088L-466.007500221 -3.94772275733L-462.565501903 2.02266925624L-457.257152241 6.41747950113L-455.108038321 13.1308446653L-449.705425696 17.6585084437L-446.615339789 23.6840617883L-443.691410505 29.7919715425L-443.834112479 27.6258854399L-444.622542121 25.6033445736L-445.953081595 23.7975458469L-446.0491224 21.5565593461L-446.983100742 19.5267545249L-446.689395405 17.3117691233L-446.889202368 15.1341090161L-447.892328034 13.190950437L-447.54431353 10.9365319366L-447.355692539 8.66322179673L-448.319103587 6.42725471482L-447.57495036 4.10907749707L-445.818960067 2.31007059794L-445.593591355 -0.193753811675L-443.169512041 -0.794859146968L-441.594740826 -2.7333079502L-441.751576788 -5.1941918928L-440.347046752 -7.22097325163L-440.726728996 -9.55444992462L-441.874587681 -11.6212572274L-441.279520581 -13.9047599671L-439.438387611 -15.380808409L-437.432020582 -16.5135110874L-436.161599633 -18.4356335139L-435.92862693 -20.6173392212L-435.42668271 -22.753262458L-435.289712269 -25.0248976546L-433.983265008 -26.8883039232L-433.401121503 -29.2199353346L-434.254295445 -31.466597375L-435.111107727 -33.726545982L-437.151631256 -35.0218292415L-436.066282761 -36.9725956002L-434.851799059 -38.8456946579L-434.261655739 -41.0107210837L-433.223767866 -43.0002932298L-431.126756235 -44.2246334879L-429.933945352 -46.3397384612L-427.520250123 -46.0469733464L-425.297751369 -47.0329425968L-424.522781181 -49.3719034696L-422.41135462 -50.6420194625L-420.152486655 -51.1432050003L-417.853768022 -51.4069550266L-416.343748636 -52.9997806889L-414.732249004 -54.4898548719L-413.142907066 -56.1717566343L-412.890969446 -58.4720454787L-411.787687693 -60.5370227362L-412.242940004 -62.8335651446L-410.712191286 -64.4296673016L-409.449633098 -66.2453436368L-408.595453403 -68.2653602801L-408.543146068 -70.4579282112L-407.465522226 -72.3239843987L-406.320615683 -74.1495330409L-407.826904864 -76.02385871L-407.945837444 -78.425495413L-408.36933663 -80.7099492081L-407.976077791 -82.9998025194L-407.655011284 -85.3917960569L-405.808786488 -86.9461997334L-404.873082686 -88.9962164888L-403.756626889 -90.9536731947L-397.015159322 -91.0875840666L-390.409053459 -92.4383921199L-383.620259345 -93.8219196157L-376.994491283 -91.7968093889L-370.108965629 -91.7478139483L-363.235893609 -92.1646413613L-356.987905447 -89.2793105236L-350.793396387 -86.2808863355L-343.842106007 -85.5492613123L-337.846546474 -81.9563545468L-332.833046291 -77.1444674512L-326.396322465 -74.5256837838L-320.822682615 -69.3981094471L-313.365931136 -68.0735955266L-311.047140319 -61.1767629572L-308.174302228 -54.4917130963L-306.055039952 -48.0460317659L-305.089013164 -41.3300156367L-299.578942435 -37.2714270775L-295.592428915 -31.7089878212L-289.895297312 -27.9775705903L-285.639189489 -22.6609617795L-281.415140784 -16.9781719087L-281.393337828 -9.89747894781L-279.283967767 -3.30117966192L-275.372610809 2.41387878645L-271.347798333 8.20347366812L-265.11734486 11.5049845176L-259.515641334 15.5179817881L-253.976959999 19.6175230504L-247.375812407 21.7977822101L-240.433782143 22.167775948L-239.544101582 29.4445099406L-242.97202649 35.924611786L-242.064651312 42.8609559472L-240.932582714 49.7641885758L-235.875328983 55.3471574642L-235.685237064 62.8777100318L-232.12551614 69.3802882778L-225.456960119 72.6184200711L-219.734331322 76.9985748797L-212.546927371 77.5234186006L-206.655383583 81.7414625545L-204.281614953 88.5874398762L-202.30547674 95.1905802403L-198.477159637 100.922122185L-193.660055705 105.827832694L-187.733919809 109.313718409L-182.636160048 115.376982806L-182.453614469 123.29638978L-180.99130228 130.963204121L-184.00757162 138.161851102L-187.837601453 144.43631717L-193.19247332 149.472526087L-194.774067819 157.084692164L-200.952125162 161.804662608L-194.878176039 165.975823665L-190.712234237 172.053353709L-183.838431296 175.255536902L-179.976744528 181.781678135L-179.70717508 189.033679487L-179.707524286 196.290689282L-175.832563251 203.061642595L-177.631031812 210.652864013L-180.358123591 208.53676233L-183.803320815 208.750144593L-186.87372201 209.809469837L-189.649358458 211.496294007L-192.583175366 210.729191221L-195.593005129 210.359524987L-198.618901455 210.227625364L-201.64437624 210.368864214L-204.734675973 210.300945345L-207.825490993 210.263157502L-210.749350006 209.229731918L-213.801342219 208.679946962L-216.729400603 210.041902322L-219.92615288 209.584493111L-222.350567264 211.767511497L-225.599554575 212.063207005L-228.739810938 212.892946167L-231.950331853 213.385117439L-235.155858612 213.991415061L-238.157642158 215.269027736L-241.503032849 215.34158236L-244.554121011 213.96762309L-247.864645937 212.856056485L-251.076496236 214.226885889L-253.645603234 212.177454149L-256.796092225 211.242093076L-258.410648036 208.246765103L-261.505692815 206.832736128L-264.712676556 205.973103819L-267.110552773 203.676606036L-270.223625316 202.321910284L-271.875847769 199.356007014L-274.938364664 198.530965573L-278.029093095 197.818855413L-281.213587679 197.411447687L-284.368701276 198.004950004L-287.543728528 199.639966139L-291.00723176 198.76920717L-293.203261068 196.025206168L-296.595064481 195.104469596L-299.708539427 196.698131903L-302.684890145 198.535200815L-306.239611818 198.985809476L-309.642139815 197.862467333L-313.050764021 197.342308962L-315.829040105 195.300137149L-318.383425209 193.087822822L-321.436829683 191.640086984L-322.993255201 194.838351242L-326.301468505 196.144903726L-329.129589518 197.919157743L-331.460373071 200.309491152L-334.552324992 201.935547844L-337.013053599 204.415273993L-337.070893795 208.087065083L-339.466049913 210.870699841L-343.190919309 211.240383306L-346.325092863 213.28691061L-349.411626896 215.352829212L-351.416666196 218.479253594L-355.059179679 219.163910493L-358.486906456 217.754176941L-361.971268653 217.024557135L-365.344666436 215.887318206L-367.497455987 215.118464771L-369.140452102 213.52906167L-370.956846922 212.219664462L-372.586680972 210.684264789L-373.582755094 208.537109875L-374.756630394 206.481762054L-376.667672899 204.952112289L-379.087039004 204.579849594L-380.412740154 202.586469081L-381.848765139 200.671036583L-382.44933235 198.225768735L-384.379529127 196.608871638L-386.85074277 197.161228453L-389.373247355 196.939946876L-392.023342351 196.513171599L-393.691505691 194.41022802L-395.536117279 192.697574772L-396.472760733 190.361237447L-398.214891073 188.592344191L-400.393978306 187.402562571L-402.555552842 186.204999056L-404.999459756 185.839100375L-406.987317202 184.395269713L-409.301670059 183.57065158L-409.658809292 181.097743833L-408.945213044 178.703249825L-408.438424655 176.151456706L-409.713383331 173.883646537L-411.613665903 172.100126219L-411.782373285 169.499442387L-412.68444869 167.244265553L-413.866678827 165.122498721L-412.558795255 162.88642467L-412.062380327 160.343953664L-411.959640475 157.724783003L-413.016169027 155.32595874L-413.672415771 152.80133923L-414.541212917 150.34175492L-416.771654718 148.987123198L-418.851714884 147.411290898L-418.330558988 145.106933813L-417.657132366 142.84238935L-416.234235109 140.95782181L-414.855702462 139.040563572L-414.478702599 136.694236778L-414.767053241 134.335374292L-413.836449574 132.1714512L-413.110224194 129.93065156L-413.149501247 127.467441358L-414.523918352 125.422954917L-415.746304722 123.390388409L-416.582215979 121.170747128L-416.894014401 118.684463613L-415.645874389 116.511684176L-414.388953725 114.482804246L-413.533864173 112.254570599L-413.478493878 109.789706516L-414.221650015 107.438889685L-416.437888322 106.253459483L-417.794681612 104.137787257L-418.015690606 101.805456524L-418.492221524 99.5116540235L-417.070120913 97.4638685624L-417.317748055 94.9830468759L-417.767223284 95.8396999193L-417.922143721 96.7946250872L-417.658938212 97.787485909L-418.147471428 98.6910261949L-417.301037261 99.2909032575L-416.814989134 100.207451406L-416.882609931 101.219396491L-416.751915844 102.225142226L-415.921762019 102.759076832L-414.960332592 102.982448702L-414.262196509 103.724666009L-413.265607358 103.937011446L-412.735704401 104.761955569L-412.292972883 105.636780553L-411.777471754 106.51271637L-411.788356472 107.529026605L-411.311241608 108.278620776L-410.924989835 109.078832987L-411.057030184 109.981927129L-410.761080066 110.845308394L-410.507457033 111.701840902L-410.675743374 112.579139191L-410.788036755 113.456303577L-410.562441643 114.311367323L-410.6028685 115.207449498L-410.36848858 116.073280688L-410.650092067 116.913685341L-410.949756917 117.747820511L-410.480326073 118.540437468L-410.299521252 119.443718473L-410.516663021 120.325616809L-410.759483342 121.200793086L-410.231165342 122.003722639L-409.472202857 122.593461328L-408.464177327 122.706677108L-407.785610554 123.460653512L-407.23275184 124.271892541L-406.882346412 125.188940825L-405.97604137 125.564903249L-405.175863361 126.132751581L-404.29777269 126.686382126L-403.815317332 127.605504987L-403.158914412 128.363608374L-402.539129541 129.151930805L-403.043065313 130.098344903L-403.34817618 131.126235104L-402.817832682 132.076293196L-402.694794327 133.157374214L-401.748601706 133.177068849L-400.893856682 133.583368366L-399.97744352 133.71210377L-399.06507283 133.86691208L-398.033020291 133.775508341L-397.116144292 134.258028278L-396.723815166 135.199554114L-395.958683661 135.8740664L-395.052053046 135.478083389L-394.075965566 135.63943656L-393.291650272 136.192559725L-392.377602856 136.485156783L-391.461505526 136.325103352L-390.53170496 136.343056797L-389.551444331 136.319763258L-388.769911502 136.911928713" />
- <path
- id="path3275"
- d="M 193.52657,268.85494 L 196.21468,268.3195 L 198.85198,267.71783 L 201.69355,267.96748 L 204.57393,267.98941 L 207.40716,267.76168 L 210.17135,268.16093 L 213.07609,268.11678 L 215.62066,268.85718 L 217.60818,269.97429 L 220.26216,270.59636 L 223.17753,270.55063 L 225.8528,271.16357 L 228.65319,270.66657 L 231.57332,270.90391 L 234.25862,271.44468 L 236.83056,272.12166 L 239.29588,271.28646 L 241.82144,270.50296 L 243.90868,269.31191 L 244.30342,267.70325 L 247.09102,267.17023 L 248.7518,265.87439 L 251.43723,265.13153 L 252.43375,263.62071 L 255.22434,263.12308 L 257.77501,262.34573 L 260.70964,262.36233 L 263.62717,262.53003 L 266.0192,261.69988 L 268.25858,260.75864 L 271.10496,260.41658 L 273.46908,259.51306 L 276.04712,259.20928 L 278.67872,259.0884 L 281.15376,259.61513 L 283.81642,259.71086 L 286.3649,260.14722 L 288.98848,259.86028 L 291.57093,259.47108 L 294.168,259.83222 L 296.48345,260.61287 L 298.20355,261.74339 L 300.9083,261.90419 L 303.51903,262.31034 L 306.13221,262.4557 L 308.6521,262.84865 L 311.11867,263.46936 L 313.82479,263.26833 L 314.59115,264.80821 L 316.49863,266.04191 L 319.07256,266.86811 L 322.05839,267.08082 L 323.95246,268.18416 L 326.42091,268.90524 L 329.27457,269.02076 L 331.72002,269.80523 L 334.45898,269.16804 L 337.30899,269.65104 L 339.90969,269.10352 L 342.42858,268.45827 L 345.48472,268.41841 L 347.81558,269.46197 L 350.48053,268.81708 L 353.4116,268.85494 L 355.28034,269.82676 L 356.03733,271.15224 L 355.81457,272.53663 L 356.94306,273.79198 L 359.16015,274.45565 L 360.96755,275.404 L 361.74233,276.75822 L 363.96322,277.55081 L 363.12037,278.88976 L 363.66231,280.27134 L 365.86107,281.13189 L 366.55513,282.52905 L 367.78192,283.75554 L 367.19975,285.10788 L 367.41773,286.46173 L 369.02098,287.52509 L 366.49292,288.31114 L 364.91092,289.61502 L 364.15483,291.08773 L 364.32723,292.61079 L 361.61539,292.99142 L 359.73825,294.09185 L 357.81457,295.08739 L 355.67752,295.95338 L 355.93972,297.50097 L 354.48713,298.85259 L 352.63219,300.04231 L 352.2208,301.56742 L 352.41957,303.13644 L 354.49724,304.26399 L 355.1223,305.74634 L 356.96311,306.91381 L 355.32924,307.91299 L 354.17254,309.08302 L 354.72621,310.42905 L 353.68427,311.69196 L 351.76986,312.49474 L 350.36118,313.54935 L 348.30903,314.38214 L 347.82055,315.72349 L 347.64283,317.03404 L 348.37142,318.29044 L 349.41034,319.52701 L 348.93789,320.85644 L 349.09324,322.24229 L 347.42678,323.3167 L 346.185,324.44236 L 345.48444,325.69123 L 345.64185,327.02915 L 346.87301,328.20178 L 347.3392,329.48617 L 347.86922,330.76366 L 345.62155,331.63092 L 344.73022,333.02273 L 344.17793,334.4614 L 345.283,335.80854 L 346.76921,336.9064 L 347.46325,338.20485 L 349.18693,339.19105 L 351.35007,339.89618 L 351.83986,341.17231 L 352.62311,342.40704 L 353.576,343.64207 L 353.4116,344.97267 L 350.54841,345.19741 L 347.67676,345.38983 L 345.28496,344.43492 L 342.30604,344.24988 L 339.35177,343.8842 L 336.40961,344.27613 L 334.63769,342.92192 L 331.65947,342.43295 L 329.92211,341.10893 L 326.93443,340.77916 L 325.4112,339.51604 L 323.69005,338.32575 L 322.52656,336.94173 L 320.49844,335.87052 L 318.86475,334.54313 L 316.0004,334.07271 L 313.28916,333.96062 L 310.5994,334.17243 L 308.31306,335.09828 L 305.43534,335.01307 L 302.70104,335.2819 L 300.35267,336.06817 L 297.61014,336.4021 L 294.89152,336.01756 L 291.93647,335.6717 L 289.76752,334.55784 L 286.8656,334.36764 L 284.07988,333.89847 L 281.0364,333.90561 L 278.03684,334.17754 L 275.16577,334.87599 L 273.46908,336.28342 L 270.97426,336.85112 L 268.36226,337.24573 L 266.66031,338.37655 L 264.44253,339.2227 L 261.73548,339.2416 L 259.25886,339.81847 L 256.45382,339.70266 L 254.13443,340.54295 L 251.34418,340.77439 L 248.76305,341.37952 L 246.63158,340.29445 L 243.68547,340.13281 L 241.07739,339.88262 L 238.44785,340.05959 L 235.83806,339.92643 L 233.21635,339.90729 L 230.257,339.67357 L 227.26481,339.65804 L 224.99804,338.63323 L 222.76561,337.58766 L 219.94304,337.85152 L 217.39346,338.54277 L 215.01369,339.49662 L 212.02504,339.5037 L 209.41943,339.87094 L 206.98346,340.4816 L 205.30771,341.64393 L 202.7935,342.25485 L 200.38026,342.84533 L 197.9433,343.40808 L 195.53661,344.03456 L 193.52657,344.97267 L 191.81721,343.98059 L 191.24652,342.67414 L 190.65904,341.37939 L 189.05398,340.35205 L 188.1617,339.06122 L 188.78644,337.72736 L 188.02932,336.47196 L 186.95015,335.28392 L 187.80815,333.83816 L 186.69578,332.44149 L 187.83049,331.07889 L 190.21868,330.28668 L 190.51922,328.89958 L 189.19138,327.69192 L 188.9004,326.37296 L 188.91654,325.04513 L 191.67272,324.8437 L 194.39736,324.54592 L 195.74182,323.19526 L 198.23407,322.42156 L 198.2201,320.92384 L 198.21507,319.4261 L 200.64772,318.57431 L 202.08178,317.23258 L 202.4686,315.90217 L 203.45589,314.66107 L 204.81833,313.52188 L 205.58694,312.23738 L 204.473,310.97693 L 204.12808,309.59816 L 204.19798,308.19855 L 205.25284,306.91381 L 206.63363,305.65025 L 207.27664,304.23174 L 205.66553,303.00202 L 205.44391,301.51172 L 204.24735,300.15147 L 204.73194,298.67384 L 202.20698,297.99463 L 200.81764,296.69135 L 198.27875,296.25753 L 195.77947,295.76381 L 194.03485,294.68043 L 192.92783,293.38437 L 191.86587,292.12578 L 189.79667,291.28538 L 188.75047,290.06783 L 187.50549,288.90349 L 187.41767,287.57527 L 188.15487,286.30443 L 189.00265,285.03766 L 190.79573,284.08376 L 192.3734,283.01488 L 193.16448,281.72606 L 193.84812,280.3582 L 192.75538,279.06639 L 193.30719,277.76615 L 193.68267,276.44853 L 192.87475,275.18688 L 192.00468,273.93678 L 191.06278,272.6497 L 191.56876,271.2961 L 191.70866,269.88824 L 193.52657,268.85494"
- style="fill:url(#radialGradient4250);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1.71851885;stroke-miterlimit:4;stroke-opacity:1" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="387.78088"
- height="236.67728"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dust3.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="520"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="359"
- inkscape:window-y="103" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-112.24286,-169.15633)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:9.80000019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 117.14286,383.79075 C 132.89134,377.9933 141.35833,331.00385 162.85714,309.50504 C 179.04427,293.31791 204.56791,260.36922 214.28571,240.93361 C 221.87943,225.74618 269.62455,193.26419 288.57143,183.79075 C 322.78762,166.68266 384.04214,174.38325 414.28571,189.50504 C 443.33513,204.02975 470.5072,233.37658 482.85714,258.07647 C 494.64175,281.64568 500.51676,319.90009 488.57143,343.79075 C 472.23394,376.46573 461.06991,400.93361 420,400.93361 C 386.98682,400.93361 357.67527,390.56986 345.71429,366.6479 C 331.7481,338.71553 313.48288,313.61367 300,286.6479 C 271.13254,228.91297 304.25918,299.42543 294.28571,269.50504"
- id="path2160" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="99.410004"
- height="233.62619"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dust4.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="DiamondS"
- orient="auto"
- refY="0"
- refX="0"
- id="DiamondS"
- style="overflow:visible">
- <path
- id="path3217"
- d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="scale(0.2,0.2)" />
- </marker>
- <marker
- style="overflow:visible"
- id="DistanceIn"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="DistanceIn">
- <g
- id="g2300">
- <path
- style="fill:none;stroke:#ffffff;stroke-width:1.14999998;stroke-linecap:square"
- d="M 0,0 L 2,0"
- id="path2306" />
- <path
- style="fill:#000000;fill-rule:evenodd;stroke:none"
- d="M 0,0 L 13,4 L 9,0 L 13,-4 L 0,0 z "
- id="path2302" />
- <path
- style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square"
- d="M 0,-4 L 0,40"
- id="path2304" />
- </g>
- </marker>
- <marker
- inkscape:stockid="Arrow2Send"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow2Send"
- style="overflow:visible">
- <path
- id="path3164"
- style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- transform="matrix(-0.3,0,0,-0.3,0.69,0)" />
- </marker>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.4074468"
- inkscape:cx="71.428571"
- inkscape:cy="105.71429"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="875"
- inkscape:window-y="0"
- width="99.41px"
- height="233.62619px"
- showguides="true"
- inkscape:guide-bbox="true" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-243.11429,-209.90743)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow2Send);marker-mid:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 291.42857,218.07647 C 272.34606,222.088 251.42857,231.57861 251.42857,269.50504 C 251.42857,297.73622 256.73845,331.55337 268.57143,355.21933 C 278.43679,374.95004 253.6971,424.96798 245.71429,440.93361"
- id="path2160" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="172.63466"
- height="265.65714"
- id="svg2186"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dust5.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <defs
- id="defs2188" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="520"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata2191">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-167.17143,-216.67647)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 185.71429,480.93361 C 188.96777,468.49843 168.57143,429.55044 168.57143,400.93361 C 168.57143,374.88777 199.28869,339.49909 208.57143,320.93361 C 222.78379,292.50889 246.00003,285.60027 277.14286,275.21933 C 307.18704,265.2046 334.28571,323.13529 334.28571,343.79075 C 334.28571,376.81996 350.98623,401.15478 317.14286,418.07647 C 290.79544,431.25018 254.79122,418.32922 231.42857,406.6479 C 210.48639,396.17681 220,341.45229 220,320.93361 C 220,279.3284 208.87913,269.19734 242.85714,235.21933 C 249.33287,228.7436 269.08286,222.10647 277.14286,218.07647"
- id="path2194" />
- </g>
-</svg>
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-#include <limits.h>
-
-extern mlt_filter filter_dust_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_grain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_lines_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_oldfilm_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_tcolor_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_vignette_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-static mlt_properties oldfilm_metadata( mlt_service_type type, const char *id, void *data )
-{
- char file[ PATH_MAX ];
- snprintf( file, PATH_MAX, "%s/oldfilm/filter_%s.yml", mlt_environment( "MLT_DATA" ), id );
- return mlt_properties_parse_yaml( file );
-}
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "oldfilm", filter_oldfilm_init );
- MLT_REGISTER( filter_type, "dust", filter_dust_init );
- MLT_REGISTER( filter_type, "lines", filter_lines_init );
- MLT_REGISTER( filter_type, "grain", filter_grain_init );
- MLT_REGISTER( filter_type, "tcolor", filter_tcolor_init );
- MLT_REGISTER( filter_type, "vignette", filter_vignette_init );
-
- MLT_REGISTER_METADATA( filter_type, "vignette", oldfilm_metadata, NULL );
- MLT_REGISTER_METADATA( filter_type, "tcolor", oldfilm_metadata, NULL );
- MLT_REGISTER_METADATA( filter_type, "grain", oldfilm_metadata, NULL );
- MLT_REGISTER_METADATA( filter_type, "lines", oldfilm_metadata, NULL );
- MLT_REGISTER_METADATA( filter_type, "dust", oldfilm_metadata, NULL );
- MLT_REGISTER_METADATA( filter_type, "oldfilm", oldfilm_metadata, NULL );
-
-}
-
-
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="119.44395"
- height="103.53123"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- version="1.0"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="dus.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="520"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1672"
- inkscape:window-height="969"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-63.761736,-89.023088)">
- <path
- sodipodi:type="star"
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="path2160"
- sodipodi:sides="4"
- sodipodi:cx="88.571426"
- sodipodi:cy="120.93361"
- sodipodi:r1="28.571428"
- sodipodi:r2="11.714285"
- sodipodi:arg1="0.64350111"
- sodipodi:arg2="1.4288993"
- inkscape:flatsided="false"
- inkscape:rounded="0.6"
- inkscape:randomized="-0.046"
- d="M 112.40071,138.48615 C 104.63523,149.2232 103.39252,131.84024 90.301427,133.56163 C 77.210335,135.28301 81.871947,152.01419 71.336774,143.68907 C 60.801601,135.36395 78.494219,134.93387 76.174183,122.07035 C 73.854148,109.20683 57.818168,114.22716 66.13398,103.91357 C 74.449793,93.59998 72.430606,110.63192 85.604689,108.83809 C 98.778772,107.04427 94.053041,90.946435 104.56934,98.710649 C 115.08564,106.47486 97.158906,106.41587 99.590228,119.11612 C 102.02155,131.81637 120.16619,127.74909 112.40071,138.48615 z " />
- <path
- sodipodi:type="star"
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="path2162"
- sodipodi:sides="4"
- sodipodi:cx="111.42857"
- sodipodi:cy="178.07648"
- sodipodi:r1="12.777531"
- sodipodi:r2="5.2387872"
- sodipodi:arg1="-0.46364761"
- sodipodi:arg2="0.32175055"
- inkscape:flatsided="true"
- inkscape:rounded="0.6"
- inkscape:randomized="-0.046"
- d="M 122.44277,172.69754 C 127.84769,182.25699 126.41544,184.43858 116.88365,189.64343 C 107.35186,194.84828 104.6647,193.25522 99.636235,183.39008 C 94.607766,173.52495 95.553578,171.33947 105.19655,166.41559 C 114.83951,161.4917 117.03785,163.1381 122.44277,172.69754 z " />
- <path
- sodipodi:type="star"
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="path2164"
- sodipodi:sides="4"
- sodipodi:cx="168.57143"
- sodipodi:cy="103.79075"
- sodipodi:r1="12.777531"
- sodipodi:r2="9.035079"
- sodipodi:arg1="0.46364761"
- sodipodi:arg2="1.2490458"
- inkscape:flatsided="true"
- inkscape:rounded="0.6"
- inkscape:randomized="-0.046"
- d="M 180.40305,108.92085 C 175.41043,118.48299 172.98728,120.00139 163.16132,115.65738 C 153.33537,111.31338 152.8374,107.92884 157.36569,97.901837 C 161.89398,87.874831 165.34367,86.870642 174.60621,92.239286 C 183.86875,97.60793 185.39567,99.358711 180.40305,108.92085 z " />
- </g>
-</svg>
+++ /dev/null
-/*
- * filter_dust.c -- dust filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-//#include <framework/mlt_filter.h>
-//#include <framework/mlt_frame.h>
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <time.h>
-
-static void overlay_image(uint8_t *src, int src_width, int src_height , uint8_t * overlay, int overlay_width, int overlay_height, uint8_t * alpha , int xpos, int ypos, int upsidedown , int mirror ){
- int x,y;
-
- for (y=ypos;y<src_height ; y++){
- if ( y>=0 && (y-ypos)<overlay_height ){
- uint8_t *scanline_image=src+src_width*y*2;
- int overlay_y = upsidedown ? ( overlay_height - ( y - ypos ) - 1 ) : ( y - ypos );
- uint8_t *scanline_overlay=overlay + overlay_width * 2 * overlay_y;
-
- for ( x = xpos ; x < src_width && x-xpos < overlay_width ;x++){
- if ( x>0 ){
- int overlay_x = mirror ? overlay_width - ( x - xpos ) -1 : ( x - xpos );
- double alp=(double)*(alpha+ overlay_width * overlay_y + overlay_x )/255.0;
- uint8_t* image_pixel = scanline_image + x * 2;
- uint8_t* overlay_pixel = scanline_overlay + overlay_x * 2;
-
- *image_pixel=(double)(*overlay_pixel)*alp+ (double)*image_pixel*(1.0-alp) ;
- if (xpos%2==0)
- image_pixel++;
- else
- image_pixel+=3;
-
- mirror? overlay_pixel-- : overlay_pixel++;
-
- *image_pixel=(double)(*(overlay_pixel))*alp + (double)(*image_pixel )*(1.0-alp) ;
- }
-
- }
- }
- }
-}
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_filter filter = mlt_frame_pop_service( this );
-
- int maxdia = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "maxdiameter" );
- int maxcount = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "maxcount" );
-
- mlt_position in = mlt_filter_get_in( filter );
- mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
-
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
- // load svg
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
- char *factory = mlt_properties_get( properties, "factory" );
- char temp[1204]="";
- sprintf( temp, "%s/oldfilm/", mlt_environment( "MLT_DATA" ) );
-
- mlt_properties direntries=mlt_properties_new();
- mlt_properties_dir_list(direntries,temp,"dust*.svg",1);
-
- if (!maxcount)
- return 0;
- srand(position*10000);
-
- int im=rand()%maxcount;
- int piccount=mlt_properties_count(direntries);
- while (im-- && piccount){
-
- int picnum=rand()%piccount;
-
- int y1=rand()%*height;
- int x1=rand()%*width;
- char resource[1024]="";
- char savename[1024]="",savename1[1024]="", cachedy[100];
- int dx=(*width*maxdia/100);
- int luma_width,luma_height;
- uint8_t *luma_image = NULL;
- uint8_t *alpha =NULL;
- int updown= rand()%2;
- int mirror=rand()%2;
-
- sprintf(resource,"%s",mlt_properties_get_value(direntries,picnum));
- sprintf(savename,"cache-%d-%d",picnum,dx);
- sprintf(savename1,"cache-alpha-%d-%d",picnum,dx);
- sprintf(cachedy,"cache-dy-%d-%d",picnum,dx);
-
- luma_image= mlt_properties_get_data( properties , savename , NULL );
- alpha= mlt_properties_get_data( properties , savename1 , NULL );
-
- if (luma_image == NULL || alpha == NULL ){
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
- mlt_producer producer = mlt_factory_producer( profile, factory, resource );
-
- if ( producer != NULL )
- {
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- mlt_properties_set( producer_properties, "eof", "loop" );
- mlt_frame luma_frame = NULL;
-
- if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &luma_frame, 0 ) == 0 ){
-
- mlt_properties_set_double ( MLT_FRAME_PROPERTIES ( luma_frame ) , "consumer_aspect_ratio" , 1.0 );
- mlt_image_format luma_format = mlt_image_yuv422;
- luma_width = dx;
- luma_height = luma_width * mlt_properties_get_int( MLT_FRAME_PROPERTIES ( luma_frame ) , "height" ) / mlt_properties_get_int( MLT_FRAME_PROPERTIES ( luma_frame ) , "width" );
-
- mlt_properties_set( MLT_FRAME_PROPERTIES( luma_frame ), "rescale.interp", "best" );// none/nearest/tiles/hyper
-
- mlt_frame_get_image( luma_frame, &luma_image, &luma_format, &luma_width, &luma_height, 0 );
- alpha =mlt_frame_get_alpha_mask(luma_frame);
-
- uint8_t* savealpha=mlt_pool_alloc ( luma_width * luma_height );
- uint8_t* savepic=mlt_pool_alloc ( luma_width * luma_height * 2);
-
- if (savealpha && savepic ){
- memcpy (savealpha, alpha , luma_width * luma_height );
- memcpy (savepic, luma_image , luma_width * luma_height * 2);
-
- mlt_properties_set_data ( properties , savename , savepic , sizeof(uint8_t*) , mlt_pool_release, NULL );
- mlt_properties_set_data ( properties , savename1 , savealpha , sizeof(uint8_t*) , mlt_pool_release, NULL );
- mlt_properties_set_int ( properties , cachedy , luma_height );
-
- overlay_image(*image,*width,*height,luma_image,luma_width,luma_height, alpha, x1, y1 , updown , mirror );
- }
- mlt_frame_close( luma_frame );
- }
- mlt_producer_close( producer );
- }
- }else {
- overlay_image ( *image , *width, *height , luma_image , dx , mlt_properties_get_int ( properties , cachedy ) , alpha , x1 , y1 , updown , mirror );
- }
- }
- if (piccount>0 )
- return 0;
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
-
- int h = *height;
- int w = *width;
- if (maxcount==0)
- return 0;
-
- int im=rand()%maxcount;
-
- while (im-- ){
- int type=im%2;
- int y1=rand()%h;
- int x1=rand()%w;
- int dx=rand()%maxdia;
- int dy=rand()%maxdia;
- int x=0,y=0;//,v=0;
- double v=0.0;
- for ( x = -dx ; x < dx ; x++ )
- for ( y = -dy ; y < dy ; y++ ) {
- if ( x1+x < w && x1+x > 0 && y1+y < h && y1+y > 0 ){
- uint8_t *pix=*image+(y+y1)*w*2+(x+x1)*2;
- //v=(1.0-fabs(x)/dx)*(1.0-fabs(y)/dy);
- v=pow((double)x/(double)dx*5.0,2.0)+pow((double)y/(double)dy*5.0,2.0);
- if (v>10)
- v=10;
- v=1.0-(v/10.0);
-
- switch(type){
- case 0:
- *pix-=(*pix)*v;
- break;
- case 1:
- *pix+=(255-*pix)*v;
- break;
- }
- }
- }
- }
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-
-mlt_filter filter_dust_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "maxdiameter", "2" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "maxcount", "10" );
- }
- return this;
-}
-
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: dust
-title: Dust
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: Add dust and specks to the Video, as in old movies
-icon:
- filename: oldfilm/fdust.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: maxdiameter
- title: Maximal Diameter
- type: integer
- description: Maximal diameter of a dust piece
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 2
- mutable: no
- widget: spinner
- unit: %
-
- - identifier: maxcount
- title: Maximal number of dust
- type: integer
- description: How many dust pieces are on the image
- readonly: no
- required: yes
- minimum: 0
- maximum: 400
- default: 10
- mutable: no
- widget: spinner
-
+++ /dev/null
-/*
- * filter_grain.c -- grain filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#define MIN(a,b) (a<b?a:b)
-#define MAX(a,b) (a>b?a:b)
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- int h = *height;
- int w = *width;
-
- mlt_position in = mlt_filter_get_in( filter );
- mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- srand(position*10000);
-
- int noise = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "noise" );
- double contrast = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "contrast" )/100.0;
- double brightness = 127.0 * (mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "brightness" )-100.0)/100.0;
-
- int x=0,y=0,pix=0;
- for (x=0;x<w;x++)
- for(y=0;y<h;y++){
- uint8_t* pixel=(*image+(y)*w*2+(x)*2);
- if (*pixel>20){
- pix= MIN ( MAX ( ( (double)*pixel -127.0 ) * contrast + 127.0 + brightness , 0 ) , 255 ) ;
- if (noise>0)
- pix-=(rand()%noise-noise);
-
- *pixel= MIN ( MAX ( pix , 0 ) , 255 );
- }
- //*(pixel+1)= MIN ( MAX ( ( (double)*(pixel+1) -127.0 ) * .5 + 127.0 , 0 ) , 255 ) ;
- }
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-mlt_filter filter_grain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "noise", "40" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "contrast", "160" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "brightness", "70" );
- }
- return this;
-}
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: grain
-title: Grain
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: Grain over the Image
-icon:
- filename: oldfilm/grain.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: noise
- title: Noise
- type: integer
- description: Maximal value of noise
- readonly: no
- required: yes
- minimum: 0
- maximum: 200
- default: 40
- mutable: no
- widget: spinner
- unit: %
-
- - identifier: contrast
- title: Contrast
- type: integer
- description: Adjust contrast for the image
- readonly: no
- required: yes
- minimum: 0
- maximum: 400
- default: 160
- mutable: no
- widget: spinner
-
- - identifier: brightness
- title: Brightness
- type: integer
- description: Adjust brightness for the image
- readonly: no
- required: yes
- minimum: 0
- maximum: 400
- default: 70
- mutable: no
- widget: spinner
+++ /dev/null
-/*
- * filter_lines.c -- lines filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- int h = *height;
- int w = *width;
-
- int width_line = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "width" );
- int num = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "num" );
- double maxdarker= (double)mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "darker" ) ;
- double maxlighter=(double)mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "lighter" ) ;
- //int frame = mlt_properties_get_int( this, "_position" );
- char buf[256];
- char typebuf[256];
-
- mlt_position in = mlt_filter_get_in( filter );
- mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- srand(position*10000);
- if (!width_line)
- return 0;
-
- while (num--){
- int type=(rand()%3)+1;
- int x1=(double)w*rand()/RAND_MAX;
- int dx=rand()%width_line;
- int x=0,y=0;
- int ystart=rand()%h;
- int yend=rand()%h;
-
- sprintf(buf,"line%d",num);
- sprintf(typebuf,"typeline%d",num);
- maxlighter+=rand()%30-15;
- maxdarker+=rand()%30-15;
-
- if (mlt_properties_get_int(MLT_FILTER_PROPERTIES( filter ),buf)==0){
- mlt_properties_set_int(MLT_FILTER_PROPERTIES( filter ),buf,x1);
- }
-
- if (mlt_properties_get_int(MLT_FILTER_PROPERTIES( filter ),typebuf)==0 ){
- mlt_properties_set_int(MLT_FILTER_PROPERTIES( filter ),typebuf,type);
- }
-
-
- x1=mlt_properties_get_int(MLT_FILTER_PROPERTIES( filter ),buf);
- type=mlt_properties_get_int(MLT_FILTER_PROPERTIES( filter ),typebuf);
- if (position!=mlt_properties_get_double(MLT_FILTER_PROPERTIES( filter ),"last_oldfilm_line_pos")){
- x1+=(rand()%11-5);
- }
-
- if (yend<ystart){
- yend=h;
- }
-
- for (x = -dx ; x < dx && dx != 0 ; x++ )
- for(y=ystart;y<yend;y++)
- if (x+x1<w && x+x1>0){
- uint8_t* pixel=(*image+(y)*w*2+(x+x1)*2);
- double diff=1.0-fabs(x)/dx;
- switch(type){
- case 1: //blackline
- *pixel-=((double)*pixel*diff*maxdarker/100.0);
- break;
- case 2: //whiteline
- *pixel+=((255.0-(double)*pixel)*diff*maxlighter/100.0);
- break;
- case 3: //greenline
- *(pixel+1)-=((*(pixel+1))*diff*maxlighter/100.0);
- break;
- }
-
- }
- mlt_properties_set_int(MLT_FILTER_PROPERTIES( filter ),buf,x1);
- }
- mlt_properties_set_double(MLT_FILTER_PROPERTIES( filter ),"last_oldfilm_line_pos",position);
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-mlt_filter filter_lines_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "width", "2" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "num", "5" );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "darker" , 40 ) ;
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "lighter" , 40 ) ;
- }
- return this;
-}
-
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: lines
-title: Scratchlines
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: Scratchlines over the Picture
-icon:
- filename: oldfilm/lines.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: width
- title: Width of line
- type: integer
- description: Linewidth in picture
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 2
- mutable: no
- widget: spinner
- unit: pixel
-
- - identifier: num
- title: Max number of lines
- type: integer
- description: Maximal number of lines in picture
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 5
- mutable: no
- widget: spinner
- unit: lines
-
- - identifier: darker
- title: Max darker
- type: integer
- description: Make image up to n values darker behind line
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 40
- mutable: no
- widget: spinner
-
- - identifier: lighter
- title: Max lighter
- type: integer
- description: Make image up to n values lighter behind line
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 40
- mutable: no
- widget: spinner
-
-
+++ /dev/null
-/*
- * filter_oldfilm.c -- oldfilm filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- int h = *height;
- int w = *width;
-
- int x=0;
- int y=0;
-
- mlt_position in = mlt_filter_get_in( filter );
- mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
- double position = ( double )( time - in ) / ( double )( out - in + 1 );
- srand(position*10000);
-
- int delta = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "delta" );
- int every = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "every" );
-
- int bdu = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "brightnessdelta_up" );
- int bdd = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "brightnessdelta_down" );
- int bevery = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "brightnessdelta_every" );
-
- int diffpic=0;
- if (delta)
- diffpic=rand()%delta*2-delta;
-
- int brightdelta=0;
- if ((bdu+bdd)!=0)
- brightdelta=rand()%(bdu+bdd)-bdd;
- if (rand()%100>every)
- diffpic=0;
- if (rand()%100>bevery)
- brightdelta=0;
- int yend,ydiff;
- if (diffpic<=0){
- y=h;
- yend=0;
- ydiff=-1;
- }else{
- y=0;
- yend=h;
- ydiff=1;
- }
-
- while(y!=yend){
- //int newy=y+diffpic;
- for (x=0;x<w;x++){
- uint8_t* pic=(*image+y*w*2+x*2);
- int newy=y+diffpic;
- if (newy>0 && newy<h ){
- uint8_t oldval=*(pic+diffpic*w*2);
- /* frame around
- int randx=(x<=frameborder)?x:(x+frameborder>w)?w-x:-1;
- int randy=((newy)<=frameborder)?(newy):((newy)+frameborder>h)?h-(y+diffpic):-1;
- if (randx>=0 ){
- oldval=oldval*pow(((double)randx/(double)frameborder),1.5);
- }
- if (randy>=0 ){
- oldval=oldval*pow(((double)randy/(double)frameborder),1.5);
- }
- if (randx>=0 && randy>=0){
- //oldval=oldval*(randx*randy)/500.0;
- }
- */
- if ( ((int) oldval + brightdelta ) >255)
- *pic=255;
- else if ( ( (int) oldval+brightdelta ) <0){
- *pic=0;
- }else
- *pic=oldval+brightdelta;
- *(pic+1)=*(pic+diffpic*w*2+1);
-
- }else{
- *pic=0;
- //*(pic-1)=127;
- }
-
- }
- y+=ydiff;
- }
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-mlt_filter filter_oldfilm_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "delta", "14" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "every", "20" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "brightnessdelta_up" , "20" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "brightnessdelta_down" , "30" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "brightnessdelta_every" , "70" );
- }
- return this;
-}
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: oldfilm
-title: Oldfilm
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: Moves the Picture up and down and random brightness change
-icon:
- filename: oldfilm/oldfilm.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: delta
- title: Y-Delta
- type: integer
- description: Maximum delta value of Up/Down move
- readonly: no
- required: yes
- minimum: 0
- maximum: 400
- default: 14
- mutable: no
- widget: spinner
- unit: pixel
-
- - identifier: every
- title: % of picture have a delta
- type: integer
- description: n'th % have a Y-Delta in picture
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 20
- mutable: no
- widget: spinner
- unit: %
-
- - identifier: brightnessdelta_up
- title: Brightness up
- type: integer
- description: Makes image n values lighter
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 20
- mutable: no
- widget: spinner
-
- - identifier: brightnessdelta_down
- title: Brightness down
- type: integer
- description: Makes image n values darker
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 20
- mutable: no
- widget: spinner
-
- - identifier: brightnessdelta_every
- title: Brightness every
- type: integer
- description: Change value only for n/100
- readonly: no
- required: yes
- minimum: 0
- maximum: 100
- default: 70
- mutable: no
- widget: spinner
- unit: %
+++ /dev/null
-/*
- * filter_tcolor.c -- tcolor filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define MIN(a,b) (a<b?a:b)
-#define MAX(a,b) (a<b?b:a)
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
-
- double over_cr = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "oversaturate_cr" )/100.0;
- double over_cb = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "oversaturate_cb" )/100.0;
-
- int video_width = *width;
- int video_height = *height;
-
- int x,y;
-
- for (y=0;y<video_height;y++){
- for (x=0;x<video_width;x+=2){
- uint8_t *pix=(*image+y*video_width*2+x*2+1);
- uint8_t *pix1=(*image+y*video_width*2+x*2+3);
- *pix=MIN(MAX( ((double)*pix-127.0)*over_cb+127.0,0),255);
- *pix1=MIN(MAX( ((double)*pix1-127.0)*over_cr+127.0,0),255);
- }
- }
- // short a, short b, short c, short d
- // a= gray val pix 1
- // b: +=blue, -=yellow
- // c: =gray pix 2
- // d: +=red,-=green
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-
-mlt_filter filter_tcolor_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "oversaturate_cr", "190" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "oversaturate_cb", "190" );
- }
- return this;
-}
-
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: tcolor
-title: Technicolor
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: Oversaturate the Color in Video, like in old Technicolor movies
-icon:
-filename: oldfilm/tcolor.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: oversaturate_cr # 'argument' is a reserved name for a value supplied to the factory
- title: Blue/Yellow- axis
- type: integer
- description: Adjust factor for Blue/Yellow axis
- readonly: no
- required: yes
- minimum: -400
- maximum: 400
- default: 190
- mutable: no
- widget: spinner
-
- - identifier: oversaturate_cb
- title: Red/Green-axis
- type: integer
- description: Adjust factor for Red/Green axis
- readonly: no
- required: yes
- minimum: -400
- maximum: 400
- default: 190
- mutable: no
- widget: spinner
+++ /dev/null
-/*
- * filter_vignette.c -- vignette filter
- * Copyright (c) 2007 Marco Gittler <g.marco@freenet.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_geometry.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#define MIN(a,b) (a<b?a:b)
-#define MAX(a,b) (a<b?b:a)
-
-#define SIGMOD_STEPS 1000
-#define POSITION_VALUE(p,s,e) (s+((double)(e-s)*p ))
-//static double pow2[SIGMOD_STEPS];
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
-
- mlt_filter filter = mlt_frame_pop_service( this );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- mlt_position in = mlt_filter_get_in( filter );
- //mlt_position out = mlt_filter_get_out( filter );
- mlt_position time = mlt_frame_get_position( this );
-
- mlt_geometry geom=mlt_geometry_init();
- struct mlt_geometry_item_s item;
- float smooth, radius, cx, cy, opac;
- char *val=mlt_properties_get(MLT_FILTER_PROPERTIES( filter ), "geometry" );
- mlt_geometry_parse(geom,val,-1,-1,-1);
- mlt_geometry_fetch(geom,&item,time-in);
- smooth=item.x;
- radius=item.y;
- cx=item.w;
- cy=item.h;
- opac=item.mix;
- mlt_geometry_close(geom);
-
- int video_width = *width;
- int video_height = *height;
-
- int x,y;
- int w2=cx,h2=cy;
- double delta=1.0;
- double max_opac=opac/100.0;
-
- for (y=0;y<video_height;y++){
- int h2_pow2=pow(y-h2,2.0);
- for (x=0;x<video_width;x++){
- uint8_t *pix=(*image+y*video_width*2+x*2);
- int dx=sqrt(h2_pow2+pow(x-w2,2.0));
-
- if (radius-smooth>dx){ //center, make not darker
- continue;
- }
- else if (radius+smooth<=dx){//max dark after smooth area
- delta=0.0;
- }else{
- //double sigx=5.0-10.0*(double)(dx-radius+smooth)/(2.0*smooth);//smooth >10 inner area, <-10 in dark area
- //delta=pow2[((int)((sigx+10.0)*SIGMOD_STEPS/20.0))];//sigmoidal
- delta = ((double)(radius+smooth-dx)/(2.0*smooth));//linear
- }
- delta=MAX(max_opac,delta);
- *pix=(double)(*pix)*delta;
- *(pix+1)=((double)(*(pix+1)-127.0)*delta)+127.0;
- }
- }
- // short a, short b, short c, short d
- // a= gray val pix 1
- // b: +=blue, -=yellow
- // c: =gray pix 2
- // d: +=red,-=green
- }
-
- return error;
-}
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
-
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-
-mlt_filter filter_vignette_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- //int i=0;
- if ( this != NULL )
- {
- /*
- for (i=-SIGMOD_STEPS/2;i<SIGMOD_STEPS/2;i++){
- pow2[i+SIGMOD_STEPS/2]=1.0/(1.0+pow(2.0,-((double)i)/((double)SIGMOD_STEPS/20.0)));
- }
- */
-
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "geometry", "80:50%:50%:50%:0" );
- //mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "end", "" );
-
- }
- return this;
-}
-
-
+++ /dev/null
-schema_version: 0.1
-type: filter # consumer, filter, producer, or transition
-identifier: vignette
-title: Vignette Effect
-version: 0.2.5
-copyright: Copyright (C) 2008 Marco Gittler
-license: GPL
-language: en
-url: none
-creator: Marco Gittler
-tags:
- - Video # this may produce video
-description: |
- Vigentte around a point with adjustable smooth, radius, position
- and transparency
-icon:
-filename: oldfilm/vignette.svg # relative to $MLT_DATA/modules/
- content-type: image/svg
-
-notes: Implementation or additional usage notes go here.
-bugs: # this can be just for documentation, or the tool may disclose it to help user avoid pitfalls
- - need to do some speed improvement.
-
-parameters:
- - identifier: geometry # 'argument' is a reserved name for a value supplied to the factory
- title: Geometry Value # the title can be used as a label for the widget
- type: geometry
- description: Start position, "smooth":"radius","X"x"Y","maxopac"
- readonly: no
- required: yes
- mutable: no
- format: %d:%d:%dx%d:%d
- minimum: 0:0:0:0:0
- maximum: 100:100:100:100:100
- default: 80:50%:50%:50%:0
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="68.586548"
- height="57.142868"
- id="svg2267"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="grai.svg"
- version="1.0"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.82687501"
- inkscape:cx="547.34922"
- inkscape:cy="-51.149976"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1195"
- inkscape:window-height="742"
- inkscape:window-x="315"
- inkscape:window-y="144" />
- <defs
- id="defs2269" />
- <metadata
- id="metadata2272">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- id="layer1"
- inkscape:groupmode="layer"
- transform="translate(-49.372635,-144.21402)">
- <rect
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect3308"
- width="22.857143"
- height="28.571428"
- x="49.372635"
- y="144.21402" />
- <rect
- y="144.21404"
- x="72.199547"
- height="28.571428"
- width="22.857143"
- id="rect3310"
- style="opacity:0.68085106;fill:#000000;fill-opacity:0.63380283;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- style="opacity:0.68085106;fill:#000000;fill-opacity:0.10563378;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect3312"
- width="22.857143"
- height="28.571428"
- x="95.026451"
- y="144.21404" />
- <rect
- y="172.78546"
- x="95.102043"
- height="28.571428"
- width="22.857143"
- id="rect3314"
- style="opacity:0.94680852;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect3316"
- width="22.857143"
- height="28.571428"
- x="72.275139"
- y="172.78546" />
- <rect
- y="172.78546"
- x="49.448231"
- height="28.571428"
- width="22.857143"
- id="rect3318"
- style="opacity:0.41489366;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1" />
- </g>
- <g
- id="g2293"
- inkscape:groupmode="layer"
- inkscape:label="fill text"
- transform="translate(-49.372635,-144.21402)" />
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="138.14285"
- height="275.28571"
- id="svg2251"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- version="1.0"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="lin.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <defs
- id="defs2253" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="62.857143"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata2256">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-128.07143,-217.57647)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 180,223.79075 L 180,492.36218"
- id="path2261" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 265.71429,218.07647 L 265.71429,389.50504"
- id="path2263" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 128.57143,309.50504 L 128.57143,440.93361"
- id="path2265" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="320"
- height="200"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- version="1.0"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="old.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="520"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1181"
- inkscape:window-height="822"
- inkscape:window-x="402"
- inkscape:window-y="124" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-45.714287,-120.93361)">
- <rect
- style="opacity:0.41489366;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect2160"
- width="320"
- height="200"
- x="45.714287"
- y="120.93361" />
- <rect
- style="opacity:0.41489366;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect2162"
- width="268.57144"
- height="171.42857"
- x="74.285713"
- y="149.50504" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="112.63159"
- height="102.85714"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="tcol.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- version="1.0">
- <defs
- id="defs4">
- <marker
- inkscape:stockid="Arrow1Lend"
- orient="auto"
- refY="0"
- refX="0"
- id="Arrow1Lend"
- style="overflow:visible">
- <path
- id="path4111"
- d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
- style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
- transform="matrix(-0.8,0,0,-0.8,-10,0)" />
- </marker>
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="3.5843946"
- inkscape:cx="88.57143"
- inkscape:cy="77.236043"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="1121"
- inkscape:window-height="586"
- inkscape:window-x="551"
- inkscape:window-y="239" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-42.857143,-175.21933)">
- <rect
- style="opacity:1;fill:#910000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5999999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect2160"
- width="52.370373"
- height="102.85714"
- x="42.857143"
- y="175.21933" />
- <rect
- y="175.21933"
- x="94.469757"
- height="102.85714"
- width="61.018974"
- id="rect2162"
- style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5999999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- style="opacity:0.68085106;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;marker-end:url(#Arrow1Lend);stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- d="M 66.39894,224.60733 C 123.87029,224.60733 123.87029,224.60733 123.87029,224.60733"
- id="path3134" />
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="251.42857"
- height="188.57143"
- id="svg2182"
- sodipodi:version="0.32"
- inkscape:version="0.45.1"
- version="1.0"
- sodipodi:docbase="/home/marco/mlt-svn/mlt/src/modules/oldfilm"
- sodipodi:docname="vig.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <defs
- id="defs2184">
- <linearGradient
- id="linearGradient3165">
- <stop
- style="stop-color:#ffffff;stop-opacity:1;"
- offset="0"
- id="stop3167" />
- <stop
- style="stop-color:#000000;stop-opacity:0.98666668;"
- offset="1"
- id="stop3169" />
- </linearGradient>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3165"
- id="radialGradient3171"
- cx="228.57143"
- cy="300.93362"
- fx="228.57143"
- fy="300.93362"
- r="77.14286"
- gradientTransform="matrix(1,0,0,0.9259259,0,22.291383)"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="350"
- inkscape:cy="-176.04888"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:window-width="797"
- inkscape:window-height="586"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata2187">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-105.71429,-195.21933)">
- <rect
- style="opacity:0.95035466;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="rect2190"
- width="251.42857"
- height="188.57143"
- x="105.71429"
- y="195.21933" />
- <path
- sodipodi:type="arc"
- style="opacity:1;fill:url(#radialGradient3171);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.5999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2.4000001;stroke-dasharray:none;stroke-opacity:1"
- id="path2192"
- sodipodi:cx="228.57143"
- sodipodi:cy="300.93362"
- sodipodi:rx="77.14286"
- sodipodi:ry="71.428574"
- d="M 305.71429 300.93362 A 77.14286 71.428574 0 1 1 151.42857,300.93362 A 77.14286 71.428574 0 1 1 305.71429 300.93362 z"
- transform="translate(0,-11.428571)" />
- </g>
-</svg>
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltplus$(LIBSUF)
-
-OBJS = factory.o \
- filter_affine.o \
- filter_charcoal.o \
- filter_invert.o \
- filter_sepia.o \
- transition_affine.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_affine_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_charcoal_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_invert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_sepia_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_transition transition_affine_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "affine", filter_affine_init );
- MLT_REGISTER( filter_type, "charcoal", filter_charcoal_init );
- MLT_REGISTER( filter_type, "invert", filter_invert_init );
- MLT_REGISTER( filter_type, "sepia", filter_sepia_init );
- MLT_REGISTER( transition_type, "affine", transition_affine_init );
-}
+++ /dev/null
-/*
- * filter_affine.c -- affine filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Get the properties
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the image
- int error = 0; //mlt_frame_get_image( this, image, format, width, height, 0 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- mlt_producer producer = mlt_properties_get_data( properties, "producer", NULL );
- mlt_transition transition = mlt_properties_get_data( properties, "transition", NULL );
- mlt_frame a_frame = NULL;
-
- if ( producer == NULL )
- {
- char *background = mlt_properties_get( properties, "background" );
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
- producer = mlt_factory_producer( profile, "fezzik", background );
- mlt_properties_set_data( properties, "producer", producer, 0, (mlt_destructor)mlt_producer_close, NULL );
- }
-
- if ( transition == NULL )
- {
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
- transition = mlt_factory_transition( profile, "affine", NULL );
- mlt_properties_set_data( properties, "transition", transition, 0, (mlt_destructor)mlt_transition_close, NULL );
- }
-
- if ( producer != NULL && transition != NULL )
- {
- char *name = mlt_properties_get( properties, "_unique_id" );
- mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( this ), name );
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( this );
- double consumer_ar = mlt_properties_get_double( frame_properties, "consumer_aspect_ratio" );
- mlt_properties_set_position( MLT_TRANSITION_PROPERTIES( transition ), "in", mlt_filter_get_in( filter ) );
- mlt_properties_set_position( MLT_TRANSITION_PROPERTIES( transition ), "out", mlt_filter_get_out( filter ) );
- mlt_producer_seek( producer, position );
- mlt_frame_set_position( this, position );
- mlt_properties_pass( MLT_PRODUCER_PROPERTIES( producer ), properties, "producer." );
- mlt_properties_pass( MLT_TRANSITION_PROPERTIES( transition ), properties, "transition." );
- mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &a_frame, 0 );
- mlt_properties_set( MLT_FRAME_PROPERTIES( a_frame ), "rescale.interp", "nearest" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( a_frame ), "distort", 1 );
-
- // Special case - aspect_ratio = 0
- if ( mlt_properties_get_double( frame_properties, "aspect_ratio" ) == 0 )
- mlt_properties_set_double( frame_properties, "aspect_ratio", consumer_ar );
- if ( mlt_properties_get_double( MLT_FRAME_PROPERTIES( a_frame ), "aspect_ratio" ) == 0 )
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( a_frame ), "aspect_ratio", consumer_ar );
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( a_frame ), "consumer_aspect_ratio", consumer_ar );
-
- mlt_transition_process( transition, a_frame, this );
- mlt_frame_get_image( a_frame, image, format, width, height, writable );
- mlt_properties_set_data( frame_properties, "affine_frame", a_frame, 0, (mlt_destructor)mlt_frame_close, NULL );
- mlt_properties_set_data( frame_properties, "image", *image, *width * *height * 2, NULL, NULL );
- mlt_properties_set_data( frame_properties, "alpha", mlt_frame_get_alpha_mask( a_frame ), *width * *height, NULL, NULL );
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get a unique name to store the frame position
- char *name = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "_unique_id" );
-
- // Assign the current position to the name
- mlt_properties_set_position( properties, name, mlt_frame_get_position( frame ) - mlt_filter_get_in( this ) );
-
- // Push the frame filter
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_affine_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "background", "colour:black" );
- }
- return this;
-}
-
-
+++ /dev/null
-/*
- * filter_charcoal.c -- charcoal filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-static inline int get_Y( uint8_t *pixels, int width, int height, int x, int y )
-{
- if ( x < 0 || x >= width || y < 0 || y >= height )
- {
- return 235;
- }
- else
- {
- uint8_t *pixel = pixels + y * ( width << 1 ) + ( x << 1 );
- return *pixel;
- }
-}
-
-static inline int sqrti( int n )
-{
- int p = 0;
- int q = 1;
- int r = n;
- int h = 0;
-
- while( q <= n )
- q = q << 2;
-
- while( q != 1 )
- {
- q = q >> 2;
- h = p + q;
- p = p >> 1;
- if ( r >= h )
- {
- p = p + q;
- r = r - h;
- }
- }
-
- return p;
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- // Get the charcoal scatter value
- int x_scatter = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "x_scatter" );
- int y_scatter = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "y_scatter" );
- float scale = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "scale" );
- float mix = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "mix" );
- int invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "invert" );
-
- // We'll process pixel by pixel
- int x = 0;
- int y = 0;
-
- // We need to create a new frame as this effect modifies the input
- uint8_t *temp = mlt_pool_alloc( *width * *height * 2 );
- uint8_t *p = temp;
- uint8_t *q = *image;
-
- // Calculations are carried out on a 3x3 matrix
- int matrix[ 3 ][ 3 ];
-
- // Used to carry out the matrix calculations
- int sum1;
- int sum2;
- float sum;
- int val;
-
- // Loop for each row
- for ( y = 0; y < *height; y ++ )
- {
- // Loop for each pixel
- for ( x = 0; x < *width; x ++ )
- {
- // Populate the matrix
- matrix[ 0 ][ 0 ] = get_Y( *image, *width, *height, x - x_scatter, y - y_scatter );
- matrix[ 0 ][ 1 ] = get_Y( *image, *width, *height, x , y - y_scatter );
- matrix[ 0 ][ 2 ] = get_Y( *image, *width, *height, x + x_scatter, y - y_scatter );
- matrix[ 1 ][ 0 ] = get_Y( *image, *width, *height, x - x_scatter, y );
- matrix[ 1 ][ 2 ] = get_Y( *image, *width, *height, x + x_scatter, y );
- matrix[ 2 ][ 0 ] = get_Y( *image, *width, *height, x - x_scatter, y + y_scatter );
- matrix[ 2 ][ 1 ] = get_Y( *image, *width, *height, x , y + y_scatter );
- matrix[ 2 ][ 2 ] = get_Y( *image, *width, *height, x + x_scatter, y + y_scatter );
-
- // Do calculations
- sum1 = (matrix[2][0] - matrix[0][0]) + ( (matrix[2][1] - matrix[0][1]) << 1 ) + (matrix[2][2] - matrix[2][0]);
- sum2 = (matrix[0][2] - matrix[0][0]) + ( (matrix[1][2] - matrix[1][0]) << 1 ) + (matrix[2][2] - matrix[2][0]);
- sum = scale * sqrti( sum1 * sum1 + sum2 * sum2 );
-
- // Assign value
- *p ++ = !invert ? ( sum >= 16 && sum <= 235 ? 251 - sum : sum < 16 ? 235 : 16 ) :
- ( sum >= 16 && sum <= 235 ? sum : sum < 16 ? 16 : 235 );
- q ++;
- val = 128 + mix * ( *q ++ - 128 );
- val = val < 16 ? 16 : val > 240 ? 240 : val;
- *p ++ = val;
- }
- }
-
- // Return the created image
- *image = temp;
-
- // Store new and destroy old
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", *image, *width * *height * 2, mlt_pool_release, NULL );
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the frame filter
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_charcoal_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "x_scatter", "1" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "y_scatter", "1" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "scale", "1.5" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "mix", "0" );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_invert.c -- invert filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-static inline int clamp( int v, int l, int u )
-{
- return v < l ? l : ( v > u ? u : v );
-}
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the image
- mlt_filter filter = mlt_frame_pop_service( this );
- int mask = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "alpha" );
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *format == mlt_image_yuv422 )
- {
- uint8_t *p = *image;
- uint8_t *q = *image + *width * *height * 2;
- uint8_t *r = *image;
-
- while ( p != q )
- {
- *p ++ = clamp( 251 - *r ++, 16, 235 );
- *p ++ = clamp( 256 - *r ++, 16, 240 );
- }
-
- if ( mask )
- {
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- int size = *width * *height;
- memset( alpha, mask, size );
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the frame filter
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_invert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- this->process = filter_process;
- return this;
-}
-
+++ /dev/null
-/*
- * filter_sepia.c -- sepia filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the filter
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Get the image
- int error = mlt_frame_get_image( this, image, format, width, height, 1 );
-
- // Only process if we have no error and a valid colour space
- if ( error == 0 && *image && *format == mlt_image_yuv422 )
- {
- // We modify the whole image
- uint8_t *p = *image;
- int h = *height;
- int uneven = *width % 2;
- int w = ( *width - uneven ) / 2;
- int t;
-
- // Get u and v values
- int u = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "u" );
- int v = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "v" );
-
- // Loop through image
- while( h -- )
- {
- t = w;
- while( t -- )
- {
- p ++;
- *p ++ = u;
- p ++;
- *p ++ = v;
- }
- if ( uneven )
- {
- p ++;
- *p ++ = u;
- }
- }
- }
-
- return error;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Push the frame filter
- mlt_frame_push_service( frame, this );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_sepia_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = filter_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "u", "75" );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "v", "150" );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * transition_affine.c -- affine transformations
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_transition.h>
-#include <framework/mlt.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-
-/** Calculate real geometry.
-*/
-
-static void geometry_calculate( mlt_transition this, const char *store, struct mlt_geometry_item_s *output, float position )
-{
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL );
- int mirror_off = mlt_properties_get_int( properties, "mirror_off" );
- int repeat_off = mlt_properties_get_int( properties, "repeat_off" );
- int length = mlt_geometry_get_length( geometry );
-
- // Allow wrapping
- if ( !repeat_off && position >= length && length != 0 )
- {
- int section = position / length;
- position -= section * length;
- if ( !mirror_off && section % 2 == 1 )
- position = length - position;
- }
-
- // Fetch the key for the position
- mlt_geometry_fetch( geometry, output, position );
-}
-
-
-static mlt_geometry transition_parse_keys( mlt_transition this, const char *name, const char *store, int normalised_width, int normalised_height )
-{
- // Get the properties of the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Try to fetch it first
- mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL );
-
- // Get the in and out position
- mlt_position in = mlt_transition_get_in( this );
- mlt_position out = mlt_transition_get_out( this );
-
- // Determine length and obtain cycle
- int length = out - in + 1;
- double cycle = mlt_properties_get_double( properties, "cycle" );
-
- // Allow a geometry repeat cycle
- if ( cycle >= 1 )
- length = cycle;
- else if ( cycle > 0 )
- length *= cycle;
-
- if ( geometry == NULL )
- {
- // Get the new style geometry string
- char *property = mlt_properties_get( properties, name );
-
- // Create an empty geometries object
- geometry = mlt_geometry_init( );
-
- // Parse the geometry if we have one
- mlt_geometry_parse( geometry, property, length, normalised_width, normalised_height );
-
- // Store it
- mlt_properties_set_data( properties, store, geometry, 0, ( mlt_destructor )mlt_geometry_close, NULL );
- }
- else
- {
- // Check for updates and refresh if necessary
- mlt_geometry_refresh( geometry, mlt_properties_get( properties, name ), length, normalised_width, normalised_height );
- }
-
- return geometry;
-}
-
-static mlt_geometry composite_calculate( mlt_transition this, struct mlt_geometry_item_s *result, int nw, int nh, float position )
-{
- // Structures for geometry
- mlt_geometry start = transition_parse_keys( this, "geometry", "geometries", nw, nh );
-
- // Do the calculation
- geometry_calculate( this, "geometries", result, position );
-
- return start;
-}
-
-static inline float composite_calculate_key( mlt_transition this, const char *name, const char *store, int norm, float position )
-{
- // Struct for the result
- struct mlt_geometry_item_s result;
-
- // Structures for geometry
- transition_parse_keys( this, name, store, norm, 0 );
-
- // Do the calculation
- geometry_calculate( this, store, &result, position );
-
- return result.x;
-}
-
-typedef struct
-{
- float matrix[3][3];
-}
-affine_t;
-
-static void affine_init( float this[3][3] )
-{
- this[0][0] = 1;
- this[0][1] = 0;
- this[0][2] = 0;
- this[1][0] = 0;
- this[1][1] = 1;
- this[1][2] = 0;
- this[2][0] = 0;
- this[2][1] = 0;
- this[2][2] = 1;
-}
-
-// Multiply two this affine transform with that
-static void affine_multiply( float this[3][3], float that[3][3] )
-{
- float output[3][3];
- int i;
- int j;
-
- for ( i = 0; i < 3; i ++ )
- for ( j = 0; j < 3; j ++ )
- output[i][j] = this[i][0] * that[j][0] + this[i][1] * that[j][1] + this[i][2] * that[j][2];
-
- this[0][0] = output[0][0];
- this[0][1] = output[0][1];
- this[0][2] = output[0][2];
- this[1][0] = output[1][0];
- this[1][1] = output[1][1];
- this[1][2] = output[1][2];
- this[2][0] = output[2][0];
- this[2][1] = output[2][1];
- this[2][2] = output[2][2];
-}
-
-// Rotate by a given angle
-static void affine_rotate_x( float this[3][3], float angle )
-{
- float affine[3][3];
- affine[0][0] = cos( angle * M_PI / 180 );
- affine[0][1] = 0 - sin( angle * M_PI / 180 );
- affine[0][2] = 0;
- affine[1][0] = sin( angle * M_PI / 180 );
- affine[1][1] = cos( angle * M_PI / 180 );
- affine[1][2] = 0;
- affine[2][0] = 0;
- affine[2][1] = 0;
- affine[2][2] = 1;
- affine_multiply( this, affine );
-}
-
-static void affine_rotate_y( float this[3][3], float angle )
-{
- float affine[3][3];
- affine[0][0] = cos( angle * M_PI / 180 );
- affine[0][1] = 0;
- affine[0][2] = 0 - sin( angle * M_PI / 180 );
- affine[1][0] = 0;
- affine[1][1] = 1;
- affine[1][2] = 0;
- affine[2][0] = sin( angle * M_PI / 180 );
- affine[2][1] = 0;
- affine[2][2] = cos( angle * M_PI / 180 );
- affine_multiply( this, affine );
-}
-
-static void affine_rotate_z( float this[3][3], float angle )
-{
- float affine[3][3];
- affine[0][0] = 1;
- affine[0][1] = 0;
- affine[0][2] = 0;
- affine[1][0] = 0;
- affine[1][1] = cos( angle * M_PI / 180 );
- affine[1][2] = sin( angle * M_PI / 180 );
- affine[2][0] = 0;
- affine[2][1] = - sin( angle * M_PI / 180 );
- affine[2][2] = cos( angle * M_PI / 180 );
- affine_multiply( this, affine );
-}
-
-static void affine_scale( float this[3][3], float sx, float sy )
-{
- float affine[3][3];
- affine[0][0] = sx;
- affine[0][1] = 0;
- affine[0][2] = 0;
- affine[1][0] = 0;
- affine[1][1] = sy;
- affine[1][2] = 0;
- affine[2][0] = 0;
- affine[2][1] = 0;
- affine[2][2] = 1;
- affine_multiply( this, affine );
-}
-
-// Shear by a given value
-static void affine_shear( float this[3][3], float shear_x, float shear_y, float shear_z )
-{
- float affine[3][3];
- affine[0][0] = 1;
- affine[0][1] = tan( shear_x * M_PI / 180 );
- affine[0][2] = 0;
- affine[1][0] = tan( shear_y * M_PI / 180 );
- affine[1][1] = 1;
- affine[1][2] = tan( shear_z * M_PI / 180 );
- affine[2][0] = 0;
- affine[2][1] = 0;
- affine[2][2] = 1;
- affine_multiply( this, affine );
-}
-
-static void affine_offset( float this[3][3], int x, int y )
-{
- this[0][2] += x;
- this[1][2] += y;
-}
-
-// Obtain the mapped x coordinate of the input
-static inline double MapX( float this[3][3], int x, int y )
-{
- return this[0][0] * x + this[0][1] * y + this[0][2];
-}
-
-// Obtain the mapped y coordinate of the input
-static inline double MapY( float this[3][3], int x, int y )
-{
- return this[1][0] * x + this[1][1] * y + this[1][2];
-}
-
-static inline double MapZ( float this[3][3], int x, int y )
-{
- return this[2][0] * x + this[2][1] * y + this[2][2];
-}
-
-#define MAX( x, y ) x > y ? x : y
-#define MIN( x, y ) x < y ? x : y
-
-static void affine_max_output( float this[3][3], float *w, float *h, float dz )
-{
- int tlx = MapX( this, -720, 576 ) / dz;
- int tly = MapY( this, -720, 576 ) / dz;
- int trx = MapX( this, 720, 576 ) / dz;
- int try = MapY( this, 720, 576 ) / dz;
- int blx = MapX( this, -720, -576 ) / dz;
- int bly = MapY( this, -720, -576 ) / dz;
- int brx = MapX( this, 720, -576 ) / dz;
- int bry = MapY( this, 720, -576 ) / dz;
-
- int max_x;
- int max_y;
- int min_x;
- int min_y;
-
- max_x = MAX( tlx, trx );
- max_x = MAX( max_x, blx );
- max_x = MAX( max_x, brx );
-
- min_x = MIN( tlx, trx );
- min_x = MIN( min_x, blx );
- min_x = MIN( min_x, brx );
-
- max_y = MAX( tly, try );
- max_y = MAX( max_y, bly );
- max_y = MAX( max_y, bry );
-
- min_y = MIN( tly, try );
- min_y = MIN( min_y, bly );
- min_y = MIN( min_y, bry );
-
- *w = ( float )( max_x - min_x + 1 ) / 1440.0;
- *h = ( float )( max_y - min_y + 1 ) / 1152.0;
-}
-
-#define IN_RANGE( v, r ) ( v >= - r / 2 && v < r / 2 )
-
-static inline void get_affine( affine_t *affine, mlt_transition this, float position )
-{
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
- int keyed = mlt_properties_get_int( properties, "keyed" );
- affine_init( affine->matrix );
-
- if ( keyed == 0 )
- {
- float fix_rotate_x = mlt_properties_get_double( properties, "fix_rotate_x" );
- float fix_rotate_y = mlt_properties_get_double( properties, "fix_rotate_y" );
- float fix_rotate_z = mlt_properties_get_double( properties, "fix_rotate_z" );
- float rotate_x = mlt_properties_get_double( properties, "rotate_x" );
- float rotate_y = mlt_properties_get_double( properties, "rotate_y" );
- float rotate_z = mlt_properties_get_double( properties, "rotate_z" );
- float fix_shear_x = mlt_properties_get_double( properties, "fix_shear_x" );
- float fix_shear_y = mlt_properties_get_double( properties, "fix_shear_y" );
- float fix_shear_z = mlt_properties_get_double( properties, "fix_shear_z" );
- float shear_x = mlt_properties_get_double( properties, "shear_x" );
- float shear_y = mlt_properties_get_double( properties, "shear_y" );
- float shear_z = mlt_properties_get_double( properties, "shear_z" );
- float ox = mlt_properties_get_double( properties, "ox" );
- float oy = mlt_properties_get_double( properties, "oy" );
-
- affine_rotate_x( affine->matrix, fix_rotate_x + rotate_x * position );
- affine_rotate_y( affine->matrix, fix_rotate_y + rotate_y * position );
- affine_rotate_z( affine->matrix, fix_rotate_z + rotate_z * position );
- affine_shear( affine->matrix,
- fix_shear_x + shear_x * position,
- fix_shear_y + shear_y * position,
- fix_shear_z + shear_z * position );
- affine_offset( affine->matrix, ox, oy );
- }
- else
- {
- float rotate_x = composite_calculate_key( this, "rotate_x", "rotate_x_info", 360, position );
- float rotate_y = composite_calculate_key( this, "rotate_y", "rotate_y_info", 360, position );
- float rotate_z = composite_calculate_key( this, "rotate_z", "rotate_z_info", 360, position );
- float shear_x = composite_calculate_key( this, "shear_x", "shear_x_info", 360, position );
- float shear_y = composite_calculate_key( this, "shear_y", "shear_y_info", 360, position );
- float shear_z = composite_calculate_key( this, "shear_z", "shear_z_info", 360, position );
-
- affine_rotate_x( affine->matrix, rotate_x );
- affine_rotate_y( affine->matrix, rotate_y );
- affine_rotate_z( affine->matrix, rotate_z );
- affine_shear( affine->matrix, shear_x, shear_y, shear_z );
- }
-}
-
-/** Get the image.
-*/
-
-static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Get the b frame from the stack
- mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
-
- // Get the transition object
- mlt_transition this = mlt_frame_pop_service( a_frame );
-
- // Get the properties of the transition
- mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
-
- // Get the properties of the a frame
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
-
- // Get the properties of the b frame
- mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
-
- // Image, format, width, height and image for the b frame
- uint8_t *b_image = NULL;
- mlt_image_format b_format = mlt_image_yuv422;
- int b_width;
- int b_height;
-
- // Get the unique name to retrieve the frame position
- char *name = mlt_properties_get( properties, "_unique_id" );
-
- // Assign the current position to the name
- mlt_position position = mlt_properties_get_position( a_props, name );
- mlt_position in = mlt_properties_get_position( properties, "in" );
- mlt_position out = mlt_properties_get_position( properties, "out" );
- int mirror = mlt_properties_get_position( properties, "mirror" );
- int length = out - in + 1;
-
- // Obtain the normalised width and height from the a_frame
- int normalised_width = mlt_properties_get_int( a_props, "normalised_width" );
- int normalised_height = mlt_properties_get_int( a_props, "normalised_height" );
-
- double consumer_ar = mlt_properties_get_double( a_props, "consumer_aspect_ratio" ) ;
-
- // Structures for geometry
- struct mlt_geometry_item_s result;
-
- if ( mirror && position > length / 2 )
- position = abs( position - length );
-
- // Fetch the a frame image
- mlt_frame_get_image( a_frame, image, format, width, height, 1 );
-
- // Calculate the region now
- composite_calculate( this, &result, normalised_width, normalised_height, ( float )position );
-
- // Fetch the b frame image
- result.w = ( int )( result.w * *width / normalised_width );
- result.h = ( int )( result.h * *height / normalised_height );
- result.x = ( int )( result.x * *width / normalised_width );
- result.y = ( int )( result.y * *height / normalised_height );
- //result.w -= ( int )abs( result.w ) % 2;
- //result.x -= ( int )abs( result.x ) % 2;
- b_width = result.w;
- b_height = result.h;
-
- if ( mlt_properties_get_double( b_props, "aspect_ratio" ) == 0.0 )
- mlt_properties_set_double( b_props, "aspect_ratio", consumer_ar );
-
- if ( !strcmp( mlt_properties_get( a_props, "rescale.interp" ), "none" ) )
- {
- mlt_properties_set( b_props, "rescale.interp", "nearest" );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", consumer_ar );
- }
- else
- {
- mlt_properties_set( b_props, "rescale.interp", mlt_properties_get( a_props, "rescale.interp" ) );
- mlt_properties_set_double( b_props, "consumer_aspect_ratio", consumer_ar );
- }
-
- mlt_properties_set_int( b_props, "distort", mlt_properties_get_int( properties, "distort" ) );
- mlt_frame_get_image( b_frame, &b_image, &b_format, &b_width, &b_height, 0 );
- result.w = b_width;
- result.h = b_height;
-
- // Check that both images are of the correct format and process
- if ( *format == mlt_image_yuv422 && b_format == mlt_image_yuv422 )
- {
- register int x, y;
- register int dx, dy;
- double dz;
- float sw, sh;
-
- // Get values from the transition
- float scale_x = mlt_properties_get_double( properties, "scale_x" );
- float scale_y = mlt_properties_get_double( properties, "scale_y" );
- int scale = mlt_properties_get_int( properties, "scale" );
-
- uint8_t *p = *image;
- uint8_t *q = *image;
-
- int cx = result.x + ( b_width >> 1 );
- int cy = result.y + ( b_height >> 1 );
- cx -= cx % 2;
-
- int lower_x = 0 - cx;
- int upper_x = *width - cx;
- int lower_y = 0 - cy;
- int upper_y = *height - cy;
-
- int b_stride = b_width << 1;
- int a_stride = *width << 1;
- int x_offset = ( int )result.w >> 1;
- int y_offset = ( int )result.h >> 1;
-
- uint8_t *alpha = mlt_frame_get_alpha_mask( b_frame );
- uint8_t *mask = mlt_frame_get_alpha_mask( a_frame );
- uint8_t *pmask = mask;
- float mix;
-
- affine_t affine;
-
- get_affine( &affine, this, ( float )position );
-
- q = *image;
-
- dz = MapZ( affine.matrix, 0, 0 );
-
- if ( mask == NULL )
- {
- mask = mlt_pool_alloc( *width * *height );
- pmask = mask;
- memset( mask, 255, *width * *height );
- }
-
- if ( ( int )abs( dz * 1000 ) < 25 )
- goto getout;
-
- if ( scale )
- {
- affine_max_output( affine.matrix, &sw, &sh, dz );
- affine_scale( affine.matrix, sw, sh );
- }
- else if ( scale_x != 0 && scale_y != 0 )
- {
- affine_scale( affine.matrix, scale_x, scale_y );
- }
-
- if ( alpha == NULL )
- {
- for ( y = lower_y; y < upper_y; y ++ )
- {
- p = q;
-
- for ( x = lower_x; x < upper_x; x ++ )
- {
- dx = MapX( affine.matrix, x, y ) / dz + x_offset;
- dy = MapY( affine.matrix, x, y ) / dz + y_offset;
-
- if ( dx >= 0 && dx < b_width && dy >=0 && dy < b_height )
- {
- pmask ++;
- dx -= dx & 1;
- *p ++ = *( b_image + dy * b_stride + ( dx << 1 ) );
- *p ++ = *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 );
- }
- else
- {
- p += 2;
- pmask ++;
- }
- }
-
- q += a_stride;
- }
- }
- else
- {
- for ( y = lower_y; y < upper_y; y ++ )
- {
- p = q;
-
- for ( x = lower_x; x < upper_x; x ++ )
- {
- dx = MapX( affine.matrix, x, y ) / dz + x_offset;
- dy = MapY( affine.matrix, x, y ) / dz + y_offset;
-
- if ( dx >= 0 && dx < b_width && dy >=0 && dy < b_height )
- {
- *pmask ++ = *( alpha + dy * b_width + dx );
- mix = ( float )*( alpha + dy * b_width + dx ) / 255.0;
- dx -= dx & 1;
- *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) );
- p ++;
- *p = *p * ( 1 - mix ) + mix * *( b_image + dy * b_stride + ( dx << 1 ) + ( ( x & 1 ) << 1 ) + 1 );
- p ++;
- }
- else
- {
- p += 2;
- pmask ++;
- }
- }
-
- q += a_stride;
- }
- }
-
-getout:
- a_frame->get_alpha_mask = NULL;
- mlt_properties_set_data( a_props, "alpha", mask, 0, mlt_pool_release, NULL );
- }
-
- return 0;
-}
-
-/** Affine transition processing.
-*/
-
-static mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
-{
- // Get a unique name to store the frame position
- char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( transition ), "_unique_id" );
-
- // Assign the current position to the name
- mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
- mlt_properties_set_position( a_props, name, mlt_frame_get_position( a_frame ) );
-
- // Push the transition on to the frame
- mlt_frame_push_service( a_frame, transition );
-
- // Push the b_frame on to the stack
- mlt_frame_push_frame( a_frame, b_frame );
-
- // Push the transition method
- mlt_frame_push_get_image( a_frame, transition_get_image );
-
- return a_frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_transition transition_affine_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_transition transition = mlt_transition_new( );
- if ( transition != NULL )
- {
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "sx", 1 );
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "sy", 1 );
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "distort", 0 );
- mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "geometry", "0,0:100%x100%" );
- // Inform apps and framework that this is a video only transition
- mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 );
- transition->process = transition_process;
- }
- return transition;
-}
+++ /dev/null
-include ../../../config.mak
-include config.mak
-
-TARGET = ../libmltqimage$(LIBSUF)
-
-OBJS = factory.o producer_qimage.o
-CPPOBJS = qimage_wrapper.o
-
-CFLAGS += -I../..
-CXXFLAGS += $(CFLAGS) $(QTCXXFLAGS) -Wno-deprecated
-
-LDFLAGS = -L../../framework -lmlt
-LDFLAGS += $(QTLIBS)
-LDFLAGS += -lstdc++
-
-ifdef USE_KDE
-LDFLAGS += -lkio
-endif
-
-SRCS := $(OBJS:.o=.c) $(CPPOBJS:.o=.cpp)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS) $(CPPOBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(CPPOBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $(QTCXXFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend config.h config.mak
-
-clean:
- rm -f $(OBJS) $(TARGET) $(CPPOBJS)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" = "1" ]
-then
- cat << EOF
-QImage options:
-
- --force-qt3 - Force compile against Qt3 if Qt4 is present on the system
- --qimage-libdir - Location of QT lib directory [/usr/lib/qt4 or /usr/lib/qt3]
- --qimage-includedir - Location of QT include directory [/usr/include/qt4 or /usr/include/qt3]
- --kde-libdir - Location of KDE lib directory [/usr/lib]
- --kde-includedir - Location of KDE include directory [/usr/include/kde]
-
-EOF
-
-else
- targetos=$(uname -s)
- case $targetos in
- MINGW32*)
- export LIBSUF=.dll
- ;;
- Darwin)
- export LIBSUF=.dylib
- ;;
- Linux|FreeBSD)
- export LIBSUF=.so
- ;;
- *)
- ;;
- esac
-
- qimage_includedir=/usr/include/qt4
- qimage_libdir=/usr/lib/qt4
-
- if [ ! -d "$qimage_libdir" -o ! -d "$qimage_includedir" ]
- then
- qimage_includedir=/usr/include/qt3
- qimage_libdir=/usr/lib/qt3
- kde_includedir=/usr/include/kde
- kde_libdir=/usr/lib
- if [ "$KDEDIR" != "" ]
- then
- kde_includedir="$KDEDIR/include"
- kde_libdir="$KDEDIR"
- fi
- fi
-
- if [ "$QTDIR" != "" ]
- then
- qimage_includedir="$QTDIR/include"
- qimage_libdir="$QTDIR/lib"
- fi
-
- export force_qt3=
- export qt4_found=
-
- for i in "$@"
- do
- case $i in
- --qimage-libdir=* ) qimage_libdir="${i#--qimage-libdir=}" ;;
- --qimage-includedir=* ) qimage_includedir="${i#--qimage-includedir=}" ;;
- --kde-libdir=* ) kde_libdir="${i#--kde-libdir=}" ;;
- --kde-includedir=* ) kde_includedir="${i#--kde-includedir=}" ;;
- --force-qt3 ) force_qt3="true" ;;
- esac
- done
-
- pkg-config --exists 'QtGui >= 4'
- if [ $? -eq 0 ] && [ "$force_qt3" = "" ]
- then
- echo "Qt version 4.x detected, will compile Qt4 qimage producer"
- qt4_found=true
- echo "#define USE_QT4" > config.h
- echo "USE_QT4=1" > config.mak
- echo QTCXXFLAGS=$(pkg-config --cflags QtGui) >> config.mak
- echo QTLIBS=$(pkg-config --libs QtGui) >> config.mak
-
- elif [ -d "$qimage_libdir" -a -d "$qimage_includedir" ]
- then
-
- # test if we have a Qt3 or Qt4
- if [ -f "$qimage_libdir/libQtCore.so" ] || [ -d "$qimage_libdir/QtGui.framework" ] && [ "$force_qt3" = "" ]
- then
- echo "Qt version 4.x detected, will compile Qt4 qimage producer"
- qt4_found=true
- else
- echo "Qt version 3.x detected, will compile Qt3 qimage producer"
- fi
-
- echo "Include directory: " $qimage_includedir
-
- echo > config.h
- echo > config.mak
- if [ "$qt4_found" != "" ] && [ "$force_qt3" = "" ]
- then
- echo "#define USE_QT4" >> config.h
- echo "USE_QT4=1" >> config.mak
- if [ -d "$qimage_libdir/QtGui.framework" ]
- then
- echo QTCXXFLAGS=$(pkg-config --cflags QtGui) >> config.mak
- echo QTLIBS=$(pkg-config --libs QtGui) >> config.mak
- else
- echo QTCXXFLAGS=-I$qimage_includedir >> config.mak
- echo QTLIBS=-L$qimage_libdir -lQtGui >> config.mak
- fi
- else
- if [ -d "$kde_includedir" ]
- then
- echo "#define USE_KDE" >> config.h
- echo "USE_KDE=1" >> config.mak
- echo "#define USE_QT3" >> config.h
- echo "USE_QT3=1" >> config.mak
- echo QTCXXFLAGS=-I$qimage_includedir -I$kde_includedir -DQT_THREAD_SUPPORT >> config.mak
- echo QTLIBS=-L$qimage_libdir -L$kde_libdir/lib -lqt-mt >> config.mak
- else
- echo "qimage: KDE environment not found - disabling extra image formats"
- echo "#define USE_QT3" >> config.h
- echo "USE_QT3=1" >> config.mak
- echo QTCXXFLAGS=-I$qimage_includedir -DQT_THREAD_SUPPORT>> config.mak
- echo QTLIBS=-L$qimage_libdir -lqt-mt >> config.mak
- fi
- fi
- else
- echo "qimage: QT environment not found - disabling"
- touch ../disable-qimage
- fi
-
-fi
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2006 Visual Media
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_producer producer_qimage_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( producer_type, "qimage", producer_qimage_init );
-}
+++ /dev/null
-/*
- * producer_image.c -- a QT/QImage based producer for MLT
- * Copyright (C) 2006 Visual Media
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * NB: This module is designed to be functionally equivalent to the
- * gtk2 image loading module so it can be used as replacement.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_cache.h>
-#include "qimage_wrapper.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void load_filenames( producer_qimage this, mlt_properties producer_properties );
-static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_qimage_init( mlt_profile profile, mlt_service_type type, const char *id, char *filename )
-{
- producer_qimage this = calloc( sizeof( struct producer_qimage_s ), 1 );
- if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
- {
- mlt_producer producer = &this->parent;
-
- // Get the properties interface
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
-
- // Callback registration
-#ifdef USE_KDE
- init_qimage();
-#endif
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- // Set the default properties
- mlt_properties_set( properties, "resource", filename );
- mlt_properties_set_int( properties, "ttl", 25 );
- mlt_properties_set_int( properties, "aspect_ratio", 1 );
- mlt_properties_set_int( properties, "progressive", 1 );
-
- // Validate the resource
- if ( filename )
- load_filenames( this, properties );
- if ( this->count )
- {
- mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
- if ( frame )
- {
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
- pthread_mutex_init( &this->mutex, NULL );
- mlt_properties_set_data( frame_properties, "producer_qimage", this, 0, NULL, NULL );
- mlt_frame_set_position( frame, mlt_producer_position( producer ) );
- mlt_properties_set_position( frame_properties, "qimage_position", mlt_producer_position( producer ) );
- refresh_qimage( this, frame, 0, 0 );
- mlt_frame_close( frame );
- }
- }
- if ( this->current_width == 0 )
- {
- producer_close( producer );
- producer = NULL;
- }
- return producer;
- }
- free( this );
- return NULL;
-}
-
-static void load_filenames( producer_qimage this, mlt_properties producer_properties )
-{
- char *filename = mlt_properties_get( producer_properties, "resource" );
- this->filenames = mlt_properties_new( );
-
- // Read xml string
- if ( strstr( filename, "<svg" ) )
- {
- // Generate a temporary file for the svg
- char fullname[ 1024 ] = "/tmp/mlt.XXXXXX";
- int fd = mkstemp( fullname );
-
- if ( fd > -1 )
- {
- // Write the svg into the temp file
- ssize_t remaining_bytes;
- char *xml = filename;
-
- // Strip leading crap
- while ( xml[0] != '<' )
- xml++;
-
- remaining_bytes = strlen( xml );
- while ( remaining_bytes > 0 )
- remaining_bytes -= write( fd, xml + strlen( xml ) - remaining_bytes, remaining_bytes );
- close( fd );
-
- mlt_properties_set( this->filenames, "0", fullname );
-
- // Teehe - when the producer closes, delete the temp file and the space allo
- mlt_properties_set_data( producer_properties, "__temporary_file__", fullname, 0, ( mlt_destructor )unlink, NULL );
- }
- }
- // Obtain filenames
- else if ( strchr( filename, '%' ) != NULL )
- {
- // handle picture sequences
- int i = mlt_properties_get_int( producer_properties, "begin" );
- int gap = 0;
- char full[1024];
- int keyvalue = 0;
- char key[ 50 ];
-
- while ( gap < 100 )
- {
- struct stat buf;
- snprintf( full, 1023, filename, i ++ );
- if ( stat( full, &buf ) == 0 )
- {
- sprintf( key, "%d", keyvalue ++ );
- mlt_properties_set( this->filenames, key, full );
- gap = 0;
- }
- else
- {
- gap ++;
- }
- }
- }
- else if ( strstr( filename, "/.all." ) != NULL )
- {
- char wildcard[ 1024 ];
- char *dir_name = strdup( filename );
- char *extension = strrchr( dir_name, '.' );
-
- *( strstr( dir_name, "/.all." ) + 1 ) = '\0';
- sprintf( wildcard, "*%s", extension );
-
- mlt_properties_dir_list( this->filenames, dir_name, wildcard, 1 );
-
- free( dir_name );
- }
- else
- {
- mlt_properties_set( this->filenames, "0", filename );
- }
-
- this->count = mlt_properties_count( this->filenames );
-}
-
-static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer for this frame
- producer_qimage this = mlt_properties_get_data( properties, "producer_qimage", NULL );
-
- *width = mlt_properties_get_int( properties, "rescale_width" );
- *height = mlt_properties_get_int( properties, "rescale_height" );
-
- // Refresh the image
- refresh_qimage( this, frame, *width, *height );
-
- // We need to know the size of the image to clone it
- int image_size = this->current_width * ( this->current_height + 1 ) * 2;
- int alpha_size = this->current_width * this->current_height;
-
- // Get width and height (may have changed during the refresh)
- *width = mlt_properties_get_int( properties, "width" );
- *height = mlt_properties_get_int( properties, "height" );
-
- // NB: Cloning is necessary with this producer (due to processing of images ahead of use)
- // The fault is not in the design of mlt, but in the implementation of the qimage producer...
- if ( this->current_image != NULL )
- {
- if ( *format == mlt_image_yuv422 || *format == mlt_image_yuv420p )
- {
- // Clone the image and the alpha
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- uint8_t *alpha_copy = mlt_pool_alloc( alpha_size );
-
- memcpy( image_copy, this->current_image, image_size );
-
- // Copy or default the alpha
- if ( this->current_alpha )
- memcpy( alpha_copy, this->current_alpha, alpha_size );
- else
- memset( alpha_copy, 255, alpha_size );
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL );
-
- // We're going to pass the copy on
- *buffer = image_copy;
- }
- else if ( *format == mlt_image_rgb24a )
- {
- // Clone the image and the alpha
- image_size = *width * ( *height + 1 ) * 4;
- alpha_size = *width * ( *height + 1 );
- uint8_t *image_copy = mlt_pool_alloc( image_size );
- uint8_t *alpha_copy = mlt_pool_alloc( alpha_size );
-
- mlt_convert_yuv422_to_rgb24a(this->current_image, image_copy, (*width)*(*height));
-
- // Now update properties so we free the copy after
- mlt_properties_set_data( properties, "image", image_copy, image_size, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha_copy, alpha_size, mlt_pool_release, NULL );
-
- // We're going to pass the copy on
- *buffer = image_copy;
- }
- }
- else
- {
- // TODO: Review all cases of invalid images
- *buffer = mlt_pool_alloc( 50 * 50 * 2 );
- mlt_properties_set_data( properties, "image", *buffer, image_size, mlt_pool_release, NULL );
- *width = 50;
- *height = 50;
- }
-
- // Release references and locks
- pthread_mutex_unlock( &this->mutex );
- mlt_cache_item_close( this->image_cache );
- mlt_cache_item_close( this->alpha_cache );
-
- return 0;
-}
-
-static uint8_t *producer_get_alpha_mask( mlt_frame this )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-
- // Return the alpha mask
- return mlt_properties_get_data( properties, "alpha", NULL );
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Get the real structure for this producer
- producer_qimage this = producer->child;
-
- // Fetch the producers properties
- mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
-
- if ( this->filenames == NULL && mlt_properties_get( producer_properties, "resource" ) != NULL )
- load_filenames( this, producer_properties );
-
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- if ( *frame != NULL && this->count > 0 )
- {
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Set the producer on the frame properties
- mlt_properties_set_data( properties, "producer_qimage", this, 0, NULL, NULL );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Ensure that we have a way to obtain the position in the get_image
- mlt_properties_set_position( properties, "qimage_position", mlt_producer_position( producer ) );
-
- // Refresh the image
- refresh_qimage( this, *frame, 0, 0 );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_properties, "aspect_ratio" ) );
-
- // Set alpha call back
- ( *frame )->get_alpha_mask = producer_get_alpha_mask;
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- producer_qimage this = parent->child;
- pthread_mutex_destroy( &this->mutex );
- parent->close = NULL;
- mlt_producer_close( parent );
- mlt_properties_close( this->filenames );
- free( this );
-}
+++ /dev/null
-/*
- * qimage_wrapper.cpp -- a QT/QImage based producer for MLT
- * Copyright (C) 2006 Visual Media
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * NB: This module is designed to be functionally equivalent to the
- * gtk2 image loading module so it can be used as replacement.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "qimage_wrapper.h"
-
-#ifdef USE_QT3
-#include <qimage.h>
-#include <qmutex.h>
-
-#ifdef USE_KDE
-#include <kinstance.h>
-#include <kimageio.h>
-#endif
-
-#endif
-
-
-#ifdef USE_QT4
-#include <QtGui/QImage>
-#include <QtCore/QSysInfo>
-#include <QtCore/QMutex>
-#endif
-
-
-#include <cmath>
-
-extern "C" {
-
-#include <framework/mlt_pool.h>
-#include <framework/mlt_cache.h>
-
-#ifdef USE_KDE
-static KInstance *instance = 0L;
-#endif
-
-static void qimage_delete( void *data )
-{
- QImage *image = ( QImage * )data;
- delete image;
- image = NULL;
-#ifdef USE_KDE
- if (instance) delete instance;
- instance = 0L;
-#endif
-}
-
-static QMutex g_mutex;
-
-#ifdef USE_KDE
-void init_qimage()
-{
- if (!instance) {
- instance = new KInstance("qimage_prod");
- KImageIO::registerFormats();
- }
-}
-#endif
-
-void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int height )
-{
- // Obtain properties of frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the producer
- mlt_producer producer = &self->parent;
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // restore QImage
- pthread_mutex_lock( &self->mutex );
- mlt_cache_item qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
- QImage *qimage = static_cast<QImage*>( mlt_cache_item_data( qimage_cache, NULL ) );
-
- // restore scaled image
- self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
- self->current_image = static_cast<uint8_t*>( mlt_cache_item_data( self->image_cache, NULL ) );
-
- // restore alpha channel
- self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" );
- self->current_alpha = static_cast<uint8_t*>( mlt_cache_item_data( self->alpha_cache, NULL ) );
-
- // Check if user wants us to reload the image
- if ( mlt_properties_get_int( producer_props, "force_reload" ) )
- {
- qimage = NULL;
- self->current_image = NULL;
- mlt_properties_set_int( producer_props, "force_reload", 0 );
- }
-
- // Obtain the cache flag and structure
- int use_cache = mlt_properties_get_int( producer_props, "cache" );
- mlt_properties cache = ( mlt_properties )mlt_properties_get_data( producer_props, "_cache", NULL );
- int update_cache = 0;
-
- // Get the time to live for each frame
- double ttl = mlt_properties_get_int( producer_props, "ttl" );
-
- // Get the original position of this frame
- mlt_position position = mlt_properties_get_position( properties, "qimage_position" );
- position += mlt_producer_get_in( producer );
-
- // Image index
- int image_idx = ( int )floor( ( double )position / ttl ) % self->count;
-
- // Key for the cache
- char image_key[ 10 ];
- sprintf( image_key, "%d", image_idx );
-
- g_mutex.lock();
-
- // Check if the frame is already loaded
- if ( use_cache )
- {
- if ( cache == NULL )
- {
- cache = mlt_properties_new( );
- mlt_properties_set_data( producer_props, "_cache", cache, 0, ( mlt_destructor )mlt_properties_close, NULL );
- }
-
- mlt_frame cached = ( mlt_frame )mlt_properties_get_data( cache, image_key, NULL );
-
- if ( cached )
- {
- self->image_idx = image_idx;
- mlt_properties cached_props = MLT_FRAME_PROPERTIES( cached );
- self->current_width = mlt_properties_get_int( cached_props, "width" );
- self->current_height = mlt_properties_get_int( cached_props, "height" );
- mlt_properties_set_int( producer_props, "_real_width", mlt_properties_get_int( cached_props, "real_width" ) );
- mlt_properties_set_int( producer_props, "_real_height", mlt_properties_get_int( cached_props, "real_height" ) );
- self->current_image = ( uint8_t * )mlt_properties_get_data( cached_props, "image", NULL );
- self->current_alpha = ( uint8_t * )mlt_properties_get_data( cached_props, "alpha", NULL );
-
- if ( width != 0 && ( width != self->current_width || height != self->current_height ) )
- self->current_image = NULL;
- }
- }
-
- // optimization for subsequent iterations on single picture
- if ( width != 0 && ( image_idx != self->image_idx || width != self->current_width || height != self->current_height ) )
- self->current_image = NULL;
- if ( image_idx != self->image_idx )
- qimage = NULL;
- if ( qimage == NULL && ( width == 0 || self->current_image == NULL ) )
- {
- self->current_image = NULL;
- self->image_idx = image_idx;
- qimage = new QImage( mlt_properties_get_value( self->filenames, image_idx ) );
-
- if ( !qimage->isNull( ) )
- {
- // Store the width/height of the qimage
- self->current_width = qimage->width( );
- self->current_height = qimage->height( );
-
- // Register qimage for destruction and reuse
- mlt_cache_item_close( qimage_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage", qimage, 0, ( mlt_destructor )qimage_delete );
- qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
-
- mlt_events_block( producer_props, NULL );
- mlt_properties_set_int( producer_props, "_real_width", self->current_width );
- mlt_properties_set_int( producer_props, "_real_height", self->current_height );
- mlt_events_unblock( producer_props, NULL );
- }
- else
- {
- delete qimage;
- qimage = NULL;
- }
- }
-
- // If we have a pixbuf and this request specifies a valid dimension and we haven't already got a cached version...
- if ( qimage && width > 0 && self->current_image == NULL )
- {
- char *interps = mlt_properties_get( properties, "rescale.interp" );
- int interp = 0;
-
- // QImage has two scaling modes - we'll toggle between them here
- if ( strcmp( interps, "tiles" ) == 0 )
- interp = 1;
- else if ( strcmp( interps, "hyper" ) == 0 )
- interp = 1;
-
-#ifdef USE_QT4
- // Note - the original qimage is already safe and ready for destruction
- QImage scaled = interp == 0 ? qimage->scaled( QSize( width, height)) : qimage->scaled( QSize(width, height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- QImage temp;
- bool hasAlpha = scaled.hasAlphaChannel();
- if (hasAlpha)
- temp = scaled.convertToFormat(QImage::Format_ARGB32);
- else
- temp = scaled.convertToFormat(QImage::Format_RGB888);
-#endif
-
-#ifdef USE_QT3
- // Note - the original qimage is already safe and ready for destruction
- QImage scaled = interp == 0 ? qimage->scale( width, height, QImage::ScaleFree ) : qimage->smoothScale( width, height, QImage::ScaleFree );
- QImage temp = scaled.convertDepth( 32 );
- bool hasAlpha = true;
-#endif
-
- // Store width and height
- self->current_width = width;
- self->current_height = height;
-
- // Allocate/define image
- self->current_image = ( uint8_t * )mlt_pool_alloc( width * ( height + 1 ) * 2 );
- if ( !use_cache )
- mlt_cache_item_close( self->image_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.image", self->current_image, width * ( height + 1 ) * 2, mlt_pool_release );
- self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
-
- if (!hasAlpha) {
- mlt_convert_rgb24_to_yuv422( temp.bits(), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image );
- }
- else {
- // Allocate the alpha mask
- self->current_alpha = ( uint8_t * )mlt_pool_alloc( width * height );
- if ( !use_cache )
- mlt_cache_item_close( self->alpha_cache );
- mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha", self->current_alpha, width * height, mlt_pool_release );
- self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" );
-
-#ifdef USE_QT4
- if ( QSysInfo::ByteOrder == QSysInfo::BigEndian )
- mlt_convert_argb_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine(), self->current_image, self->current_alpha );
- else
- mlt_convert_bgr24a_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha );
-#endif
-
-#ifdef USE_QT3
- // Convert the image
- if ( QImage::systemByteOrder( ) == QImage::BigEndian )
- mlt_convert_argb_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha );
- else
- mlt_convert_bgr24a_to_yuv422( temp.bits( ), self->current_width, self->current_height, temp.bytesPerLine( ), self->current_image, self->current_alpha );
-#endif
- }
-
- // Ensure we update the cache when we need to
- update_cache = use_cache;
- }
-
- // release references no longer needed
- mlt_cache_item_close( qimage_cache );
- if ( width == 0 )
- {
- pthread_mutex_unlock( &self->mutex );
- mlt_cache_item_close( self->image_cache );
- mlt_cache_item_close( self->alpha_cache );
- }
-
- // Set width/height of frame
- mlt_properties_set_int( properties, "width", self->current_width );
- mlt_properties_set_int( properties, "height", self->current_height );
- mlt_properties_set_int( properties, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) );
- mlt_properties_set_int( properties, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) );
-
- if ( update_cache )
- {
- mlt_frame cached = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
- mlt_properties cached_props = MLT_FRAME_PROPERTIES( cached );
- mlt_properties_set_int( cached_props, "width", self->current_width );
- mlt_properties_set_int( cached_props, "height", self->current_height );
- mlt_properties_set_int( cached_props, "real_width", mlt_properties_get_int( producer_props, "_real_width" ) );
- mlt_properties_set_int( cached_props, "real_height", mlt_properties_get_int( producer_props, "_real_height" ) );
- mlt_properties_set_data( cached_props, "image", self->current_image, self->current_width * ( self->current_height + 1 ) * 2, mlt_pool_release, NULL );
- mlt_properties_set_data( cached_props, "alpha", self->current_alpha, self->current_width * self->current_height, mlt_pool_release, NULL );
- mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL );
- }
- g_mutex.unlock();
-}
-
-} // extern "C"
+++ /dev/null
-/*
- * qimage_wrapper.h -- a QT/QImage based producer for MLT
- * Copyright (C) 2006 Visual Media
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * NB: This module is designed to be functionally equivalent to the
- * gtk2 image loading module so it can be used as replacement.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef MLT_QIMAGE_WRAPPER
-#define MLT_QIMAGE_WRAPPER
-
-#include <framework/mlt.h>
-
-#include "config.h"
-#include <pthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct producer_qimage_s
-{
- struct mlt_producer_s parent;
- mlt_properties filenames;
- int count;
- int image_idx;
- uint8_t *current_image;
- uint8_t *current_alpha;
- int current_width;
- int current_height;
- mlt_cache_item image_cache;
- mlt_cache_item alpha_cache;
- pthread_mutex_t mutex;
-};
-
-typedef struct producer_qimage_s *producer_qimage;
-
-extern void refresh_qimage( producer_qimage, mlt_frame, int width, int height );
-#ifdef USE_KDE
-extern void init_qimage();
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltresample$(LIBSUF)
-
-OBJS = factory.o \
- filter_resample.o
-
-CFLAGS += -I../..
-CFLAGS += `pkg-config --cflags samplerate`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `pkg-config --libs samplerate`
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- pkg-config samplerate 2> /dev/null
- disable_samplerate=$?
-
- if [ "$disable_samplerate" != "0" ]
- then
- echo "- libsamplerate not found: disabling"
- touch ../disable-resample
- fi
- exit 0
-fi
-
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_resample_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "resample", filter_resample_init );
-}
+++ /dev/null
-/*
- * filter_resample.c -- adjust audio sample frequency
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <samplerate.h>
-#define __USE_ISOC99 1
-#include <math.h>
-
-#define BUFFER_LEN 20480
-#define RESAMPLE_TYPE SRC_SINC_FASTEST
-
-/** Get the audio.
-*/
-
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_audio( frame );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the resample information
- int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
- SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
- float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
- float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
- int channels_avail = *channels;
- SRC_DATA data;
- int i;
-
- // If no resample frequency is specified, default to requested value
- if ( output_rate == 0 )
- output_rate = *frequency;
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
- // Duplicate channels as necessary
- if ( channels_avail < *channels )
- {
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- int j, k = 0;
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
- k = ( k + 1 ) % channels_avail;
- }
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
- else if ( channels_avail == 6 && *channels == 2 )
- {
- // Nasty hack for ac3 5.1 audio - may be a cause of failure?
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- // Drop all but the first *channels
- for ( i = 0; i < *samples; i++ )
- {
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
-
- // Return now if no work to do
- if ( output_rate != *frequency )
- {
- float *p = input_buffer;
- float *end = p + *samples * *channels;
- int16_t *q = *buffer;
-
- // Convert to floating point
- while( p != end )
- *p ++ = ( float )( *q ++ ) / 32768.0;
-
- // Resample
- data.data_in = input_buffer;
- data.data_out = output_buffer;
- data.src_ratio = ( float ) output_rate / ( float ) *frequency;
- data.input_frames = *samples;
- data.output_frames = BUFFER_LEN / *channels;
- data.end_of_input = 0;
- i = src_process( state, &data );
- if ( i == 0 )
- {
- if ( data.output_frames_gen > *samples )
- {
- *buffer = mlt_pool_realloc( *buffer, data.output_frames_gen * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, mlt_pool_release, NULL );
- }
-
- *samples = data.output_frames_gen;
- *frequency = output_rate;
-
- p = output_buffer;
- q = *buffer;
- end = p + *samples * *channels;
-
- // Convert from floating back to signed 16bit
- while( p != end )
- {
- if ( *p > 1.0 )
- *p = 1.0;
- if ( *p < -1.0 )
- *p = -1.0;
- if ( *p > 0 )
- *q ++ = 32767 * *p ++;
- else
- *q ++ = 32768 * *p ++;
- }
- }
- else
- fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate );
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- if ( mlt_frame_is_test_audio( frame ) == 0 )
- {
- mlt_frame_push_audio( frame, this );
- mlt_frame_push_audio( frame, resample_get_audio );
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_resample_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- int error;
- SRC_STATE *state = src_new( RESAMPLE_TYPE, 2 /* channels */, &error );
- if ( error == 0 )
- {
- void *input_buffer = mlt_pool_alloc( BUFFER_LEN );
- void *output_buffer = mlt_pool_alloc( BUFFER_LEN );
- this->process = filter_process;
- if ( arg != NULL )
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "frequency", atoi( arg ) );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "state", state, 0, (mlt_destructor)src_delete, NULL );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "input_buffer", input_buffer, BUFFER_LEN, mlt_pool_release, NULL );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL );
- }
- else
- {
- fprintf( stderr, "filter_resample_init: %s\n", src_strerror( error ) );
- }
- }
- return this;
-}
+++ /dev/null
-include ../../../config.mak
-
-include config.mak
-
-TARGET = ../libmltsdl$(LIBSUF)
-
-OBJS = factory.o \
- consumer_sdl.o \
- consumer_sdl_preview.o \
- consumer_sdl_still.o
-
-ifeq ($(targetos),Darwin)
-CFLAGS += -ObjC
-LDFLAGS += -lobjc -framework Foundation
-else
-LDFLAGS += -lX11
-endif
-
-CFLAGS += -I../..
-CFLAGS += `sdl-config --cflags`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `sdl-config --libs`
-
-ifeq ($(WITH_SDL_IMAGE),1)
-OBJS += producer_sdl_image.o
-CFLAGS += -DWITH_SDL_IMAGE
-LDFLAGS += -lSDL_image
-endif
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- sdl-config --version > /dev/null 2>&1
- disable_sdl=$?
-
- if [ "$disable_sdl" = "0" ]
- then
- echo > config.mak
- image=`sdl-config --prefix`/include/SDL/SDL_image.h
- if [ -f "$image" ]
- then
- echo "WITH_SDL_IMAGE=1" >> config.mak
- fi
- else
- echo "- sdl development libs not found: disabling"
- touch ../disable-sdl
- fi
- exit 0
-fi
-
+++ /dev/null
-/*
- * consumer_sdl.c -- A Simple DirectMedia Layer consumer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_deque.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_filter.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <SDL/SDL.h>
-#include <SDL/SDL_syswm.h>
-#include <sys/time.h>
-
-/** This classes definition.
-*/
-
-typedef struct consumer_sdl_s *consumer_sdl;
-
-struct consumer_sdl_s
-{
- struct mlt_consumer_s parent;
- mlt_properties properties;
- mlt_deque queue;
- pthread_t thread;
- int joined;
- int running;
- uint8_t audio_buffer[ 4096 * 10 ];
- int audio_avail;
- pthread_mutex_t audio_mutex;
- pthread_cond_t audio_cond;
- pthread_mutex_t video_mutex;
- pthread_cond_t video_cond;
- int window_width;
- int window_height;
- int previous_width;
- int previous_height;
- int width;
- int height;
- int playing;
- int sdl_flags;
- SDL_Surface *sdl_screen;
- SDL_Overlay *sdl_overlay;
- SDL_Rect rect;
- uint8_t *buffer;
- int bpp;
- int filtered;
-};
-
-/** Forward references to static functions.
-*/
-
-static int consumer_start( mlt_consumer parent );
-static int consumer_stop( mlt_consumer parent );
-static int consumer_is_stopped( mlt_consumer parent );
-static void consumer_close( mlt_consumer parent );
-static void *consumer_thread( void * );
-static int consumer_get_dimensions( int *width, int *height );
-static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt_service this, void **args );
-
-/** This is what will be called by the factory - anything can be passed in
- via the argument, but keep it simple.
-*/
-
-mlt_consumer consumer_sdl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the consumer object
- consumer_sdl this = calloc( sizeof( struct consumer_sdl_s ), 1 );
-
- // If no malloc'd and consumer init ok
- if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
- {
- // Create the queue
- this->queue = mlt_deque_init( );
-
- // Get the parent consumer object
- mlt_consumer parent = &this->parent;
-
- // We have stuff to clean up, so override the close method
- parent->close = consumer_close;
-
- // get a handle on properties
- mlt_service service = MLT_CONSUMER_SERVICE( parent );
- this->properties = MLT_SERVICE_PROPERTIES( service );
-
- // Set the default volume
- mlt_properties_set_double( this->properties, "volume", 1.0 );
-
- // This is the initialisation of the consumer
- pthread_mutex_init( &this->audio_mutex, NULL );
- pthread_cond_init( &this->audio_cond, NULL);
- pthread_mutex_init( &this->video_mutex, NULL );
- pthread_cond_init( &this->video_cond, NULL);
-
- // Default scaler (for now we'll use nearest)
- mlt_properties_set( this->properties, "rescale", "nearest" );
-
- // Default buffer for low latency
- mlt_properties_set_int( this->properties, "buffer", 1 );
-
- // Default progressive true
- mlt_properties_set_int( this->properties, "progressive", 0 );
-
- // Default audio buffer
- mlt_properties_set_int( this->properties, "audio_buffer", 512 );
-
- // Ensure we don't join on a non-running object
- this->joined = 1;
-
- // process actual param
- if ( arg == NULL || sscanf( arg, "%dx%d", &this->width, &this->height ) != 2 )
- {
- this->width = mlt_properties_get_int( this->properties, "width" );
- this->height = mlt_properties_get_int( this->properties, "height" );
- }
-
- // Set the sdl flags
- this->sdl_flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_RESIZABLE | SDL_DOUBLEBUF;
-
- // Allow thread to be started/stopped
- parent->start = consumer_start;
- parent->stop = consumer_stop;
- parent->is_stopped = consumer_is_stopped;
-
- // Register specific events
- mlt_events_register( this->properties, "consumer-sdl-event", ( mlt_transmitter )consumer_sdl_event );
-
- // Return the consumer produced
- return parent;
- }
-
- // malloc or consumer init failed
- free( this );
-
- // Indicate failure
- return NULL;
-}
-
-static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( SDL_Event * )args[ 0 ] );
-}
-
-int consumer_start( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
-
- if ( !this->running )
- {
- int video_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "video_off" );
- int preview_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "preview_off" );
- int display_off = video_off | preview_off;
- int audio_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "audio_off" );
- int sdl_started = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "sdl_started" );
-
- consumer_stop( parent );
-
- this->running = 1;
- this->joined = 0;
-
- if ( mlt_properties_get_int( this->properties, "width" ) > 0 )
- this->width = mlt_properties_get_int( this->properties, "width" );
- if ( mlt_properties_get_int( this->properties, "height" ) > 0 )
- this->height = mlt_properties_get_int( this->properties, "height" );
-
- this->bpp = mlt_properties_get_int( this->properties, "bpp" );
-
- // Attach a colour space converter
- if ( preview_off && !this->filtered )
- {
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( parent ) );
- mlt_filter filter = mlt_factory_filter( profile, "avcolour_space", NULL );
- if ( filter )
- {
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "forced", mlt_image_yuv422 );
- mlt_service_attach( MLT_CONSUMER_SERVICE( parent ), filter );
- mlt_filter_close( filter );
- }
- this->filtered = 1;
- }
-
- if ( sdl_started == 0 && display_off == 0 )
- {
- if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 )
- {
- fprintf( stderr, "Failed to initialize SDL: %s\n", SDL_GetError() );
- return -1;
- }
-
- SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
- SDL_EnableUNICODE( 1 );
- }
- else if ( display_off == 0 )
- {
- this->sdl_screen = SDL_GetVideoSurface( );
- }
-
- if ( audio_off == 0 )
- SDL_InitSubSystem( SDL_INIT_AUDIO );
-
- // Default window size
- double display_ratio = mlt_properties_get_double( this->properties, "display_ratio" );
- this->window_width = ( double )this->height * display_ratio;
- this->window_height = this->height;
-
- if ( this->sdl_screen == NULL && display_off == 0 )
- {
- if ( mlt_properties_get_int( this->properties, "fullscreen" ) )
- {
- const SDL_VideoInfo *vi = SDL_GetVideoInfo();
- this->window_width = vi->current_w;
- this->window_height = vi->current_h;
- this->sdl_flags |= SDL_FULLSCREEN;
- SDL_ShowCursor( SDL_DISABLE );
- }
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
- }
-
- pthread_create( &this->thread, NULL, consumer_thread, this );
- }
-
- return 0;
-}
-
-int consumer_stop( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- if ( this->joined == 0 )
- {
- // Kill the thread and clean up
- this->joined = 1;
- this->running = 0;
- if ( this->thread )
- pthread_join( this->thread, NULL );
-
- // internal cleanup
- if ( this->sdl_overlay != NULL )
- SDL_FreeYUVOverlay( this->sdl_overlay );
- this->sdl_overlay = NULL;
-
- if ( !mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "audio_off" ) )
- {
- pthread_mutex_lock( &this->audio_mutex );
- pthread_cond_broadcast( &this->audio_cond );
- pthread_mutex_unlock( &this->audio_mutex );
- SDL_QuitSubSystem( SDL_INIT_AUDIO );
- }
-
- if ( mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "sdl_started" ) == 0 )
- SDL_Quit( );
-
- this->sdl_screen = NULL;
- }
-
- return 0;
-}
-
-int consumer_is_stopped( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
- return !this->running;
-}
-
-static int sdl_lock_display( )
-{
- SDL_Surface *screen = SDL_GetVideoSurface( );
- return screen != NULL && ( !SDL_MUSTLOCK( screen ) || SDL_LockSurface( screen ) >= 0 );
-}
-
-static void sdl_unlock_display( )
-{
- SDL_Surface *screen = SDL_GetVideoSurface( );
- if ( screen != NULL && SDL_MUSTLOCK( screen ) )
- SDL_UnlockSurface( screen );
-}
-
-static void sdl_fill_audio( void *udata, uint8_t *stream, int len )
-{
- consumer_sdl this = udata;
-
- // Get the volume
- double volume = mlt_properties_get_double( this->properties, "volume" );
-
- pthread_mutex_lock( &this->audio_mutex );
-
- // Block until audio received
- while ( this->running && len > this->audio_avail )
- pthread_cond_wait( &this->audio_cond, &this->audio_mutex );
-
- if ( this->audio_avail >= len )
- {
- // Place in the audio buffer
- if ( volume != 1.0 )
- SDL_MixAudio( stream, this->audio_buffer, len, ( int )( ( float )SDL_MIX_MAXVOLUME * volume ) );
- else
- memcpy( stream, this->audio_buffer, len );
-
- // Remove len from the audio available
- this->audio_avail -= len;
-
- // Remove the samples
- memmove( this->audio_buffer, this->audio_buffer + len, this->audio_avail );
- }
- else
- {
- // Just to be safe, wipe the stream first
- memset( stream, 0, len );
-
- // Mix the audio
- SDL_MixAudio( stream, this->audio_buffer, len, ( int )( ( float )SDL_MIX_MAXVOLUME * volume ) );
-
- // No audio left
- this->audio_avail = 0;
- }
-
- // We're definitely playing now
- this->playing = 1;
-
- pthread_cond_broadcast( &this->audio_cond );
- pthread_mutex_unlock( &this->audio_mutex );
-}
-
-static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_audio, int *duration )
-{
- // Get the properties of this consumer
- mlt_properties properties = this->properties;
- mlt_audio_format afmt = mlt_audio_pcm;
-
- // Set the preferred params of the test card signal
- int channels = mlt_properties_get_int( properties, "channels" );
- int frequency = mlt_properties_get_int( properties, "frequency" );
- static int counter = 0;
-
- int samples = mlt_sample_calculator( mlt_properties_get_double( this->properties, "fps" ), frequency, counter++ );
-
- int16_t *pcm;
- int bytes;
-
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
- *duration = ( ( samples * 1000 ) / frequency );
-
- if ( mlt_properties_get_int( properties, "audio_off" ) )
- {
- this->playing = 1;
- init_audio = 1;
- return init_audio;
- }
-
- if ( init_audio == 1 )
- {
- SDL_AudioSpec request;
- SDL_AudioSpec got;
-
- int audio_buffer = mlt_properties_get_int( properties, "audio_buffer" );
-
- // specify audio format
- memset( &request, 0, sizeof( SDL_AudioSpec ) );
- this->playing = 0;
- request.freq = frequency;
- request.format = AUDIO_S16SYS;
- request.channels = channels;
- request.samples = audio_buffer;
- request.callback = sdl_fill_audio;
- request.userdata = (void *)this;
- if ( SDL_OpenAudio( &request, &got ) != 0 )
- {
- fprintf( stderr, "SDL failed to open audio: %s\n", SDL_GetError() );
- init_audio = 2;
- }
- else if ( got.size != 0 )
- {
- SDL_PauseAudio( 0 );
- init_audio = 0;
- }
- }
-
- if ( init_audio == 0 )
- {
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- bytes = ( samples * channels * 2 );
- pthread_mutex_lock( &this->audio_mutex );
- while ( this->running && bytes > ( sizeof( this->audio_buffer) - this->audio_avail ) )
- pthread_cond_wait( &this->audio_cond, &this->audio_mutex );
- if ( this->running )
- {
- if ( mlt_properties_get_double( properties, "_speed" ) == 1 )
- memcpy( &this->audio_buffer[ this->audio_avail ], pcm, bytes );
- else
- memset( &this->audio_buffer[ this->audio_avail ], 0, bytes );
- this->audio_avail += bytes;
- }
- pthread_cond_broadcast( &this->audio_cond );
- pthread_mutex_unlock( &this->audio_mutex );
- }
- else
- {
- this->playing = 1;
- }
-
- return init_audio;
-}
-
-static int consumer_play_video( consumer_sdl this, mlt_frame frame )
-{
- // Get the properties of this consumer
- mlt_properties properties = this->properties;
-
- mlt_image_format vfmt = mlt_image_yuv422;
- int width = this->width, height = this->height;
- uint8_t *image;
- int changed = 0;
-
- int video_off = mlt_properties_get_int( properties, "video_off" );
- int preview_off = mlt_properties_get_int( properties, "preview_off" );
- mlt_image_format preview_format = mlt_properties_get_int( properties, "preview_format" );
- int display_off = video_off | preview_off;
-
- if ( this->running && display_off == 0 )
- {
- // Get the image, width and height
- mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "format", vfmt );
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
-
- // Handle events
- if ( this->sdl_screen != NULL )
- {
- SDL_Event event;
-
- sdl_lock_display( );
- changed = consumer_get_dimensions( &this->window_width, &this->window_height );
- sdl_unlock_display( );
-
- while ( SDL_PollEvent( &event ) )
- {
- mlt_events_fire( this->properties, "consumer-sdl-event", &event, NULL );
-
- switch( event.type )
- {
- case SDL_VIDEORESIZE:
- this->window_width = event.resize.w;
- this->window_height = event.resize.h;
- changed = 1;
- break;
- case SDL_QUIT:
- this->running = 0;
- break;
- case SDL_KEYDOWN:
- {
- mlt_producer producer = mlt_properties_get_data( properties, "transport_producer", NULL );
- char keyboard[ 2 ] = " ";
- void (*callback)( mlt_producer, char * ) = mlt_properties_get_data( properties, "transport_callback", NULL );
- if ( callback != NULL && producer != NULL && event.key.keysym.unicode < 0x80 && event.key.keysym.unicode > 0 )
- {
- keyboard[ 0 ] = ( char )event.key.keysym.unicode;
- callback( producer, keyboard );
- }
- }
- break;
- }
- }
- }
-
- sdl_lock_display();
-
- if ( width != this->width || height != this->height )
- {
- if ( this->sdl_overlay != NULL )
- SDL_FreeYUVOverlay( this->sdl_overlay );
- this->sdl_overlay = NULL;
- }
-
- if ( this->running && ( this->sdl_screen == NULL || changed ) )
- {
- // Force an overlay recreation
- if ( this->sdl_overlay != NULL )
- SDL_FreeYUVOverlay( this->sdl_overlay );
- this->sdl_overlay = NULL;
-
- // open SDL window with video overlay, if possible
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
- if ( consumer_get_dimensions( &this->window_width, &this->window_height ) )
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
-
- uint32_t color = mlt_properties_get_int( this->properties, "window_background" );
- SDL_FillRect( this->sdl_screen, NULL, color >> 8 );
- SDL_Flip( this->sdl_screen );
- }
-
- if ( this->running )
- {
- // Determine window's new display aspect ratio
- double this_aspect = ( double )this->window_width / this->window_height;
-
- // Get the display aspect ratio
- double display_ratio = mlt_properties_get_double( properties, "display_ratio" );
-
- // Determine frame's display aspect ratio
- double frame_aspect = mlt_frame_get_aspect_ratio( frame ) * width / height;
-
- // Store the width and height received
- this->width = width;
- this->height = height;
-
- // If using hardware scaler
- if ( mlt_properties_get( properties, "rescale" ) != NULL &&
- !strcmp( mlt_properties_get( properties, "rescale" ), "none" ) )
- {
- // Use hardware scaler to normalise display aspect ratio
- this->rect.w = frame_aspect / this_aspect * this->window_width;
- this->rect.h = this->window_height;
- if ( this->rect.w > this->window_width )
- {
- this->rect.w = this->window_width;
- this->rect.h = this_aspect / frame_aspect * this->window_height;
- }
- }
- // Special case optimisation to negate odd effect of sample aspect ratio
- // not corresponding exactly with image resolution.
- else if ( (int)( this_aspect * 1000 ) == (int)( display_ratio * 1000 ) )
- {
- this->rect.w = this->window_width;
- this->rect.h = this->window_height;
- }
- // Use hardware scaler to normalise sample aspect ratio
- else if ( this->window_height * display_ratio > this->window_width )
- {
- this->rect.w = this->window_width;
- this->rect.h = this->window_width / display_ratio;
- }
- else
- {
- this->rect.w = this->window_height * display_ratio;
- this->rect.h = this->window_height;
- }
-
- this->rect.x = ( this->window_width - this->rect.w ) / 2;
- this->rect.y = ( this->window_height - this->rect.h ) / 2;
- this->rect.x -= this->rect.x % 2;
-
- mlt_properties_set_int( this->properties, "rect_x", this->rect.x );
- mlt_properties_set_int( this->properties, "rect_y", this->rect.y );
- mlt_properties_set_int( this->properties, "rect_w", this->rect.w );
- mlt_properties_set_int( this->properties, "rect_h", this->rect.h );
-
- SDL_SetClipRect( this->sdl_screen, &this->rect );
- }
-
- if ( this->running && this->sdl_screen != NULL && this->sdl_overlay == NULL )
- {
- SDL_SetClipRect( this->sdl_screen, &this->rect );
- this->sdl_overlay = SDL_CreateYUVOverlay( width, height, SDL_YUY2_OVERLAY, this->sdl_screen );
- }
-
- if ( this->running && this->sdl_screen != NULL && this->sdl_overlay != NULL )
- {
- this->buffer = this->sdl_overlay->pixels[ 0 ];
- if ( SDL_LockYUVOverlay( this->sdl_overlay ) >= 0 )
- {
- if ( image != NULL )
- memcpy( this->buffer, image, width * height * 2 );
- SDL_UnlockYUVOverlay( this->sdl_overlay );
- SDL_DisplayYUVOverlay( this->sdl_overlay, &this->sdl_screen->clip_rect );
- }
- }
-
- sdl_unlock_display();
- }
- else if ( this->running )
- {
- vfmt = preview_format == mlt_image_none ? mlt_image_rgb24a : preview_format;
- if ( !video_off )
- mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "format", vfmt );
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
- }
-
- return 0;
-}
-
-static void *video_thread( void *arg )
-{
- // Identify the arg
- consumer_sdl this = arg;
-
- // Obtain time of thread start
- struct timeval now;
- int64_t start = 0;
- int64_t elapsed = 0;
- struct timespec tm;
- mlt_frame next = NULL;
- mlt_properties properties = NULL;
- double speed = 0;
-
- // Get real time flag
- int real_time = mlt_properties_get_int( this->properties, "real_time" );
-
- // Get the current time
- gettimeofday( &now, NULL );
-
- // Determine start time
- start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
-
- while ( this->running )
- {
- // Pop the next frame
- pthread_mutex_lock( &this->video_mutex );
- next = mlt_deque_pop_front( this->queue );
- while ( next == NULL && this->running )
- {
- pthread_cond_wait( &this->video_cond, &this->video_mutex );
- next = mlt_deque_pop_front( this->queue );
- }
- pthread_mutex_unlock( &this->video_mutex );
-
- if ( !this->running || next == NULL ) break;
-
- // Get the properties
- properties = MLT_FRAME_PROPERTIES( next );
-
- // Get the speed of the frame
- speed = mlt_properties_get_double( properties, "_speed" );
-
- // Get the current time
- gettimeofday( &now, NULL );
-
- // Get the elapsed time
- elapsed = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - start;
-
- // See if we have to delay the display of the current frame
- if ( mlt_properties_get_int( properties, "rendered" ) == 1 && this->running )
- {
- // Obtain the scheduled playout time
- int64_t scheduled = mlt_properties_get_int( properties, "playtime" );
-
- // Determine the difference between the elapsed time and the scheduled playout time
- int64_t difference = scheduled - elapsed;
-
- // Smooth playback a bit
- if ( real_time && ( difference > 20000 && speed == 1.0 ) )
- {
- tm.tv_sec = difference / 1000000;
- tm.tv_nsec = ( difference % 1000000 ) * 500;
- nanosleep( &tm, NULL );
- }
-
- // Show current frame if not too old
- if ( !real_time || ( difference > -10000 || speed != 1.0 || mlt_deque_count( this->queue ) < 2 ) )
- consumer_play_video( this, next );
-
- // If the queue is empty, recalculate start to allow build up again
- if ( real_time && ( mlt_deque_count( this->queue ) == 0 && speed == 1.0 ) )
- {
- gettimeofday( &now, NULL );
- start = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - scheduled + 20000;
- }
- }
-
- // This frame can now be closed
- mlt_frame_close( next );
- next = NULL;
- }
-
- if ( next != NULL )
- mlt_frame_close( next );
-
- mlt_consumer_stopped( &this->parent );
-
- return NULL;
-}
-
-/** Threaded wrapper for pipe.
-*/
-
-static void *consumer_thread( void *arg )
-{
- // Identify the arg
- consumer_sdl this = arg;
-
- // Get the consumer
- mlt_consumer consumer = &this->parent;
-
- // Convenience functionality
- int terminate_on_pause = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "terminate_on_pause" );
- int terminated = 0;
-
- // Video thread
- pthread_t thread;
-
- // internal intialization
- int init_audio = 1;
- int init_video = 1;
- mlt_frame frame = NULL;
- mlt_properties properties = NULL;
- int duration = 0;
- int64_t playtime = 0;
- struct timespec tm = { 0, 100000 };
-
- // Loop until told not to
- while( !terminated && this->running )
- {
- // Get a frame from the attached producer
- frame = mlt_consumer_rt_frame( consumer );
-
- // Check for termination
- if ( terminate_on_pause && frame != NULL )
- terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;
-
- // Ensure that we have a frame
- if ( frame != NULL )
- {
- // Get the frame properties
- properties = MLT_FRAME_PROPERTIES( frame );
-
- // Play audio
- init_audio = consumer_play_audio( this, frame, init_audio, &duration );
-
- // Determine the start time now
- if ( this->playing && init_video )
- {
- // Create the video thread
- pthread_create( &thread, NULL, video_thread, this );
-
- // Video doesn't need to be initialised any more
- init_video = 0;
- }
-
- // Set playtime for this frame
- mlt_properties_set_int( properties, "playtime", playtime );
-
- while ( this->running && mlt_deque_count( this->queue ) > 15 )
- nanosleep( &tm, NULL );
-
- // Push this frame to the back of the queue
- pthread_mutex_lock( &this->video_mutex );
- mlt_deque_push_back( this->queue, frame );
- pthread_cond_broadcast( &this->video_cond );
- pthread_mutex_unlock( &this->video_mutex );
-
- // Calculate the next playtime
- playtime += ( duration * 1000 );
- }
- }
-
- this->running = 0;
-
- // Kill the video thread
- if ( init_video == 0 )
- {
- pthread_mutex_lock( &this->video_mutex );
- pthread_cond_broadcast( &this->video_cond );
- pthread_mutex_unlock( &this->video_mutex );
- pthread_join( thread, NULL );
- }
-
- while( mlt_deque_count( this->queue ) )
- mlt_frame_close( mlt_deque_pop_back( this->queue ) );
-
- this->sdl_screen = NULL;
- this->audio_avail = 0;
-
- return NULL;
-}
-
-static int consumer_get_dimensions( int *width, int *height )
-{
- int changed = 0;
-
- // SDL windows manager structure
- SDL_SysWMinfo wm;
-
- // Specify the SDL Version
- SDL_VERSION( &wm.version );
-
- // Lock the display
- //sdl_lock_display();
-
-#ifndef __DARWIN__
- // Get the wm structure
- if ( SDL_GetWMInfo( &wm ) == 1 )
- {
- // Check that we have the X11 wm
- if ( wm.subsystem == SDL_SYSWM_X11 )
- {
- // Get the SDL window
- Window window = wm.info.x11.window;
-
- // Get the display session
- Display *display = wm.info.x11.display;
-
- // Get the window attributes
- XWindowAttributes attr;
- XGetWindowAttributes( display, window, &attr );
-
- // Determine whether window has changed
- changed = *width != attr.width || *height != attr.height;
-
- // Return width and height
- *width = attr.width;
- *height = attr.height;
- }
- }
-#endif
-
- // Unlock the display
- //sdl_unlock_display();
-
- return changed;
-}
-
-/** Callback to allow override of the close method.
-*/
-
-static void consumer_close( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- // Stop the consumer
- ///mlt_consumer_stop( parent );
-
- // Now clean up the rest
- mlt_consumer_close( parent );
-
- // Close the queue
- mlt_deque_close( this->queue );
-
- // Destroy mutexes
- pthread_mutex_destroy( &this->audio_mutex );
- pthread_cond_destroy( &this->audio_cond );
-
- // Finally clean up this
- free( this );
-}
+++ /dev/null
-/*
- * Purpose: A dummy thread object to inform Cocoa that it needs to be thread safe.
- * Author: Zachary Drew
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#import <Foundation/Foundation.h>
-
-@interface DummyThread : NSObject
-- init;
-- (void)startThread:(id)arg;
-@end
-
-@implementation DummyThread
-- init
-{
- [super init];
- return self;
-}
-- (void)startThread:(id)arg
-{
- return;
-}
-@end
+++ /dev/null
-/*
- * consumer_sdl_preview.c -- A Simple DirectMedia Layer consumer
- * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
- * Author: Charles Yates
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_producer.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <SDL/SDL.h>
-#include <SDL/SDL_syswm.h>
-
-typedef struct consumer_sdl_s *consumer_sdl;
-
-struct consumer_sdl_s
-{
- struct mlt_consumer_s parent;
- mlt_consumer active;
- int ignore_change;
- mlt_consumer play;
- mlt_consumer still;
- pthread_t thread;
- int joined;
- int running;
- int sdl_flags;
- double last_speed;
-
- pthread_cond_t refresh_cond;
- pthread_mutex_t refresh_mutex;
- int refresh_count;
-};
-
-/** Forward references to static functions.
-*/
-
-static int consumer_start( mlt_consumer parent );
-static int consumer_stop( mlt_consumer parent );
-static int consumer_is_stopped( mlt_consumer parent );
-static void consumer_close( mlt_consumer parent );
-static void *consumer_thread( void * );
-static void consumer_frame_show_cb( mlt_consumer sdl, mlt_consumer this, mlt_frame frame );
-static void consumer_sdl_event_cb( mlt_consumer sdl, mlt_consumer this, SDL_Event *event );
-static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer this, char *name );
-
-mlt_consumer consumer_sdl_preview_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- consumer_sdl this = calloc( sizeof( struct consumer_sdl_s ), 1 );
- if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
- {
- // Get the parent consumer object
- mlt_consumer parent = &this->parent;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( parent );
-
- // Get the width and height
- int width = mlt_properties_get_int( properties, "width" );
- int height = mlt_properties_get_int( properties, "height" );
-
- // Process actual param
- if ( arg == NULL || sscanf( arg, "%dx%d", &width, &height ) == 2 )
- {
- mlt_properties_set_int( properties, "width", width );
- mlt_properties_set_int( properties, "height", height );
- }
-
- // Create child consumers
- this->play = mlt_factory_consumer( profile, "sdl", arg );
- this->still = mlt_factory_consumer( profile, "sdl_still", arg );
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( parent ), "real_time", "0" );
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( parent ), "rescale", "nearest" );
- parent->close = consumer_close;
- parent->start = consumer_start;
- parent->stop = consumer_stop;
- parent->is_stopped = consumer_is_stopped;
- this->joined = 1;
- mlt_events_listen( MLT_CONSUMER_PROPERTIES( this->play ), this, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb );
- mlt_events_listen( MLT_CONSUMER_PROPERTIES( this->still ), this, "consumer-frame-show", ( mlt_listener )consumer_frame_show_cb );
- mlt_events_listen( MLT_CONSUMER_PROPERTIES( this->play ), this, "consumer-sdl-event", ( mlt_listener )consumer_sdl_event_cb );
- mlt_events_listen( MLT_CONSUMER_PROPERTIES( this->still ), this, "consumer-sdl-event", ( mlt_listener )consumer_sdl_event_cb );
- pthread_cond_init( &this->refresh_cond, NULL );
- pthread_mutex_init( &this->refresh_mutex, NULL );
- mlt_events_listen( MLT_CONSUMER_PROPERTIES( parent ), this, "property-changed", ( mlt_listener )consumer_refresh_cb );
- return parent;
- }
- free( this );
- return NULL;
-}
-
-void consumer_frame_show_cb( mlt_consumer sdl, mlt_consumer parent, mlt_frame frame )
-{
- consumer_sdl this = parent->child;
- this->last_speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" );
- mlt_events_fire( MLT_CONSUMER_PROPERTIES( parent ), "consumer-frame-show", frame, NULL );
-}
-
-static void consumer_sdl_event_cb( mlt_consumer sdl, mlt_consumer parent, SDL_Event *event )
-{
- mlt_events_fire( MLT_CONSUMER_PROPERTIES( parent ), "consumer-sdl-event", event, NULL );
-}
-
-static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer parent, char *name )
-{
- if ( !strcmp( name, "refresh" ) )
- {
- consumer_sdl this = parent->child;
- pthread_mutex_lock( &this->refresh_mutex );
- this->refresh_count = this->refresh_count <= 0 ? 1 : this->refresh_count ++;
- pthread_cond_broadcast( &this->refresh_cond );
- pthread_mutex_unlock( &this->refresh_mutex );
- }
-}
-
-static int consumer_start( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
-
- if ( !this->running )
- {
- // properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( parent );
- mlt_properties play = MLT_CONSUMER_PROPERTIES( this->play );
- mlt_properties still = MLT_CONSUMER_PROPERTIES( this->still );
-
- char *window_id = mlt_properties_get( properties, "window_id" );
- char *audio_driver = mlt_properties_get( properties, "audio_driver" );
- char *video_driver = mlt_properties_get( properties, "video_driver" );
- char *audio_device = mlt_properties_get( properties, "audio_device" );
- char *output_display = mlt_properties_get( properties, "output_display" );
- int progressive = mlt_properties_get_int( properties, "progressive" ) | mlt_properties_get_int( properties, "deinterlace" );
-
- consumer_stop( parent );
-
- this->running = 1;
- this->joined = 0;
- this->last_speed = 1;
-
- if ( output_display != NULL )
- setenv( "DISPLAY", output_display, 1 );
-
- if ( window_id != NULL )
- setenv( "SDL_WINDOWID", window_id, 1 );
-
- if ( video_driver != NULL )
- setenv( "SDL_VIDEODRIVER", video_driver, 1 );
-
- if ( audio_driver != NULL )
- setenv( "SDL_AUDIODRIVER", audio_driver, 1 );
-
- if ( audio_device != NULL )
- setenv( "AUDIODEV", audio_device, 1 );
-
- if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 )
- {
- fprintf( stderr, "Failed to initialize SDL: %s\n", SDL_GetError() );
- return -1;
- }
-
- SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
- SDL_EnableUNICODE( 1 );
-
- // Pass properties down
- mlt_properties_set_data( play, "transport_producer", mlt_properties_get_data( properties, "transport_producer", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( still, "transport_producer", mlt_properties_get_data( properties, "transport_producer", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( play, "transport_callback", mlt_properties_get_data( properties, "transport_callback", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( still, "transport_callback", mlt_properties_get_data( properties, "transport_callback", NULL ), 0, NULL, NULL );
-
- mlt_properties_set_int( play, "progressive", progressive );
- mlt_properties_set_int( still, "progressive", progressive );
-
- mlt_properties_pass_list( play, properties, "resize,rescale,width,height,aspect_ratio,display_ratio,volume" );
- mlt_properties_pass_list( still, properties, "resize,rescale,width,height,aspect_ratio,display_ratio" );
- mlt_properties_pass_list( play, properties, "deinterlace_method" );
- mlt_properties_pass_list( still, properties, "deinterlace_method" );
- mlt_properties_pass_list( play, properties, "preview_off,preview_format,window_background" );
- mlt_properties_pass_list( still, properties, "preview_off,preview_format,window_background" );
-
- mlt_properties_pass( play, properties, "play." );
- mlt_properties_pass( still, properties, "still." );
-
- mlt_properties_set_data( play, "app_lock", mlt_properties_get_data( properties, "app_lock", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( still, "app_lock", mlt_properties_get_data( properties, "app_lock", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( play, "app_unlock", mlt_properties_get_data( properties, "app_unlock", NULL ), 0, NULL, NULL );
- mlt_properties_set_data( still, "app_unlock", mlt_properties_get_data( properties, "app_unlock", NULL ), 0, NULL, NULL );
-
- mlt_properties_set_int( play, "put_mode", 1 );
- mlt_properties_set_int( still, "put_mode", 1 );
-
- // Start the still producer just to initialise the gui
- mlt_consumer_start( this->still );
- this->active = this->still;
-
- // Inform child consumers that we control the sdl
- mlt_properties_set_int( play, "sdl_started", 1 );
- mlt_properties_set_int( still, "sdl_started", 1 );
-
- pthread_create( &this->thread, NULL, consumer_thread, this );
- }
-
- return 0;
-}
-
-static int consumer_stop( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- if ( this->joined == 0 )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( parent );
- int app_locked = mlt_properties_get_int( properties, "app_locked" );
- void ( *lock )( void ) = mlt_properties_get_data( properties, "app_lock", NULL );
- void ( *unlock )( void ) = mlt_properties_get_data( properties, "app_unlock", NULL );
-
- if ( app_locked && unlock ) unlock( );
-
- // Kill the thread and clean up
- this->running = 0;
-
- pthread_mutex_lock( &this->refresh_mutex );
- pthread_cond_broadcast( &this->refresh_cond );
- pthread_mutex_unlock( &this->refresh_mutex );
-
- pthread_join( this->thread, NULL );
- this->joined = 1;
-
- if ( app_locked && lock ) lock( );
-
- SDL_Quit( );
- }
-
- return 0;
-}
-
-static int consumer_is_stopped( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
- return !this->running;
-}
-
-static void *consumer_thread( void *arg )
-{
- // Identify the arg
- consumer_sdl this = arg;
-
- // Get the consumer
- mlt_consumer consumer = &this->parent;
-
- // Get the properties
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
-
- // internal intialization
- int first = 1;
- mlt_frame frame = NULL;
- int last_position = -1;
-
- // Determine if the application is dealing with the preview
- int preview_off = mlt_properties_get_int( properties, "preview_off" );
-
- this->refresh_count = 0;
-
- // Loop until told not to
- while( this->running )
- {
- // Get a frame from the attached producer
- frame = mlt_consumer_get_frame( consumer );
-
- // Ensure that we have a frame
- if ( this->running && frame != NULL )
- {
- // Get the speed of the frame
- double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" );
-
- // Lock during the operation
- mlt_service_lock( MLT_CONSUMER_SERVICE( consumer ) );
-
- // Get refresh request for the current frame
- int refresh = mlt_properties_get_int( properties, "refresh" );
-
- // Decrement refresh and clear changed
- mlt_events_block( properties, properties );
- mlt_properties_set_int( properties, "refresh", 0 );
- mlt_events_unblock( properties, properties );
-
- // Unlock after the operation
- mlt_service_unlock( MLT_CONSUMER_SERVICE( consumer ) );
-
- // Set the changed property on this frame for the benefit of still
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "refresh", refresh );
-
- // Make sure the recipient knows that this frame isn't really rendered
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "rendered", 0 );
-
- // Optimisation to reduce latency
- if ( speed == 1.0 )
- {
- if ( last_position != -1 && last_position + 1 != mlt_frame_get_position( frame ) )
- mlt_consumer_purge( this->play );
- last_position = mlt_frame_get_position( frame );
- }
- else
- {
- //mlt_consumer_purge( this->play );
- last_position = -1;
- }
-
- // If we're not the first frame and both consumers are stopped, then stop ourselves
- if ( !first && mlt_consumer_is_stopped( this->play ) && mlt_consumer_is_stopped( this->still ) )
- {
- this->running = 0;
- mlt_frame_close( frame );
- }
- // Allow a little grace time before switching consumers on speed changes
- else if ( this->ignore_change -- > 0 && this->active != NULL && !mlt_consumer_is_stopped( this->active ) )
- {
- mlt_consumer_put_frame( this->active, frame );
- }
- // If we aren't playing normally, then use the still
- else if ( speed != 1 )
- {
- if ( !mlt_consumer_is_stopped( this->play ) )
- mlt_consumer_stop( this->play );
- if ( mlt_consumer_is_stopped( this->still ) )
- {
- this->last_speed = speed;
- this->active = this->still;
- this->ignore_change = 0;
- mlt_consumer_start( this->still );
- }
- mlt_consumer_put_frame( this->still, frame );
- }
- // Otherwise use the normal player
- else
- {
- if ( !mlt_consumer_is_stopped( this->still ) )
- mlt_consumer_stop( this->still );
- if ( mlt_consumer_is_stopped( this->play ) )
- {
- this->last_speed = speed;
- this->active = this->play;
- this->ignore_change = 25;
- mlt_consumer_start( this->play );
- }
- mlt_consumer_put_frame( this->play, frame );
- }
-
- // Copy the rectangle info from the active consumer
- if ( this->running && preview_off == 0 )
- {
- mlt_properties active = MLT_CONSUMER_PROPERTIES( this->active );
- mlt_service_lock( MLT_CONSUMER_SERVICE( consumer ) );
- mlt_properties_set_int( properties, "rect_x", mlt_properties_get_int( active, "rect_x" ) );
- mlt_properties_set_int( properties, "rect_y", mlt_properties_get_int( active, "rect_y" ) );
- mlt_properties_set_int( properties, "rect_w", mlt_properties_get_int( active, "rect_w" ) );
- mlt_properties_set_int( properties, "rect_h", mlt_properties_get_int( active, "rect_h" ) );
- mlt_service_unlock( MLT_CONSUMER_SERVICE( consumer ) );
- }
-
- if ( this->active == this->still )
- {
- pthread_mutex_lock( &this->refresh_mutex );
- if ( this->running && speed == 0 && this->refresh_count <= 0 )
- pthread_cond_wait( &this->refresh_cond, &this->refresh_mutex );
- this->refresh_count --;
- pthread_mutex_unlock( &this->refresh_mutex );
- }
-
- // We are definitely not waiting on the first frame any more
- first = 0;
- }
- else
- {
- if ( frame ) mlt_frame_close( frame );
- mlt_consumer_put_frame( this->active, NULL );
- this->running = 0;
- }
- }
-
- if ( this->play ) mlt_consumer_stop( this->play );
- if ( this->still ) mlt_consumer_stop( this->still );
-
- return NULL;
-}
-
-/** Callback to allow override of the close method.
-*/
-
-static void consumer_close( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- // Stop the consumer
- mlt_consumer_stop( parent );
-
- // Close the child consumers
- mlt_consumer_close( this->play );
- mlt_consumer_close( this->still );
-
- // Now clean up the rest
- mlt_consumer_close( parent );
-
- // Finally clean up this
- free( this );
-}
+++ /dev/null
-/*
- * consumer_sdl_still.c -- A Simple DirectMedia Layer consumer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_consumer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_deque.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_filter.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <SDL/SDL.h>
-#include <SDL/SDL_syswm.h>
-#include <sys/time.h>
-
-/** This classes definition.
-*/
-
-typedef struct consumer_sdl_s *consumer_sdl;
-
-struct consumer_sdl_s
-{
- struct mlt_consumer_s parent;
- mlt_properties properties;
- pthread_t thread;
- int joined;
- int running;
- int window_width;
- int window_height;
- int width;
- int height;
- int playing;
- int sdl_flags;
- SDL_Surface *sdl_screen;
- SDL_Rect rect;
- uint8_t *buffer;
- int last_position;
- mlt_producer last_producer;
- int filtered;
-};
-
-/** Forward references to static functions.
-*/
-
-static int consumer_start( mlt_consumer parent );
-static int consumer_stop( mlt_consumer parent );
-static int consumer_is_stopped( mlt_consumer parent );
-static void consumer_close( mlt_consumer parent );
-static void *consumer_thread( void * );
-static int consumer_get_dimensions( int *width, int *height );
-static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt_service this, void **args );
-
-/** This is what will be called by the factory - anything can be passed in
- via the argument, but keep it simple.
-*/
-
-mlt_consumer consumer_sdl_still_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the consumer object
- consumer_sdl this = calloc( sizeof( struct consumer_sdl_s ), 1 );
-
- // If no malloc'd and consumer init ok
- if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
- {
- // Get the parent consumer object
- mlt_consumer parent = &this->parent;
-
- // get a handle on properties
- mlt_service service = MLT_CONSUMER_SERVICE( parent );
- this->properties = MLT_SERVICE_PROPERTIES( service );
-
- // We have stuff to clean up, so override the close method
- parent->close = consumer_close;
-
- // Default scaler (for now we'll use nearest)
- mlt_properties_set( this->properties, "rescale", "nearest" );
-
- // We're always going to run this in non-realtime mode
- mlt_properties_set( this->properties, "real_time", "0" );
-
- // Default progressive true
- mlt_properties_set_int( this->properties, "progressive", 1 );
-
- // Ensure we don't join on a non-running object
- this->joined = 1;
-
- // process actual param
- if ( arg == NULL || sscanf( arg, "%dx%d", &this->width, &this->height ) != 2 )
- {
- this->width = mlt_properties_get_int( this->properties, "width" );
- this->height = mlt_properties_get_int( this->properties, "height" );
- }
- else
- {
- mlt_properties_set_int( this->properties, "width", this->width );
- mlt_properties_set_int( this->properties, "height", this->height );
- }
-
- // Set the sdl flags
- this->sdl_flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_RESIZABLE | SDL_DOUBLEBUF;
-
- // Allow thread to be started/stopped
- parent->start = consumer_start;
- parent->stop = consumer_stop;
- parent->is_stopped = consumer_is_stopped;
-
- // Register specific events
- mlt_events_register( this->properties, "consumer-sdl-event", ( mlt_transmitter )consumer_sdl_event );
-
- // Return the consumer produced
- return parent;
- }
-
- // malloc or consumer init failed
- free( this );
-
- // Indicate failure
- return NULL;
-}
-
-static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt_service this, void **args )
-{
- if ( listener != NULL )
- listener( owner, this, ( SDL_Event * )args[ 0 ] );
-}
-
-static int consumer_start( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
-
- if ( !this->running )
- {
- int preview_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "preview_off" );
- int sdl_started = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "sdl_started" );
-
- // Attach a colour space converter
- if ( !this->filtered )
- {
- mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( parent ) );
- mlt_filter filter = mlt_factory_filter( profile, "avcolour_space", NULL );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "forced", mlt_image_yuv422 );
- mlt_service_attach( MLT_CONSUMER_SERVICE( parent ), filter );
- mlt_filter_close( filter );
- this->filtered = 1;
- }
-
- consumer_stop( parent );
-
- this->last_position = -1;
- this->running = 1;
- this->joined = 0;
-
- // Allow the user to force resizing to window size
- this->width = mlt_properties_get_int( this->properties, "width" );
- this->height = mlt_properties_get_int( this->properties, "height" );
-
- // Default window size
- double display_ratio = mlt_properties_get_double( this->properties, "display_ratio" );
- this->window_width = ( double )this->height * display_ratio;
- this->window_height = this->height;
-
- if ( sdl_started == 0 && preview_off == 0 )
- {
- if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 )
- {
- fprintf( stderr, "Failed to initialize SDL: %s\n", SDL_GetError() );
- return -1;
- }
-
- SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
- SDL_EnableUNICODE( 1 );
- }
- else if ( preview_off == 0 )
- {
- if ( SDL_GetVideoSurface( ) != NULL )
- {
- this->sdl_screen = SDL_GetVideoSurface( );
- }
- }
-
- if ( this->sdl_screen == NULL && preview_off == 0 )
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
-
- pthread_create( &this->thread, NULL, consumer_thread, this );
- }
-
- return 0;
-}
-
-static int consumer_stop( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- if ( this->joined == 0 )
- {
- int preview_off = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "preview_off" );
- int sdl_started = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( parent ), "sdl_started" );
-
- // Kill the thread and clean up
- this->running = 0;
-
- pthread_join( this->thread, NULL );
- this->joined = 1;
-
- if ( sdl_started == 0 && preview_off == 0 )
- SDL_Quit( );
-
- this->sdl_screen = NULL;
- }
-
- return 0;
-}
-
-static int consumer_is_stopped( mlt_consumer parent )
-{
- consumer_sdl this = parent->child;
- return !this->running;
-}
-
-static int sdl_lock_display( )
-{
- SDL_Surface *screen = SDL_GetVideoSurface( );
- return screen != NULL && ( !SDL_MUSTLOCK( screen ) || SDL_LockSurface( screen ) >= 0 );
-}
-
-static void sdl_unlock_display( )
-{
- SDL_Surface *screen = SDL_GetVideoSurface( );
- if ( screen != NULL && SDL_MUSTLOCK( screen ) )
- SDL_UnlockSurface( screen );
-}
-
-static inline void display_1( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
-{
- // Generate the affine transform scaling values
- if ( rect.w == 0 || rect.h == 0 ) return;
- int scale_width = ( width << 16 ) / rect.w;
- int scale_height = ( height << 16 ) / rect.h;
- int stride = width * 3;
- int x, y, row_index;
- uint8_t *q, *row;
-
- // Constants defined for clarity and optimisation
- int scanlength = screen->pitch;
- uint8_t *start = ( uint8_t * )screen->pixels + rect.y * scanlength + rect.x;
- uint8_t *p;
-
- // Iterate through the screen using a very basic scaling algorithm
- for ( y = 0; y < rect.h; y ++ )
- {
- p = start;
- row_index = ( 32768 + scale_height * y ) >> 16;
- row = image + stride * row_index;
- for ( x = 0; x < rect.w; x ++ )
- {
- q = row + ( ( ( 32768 + scale_width * x ) >> 16 ) * 3 );
- *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
- }
- start += scanlength;
- }
-}
-
-static inline void display_2( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
-{
- // Generate the affine transform scaling values
- if ( rect.w == 0 || rect.h == 0 ) return;
- int scale_width = ( width << 16 ) / rect.w;
- int scale_height = ( height << 16 ) / rect.h;
- int stride = width * 3;
- int x, y, row_index;
- uint8_t *q, *row;
-
- // Constants defined for clarity and optimisation
- int scanlength = screen->pitch / 2;
- uint16_t *start = ( uint16_t * )screen->pixels + rect.y * scanlength + rect.x;
- uint16_t *p;
-
- // Iterate through the screen using a very basic scaling algorithm
- for ( y = 0; y < rect.h; y ++ )
- {
- p = start;
- row_index = ( 32768 + scale_height * y ) >> 16;
- row = image + stride * row_index;
- for ( x = 0; x < rect.w; x ++ )
- {
- q = row + ( ( ( 32768 + scale_width * x ) >> 16 ) * 3 );
- *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
- }
- start += scanlength;
- }
-}
-
-static inline void display_3( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
-{
- // Generate the affine transform scaling values
- if ( rect.w == 0 || rect.h == 0 ) return;
- int scale_width = ( width << 16 ) / rect.w;
- int scale_height = ( height << 16 ) / rect.h;
- int stride = width * 3;
- int x, y, row_index;
- uint8_t *q, *row;
-
- // Constants defined for clarity and optimisation
- int scanlength = screen->pitch;
- uint8_t *start = ( uint8_t * )screen->pixels + rect.y * scanlength + rect.x;
- uint8_t *p;
- uint32_t pixel;
-
- // Iterate through the screen using a very basic scaling algorithm
- for ( y = 0; y < rect.h; y ++ )
- {
- p = start;
- row_index = ( 32768 + scale_height * y ) >> 16;
- row = image + stride * row_index;
- for ( x = 0; x < rect.w; x ++ )
- {
- q = row + ( ( ( 32768 + scale_width * x ) >> 16 ) * 3 );
- pixel = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
- *p ++ = (pixel & 0xFF0000) >> 16;
- *p ++ = (pixel & 0x00FF00) >> 8;
- *p ++ = (pixel & 0x0000FF);
- }
- start += scanlength;
- }
-}
-
-static inline void display_4( SDL_Surface *screen, SDL_Rect rect, uint8_t *image, int width, int height )
-{
- // Generate the affine transform scaling values
- if ( rect.w == 0 || rect.h == 0 ) return;
- int scale_width = ( width << 16 ) / rect.w;
- int scale_height = ( height << 16 ) / rect.h;
- int stride = width * 3;
- int x, y, row_index;
- uint8_t *q, *row;
-
- // Constants defined for clarity and optimisation
- int scanlength = screen->pitch / 4;
- uint32_t *start = ( uint32_t * )screen->pixels + rect.y * scanlength + rect.x;
- uint32_t *p;
-
- // Iterate through the screen using a very basic scaling algorithm
- for ( y = 0; y < rect.h; y ++ )
- {
- p = start;
- row_index = ( 32768 + scale_height * y ) >> 16;
- row = image + stride * row_index;
- for ( x = 0; x < rect.w; x ++ )
- {
- q = row + ( ( ( 32768 + scale_width * x ) >> 16 ) * 3 );
- *p ++ = SDL_MapRGB( screen->format, *q, *( q + 1 ), *( q + 2 ) );
- }
- start += scanlength;
- }
-}
-
-static int consumer_play_video( consumer_sdl this, mlt_frame frame )
-{
- // Get the properties of this consumer
- mlt_properties properties = this->properties;
-
- mlt_image_format vfmt = mlt_image_rgb24;
- int height = this->height;
- int width = this->width;
- uint8_t *image = NULL;
- int changed = 0;
- double display_ratio = mlt_properties_get_double( this->properties, "display_ratio" );
-
- void ( *lock )( void ) = mlt_properties_get_data( properties, "app_lock", NULL );
- void ( *unlock )( void ) = mlt_properties_get_data( properties, "app_unlock", NULL );
-
- if ( lock != NULL ) lock( );
-
- sdl_lock_display();
-
- // Handle events
- if ( this->sdl_screen != NULL )
- {
- SDL_Event event;
-
- changed = consumer_get_dimensions( &this->window_width, &this->window_height );
-
- while ( SDL_PollEvent( &event ) )
- {
- mlt_events_fire( this->properties, "consumer-sdl-event", &event, NULL );
-
- switch( event.type )
- {
- case SDL_VIDEORESIZE:
- this->window_width = event.resize.w;
- this->window_height = event.resize.h;
- changed = 1;
- break;
- case SDL_QUIT:
- this->running = 0;
- break;
- case SDL_KEYDOWN:
- {
- mlt_producer producer = mlt_properties_get_data( properties, "transport_producer", NULL );
- char keyboard[ 2 ] = " ";
- void (*callback)( mlt_producer, char * ) = mlt_properties_get_data( properties, "transport_callback", NULL );
- if ( callback != NULL && producer != NULL && event.key.keysym.unicode < 0x80 && event.key.keysym.unicode > 0 )
- {
- keyboard[ 0 ] = ( char )event.key.keysym.unicode;
- callback( producer, keyboard );
- }
- }
- break;
- }
- }
- }
-
- if ( this->sdl_screen == NULL || changed )
- {
- // open SDL window
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
- if ( consumer_get_dimensions( &this->window_width, &this->window_height ) )
- this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
- uint32_t color = mlt_properties_get_int( this->properties, "window_background" );
- SDL_FillRect( this->sdl_screen, NULL, color >> 8 );
- changed = 1;
- }
- else
- {
- changed = 1;
- }
-
- if ( changed == 0 &&
- this->last_position == mlt_frame_get_position( frame ) &&
- this->last_producer == mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer", NULL ) )
- {
- sdl_unlock_display( );
- if ( unlock != NULL ) unlock( );
- return 0;
- }
-
- // Update last frame shown info
- this->last_position = mlt_frame_get_position( frame );
- this->last_producer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer", NULL );
-
- // Get the image, width and height
- mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
-
- if ( image != NULL )
- {
- char *rescale = mlt_properties_get( properties, "rescale" );
- if ( rescale != NULL && strcmp( rescale, "none" ) )
- {
- double this_aspect = display_ratio / ( ( double )this->window_width / ( double )this->window_height );
- this->rect.w = this_aspect * this->window_width;
- this->rect.h = this->window_height;
- if ( this->rect.w > this->window_width )
- {
- this->rect.w = this->window_width;
- this->rect.h = ( 1.0 / this_aspect ) * this->window_height;
- }
- }
- else
- {
- double frame_aspect = mlt_frame_get_aspect_ratio( frame ) * width / height;
- this->rect.w = frame_aspect * this->window_height;
- this->rect.h = this->window_height;
- if ( this->rect.w > this->window_width )
- {
- this->rect.w = this->window_width;
- this->rect.h = ( 1.0 / frame_aspect ) * this->window_width;
- }
- }
-
- this->rect.x = ( this->window_width - this->rect.w ) / 2;
- this->rect.y = ( this->window_height - this->rect.h ) / 2;
-
- mlt_properties_set_int( this->properties, "rect_x", this->rect.x );
- mlt_properties_set_int( this->properties, "rect_y", this->rect.y );
- mlt_properties_set_int( this->properties, "rect_w", this->rect.w );
- mlt_properties_set_int( this->properties, "rect_h", this->rect.h );
- }
-
- if ( !mlt_consumer_is_stopped( &this->parent ) && SDL_GetVideoSurface( ) != NULL && this->sdl_screen != NULL && this->sdl_screen->pixels != NULL )
- {
- switch( this->sdl_screen->format->BytesPerPixel )
- {
- case 1:
- display_1( this->sdl_screen, this->rect, image, width, height );
- break;
- case 2:
- display_2( this->sdl_screen, this->rect, image, width, height );
- break;
- case 3:
- display_3( this->sdl_screen, this->rect, image, width, height );
- break;
- case 4:
- display_4( this->sdl_screen, this->rect, image, width, height );
- break;
- default:
- fprintf( stderr, "Unsupported video depth %d\n", this->sdl_screen->format->BytesPerPixel );
- break;
- }
-
- // Flip it into sight
- SDL_Flip( this->sdl_screen );
- }
-
- sdl_unlock_display();
-
- if ( unlock != NULL ) unlock( );
-
- return 1;
-}
-
-/** Threaded wrapper for pipe.
-*/
-
-static void *consumer_thread( void *arg )
-{
- // Identify the arg
- consumer_sdl this = arg;
-
- // Get the consumer
- mlt_consumer consumer = &this->parent;
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
-
- // internal intialization
- mlt_frame frame = NULL;
- mlt_image_format vfmt = mlt_image_rgb24a;
- int height = this->height;
- int width = this->width;
- uint8_t *image = NULL;
-
- // Allow the hosting app to provide the preview
- int preview_off = mlt_properties_get_int( properties, "preview_off" );
- mlt_image_format preview_format = mlt_properties_get_int( properties, "preview_format" );
-
- // Check if a specific colour space has been requested
- if ( preview_off && preview_format != mlt_image_none )
- vfmt = preview_format;
-
- // Loop until told not to
- while( this->running )
- {
- // Get a frame from the attached producer
- frame = mlt_consumer_rt_frame( consumer );
-
- // Ensure that we have a frame
- if ( this->running && frame != NULL )
- {
- if ( preview_off == 0 )
- {
- consumer_play_video( this, frame );
- }
- else
- {
- mlt_frame_get_image( frame, &image, &vfmt, &width, &height, 0 );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "format", vfmt );
- mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
- }
- mlt_frame_close( frame );
- }
- else
- {
- if ( frame ) mlt_frame_close( frame );
- this->running = 0;
- }
- }
-
- return NULL;
-}
-
-static int consumer_get_dimensions( int *width, int *height )
-{
- int changed = 0;
-
- // SDL windows manager structure
- SDL_SysWMinfo wm;
-
- // Specify the SDL Version
- SDL_VERSION( &wm.version );
-
- // Get the wm structure
- if ( SDL_GetWMInfo( &wm ) == 1 )
- {
-#ifndef __DARWIN__
- // Check that we have the X11 wm
- if ( wm.subsystem == SDL_SYSWM_X11 )
- {
- // Get the SDL window
- Window window = wm.info.x11.window;
-
- // Get the display session
- Display *display = wm.info.x11.display;
-
- // Get the window attributes
- XWindowAttributes attr;
- XGetWindowAttributes( display, window, &attr );
-
- // Determine whether window has changed
- changed = *width != attr.width || *height != attr.height;
-
- // Return width and height
- *width = attr.width;
- *height = attr.height;
- }
-#endif
- }
-
- return changed;
-}
-
-/** Callback to allow override of the close method.
-*/
-
-static void consumer_close( mlt_consumer parent )
-{
- // Get the actual object
- consumer_sdl this = parent->child;
-
- // Stop the consumer
- mlt_consumer_stop( parent );
-
- // Now clean up the rest
- mlt_consumer_close( parent );
-
- // Finally clean up this
- free( this );
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_consumer consumer_sdl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_consumer consumer_sdl_still_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_consumer consumer_sdl_preview_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-#ifdef WITH_SDL_IMAGE
-extern mlt_producer producer_sdl_image_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-#endif
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "sdl", consumer_sdl_init );
- MLT_REGISTER( consumer_type, "sdl_preview", consumer_sdl_preview_init );
- MLT_REGISTER( consumer_type, "sdl_still", consumer_sdl_still_init );
-#ifdef WITH_SDL_IMAGE
- MLT_REGISTER( producer_type, "sdl_image", producer_sdl_image_init );
-#endif
-}
+++ /dev/null
-/*
- * producer_sdl_image.c -- Image loader which wraps SDL_image
- * Copyright (C) 2005 Visual Media FX
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_pool.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <math.h>
-
-#include <SDL_image.h>
-
-static int producer_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
- SDL_Surface *surface = mlt_properties_get_data( properties, "surface", NULL );
- SDL_Surface *converted = NULL;
- uint8_t *alpha;
-
- *width = surface->w;
- *height = surface->h;
- *format = mlt_image_yuv422;
- *image = mlt_pool_alloc( *width * *height * 2 );
- alpha = mlt_pool_alloc( *width * *height );
-
- if ( surface->format->BitsPerPixel != 32 && surface->format->BitsPerPixel != 24 )
- {
- SDL_PixelFormat fmt;
- fmt.BitsPerPixel = 24;
- fmt.BytesPerPixel = 3;
- fmt.Rshift = 16;
- fmt.Gshift = 8;
- fmt.Bshift = 0;
- fmt.Rmask = 0xff << 16;
- fmt.Gmask = 0xff << 8;
- fmt.Bmask = 0xff;
- converted = SDL_ConvertSurface( surface, &fmt, 0 );
- }
-
- switch( surface->format->BitsPerPixel )
- {
- case 32:
- mlt_convert_rgb24a_to_yuv422( surface->pixels, *width, *height, surface->pitch, *image, alpha );
- break;
- case 24:
- mlt_convert_rgb24_to_yuv422( surface->pixels, *width, *height, surface->pitch, *image );
- memset( alpha, 255, *width * *height );
- break;
- default:
- mlt_convert_rgb24_to_yuv422( converted->pixels, *width, *height, converted->pitch, *image );
- memset( alpha, 255, *width * *height );
- break;
- }
-
- if ( converted )
- SDL_FreeSurface( converted );
-
- // Update the frame
- mlt_properties_set_data( properties, "image", *image, *width * *height * 2, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "alpha", alpha, *width * *height, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "width", *width );
- mlt_properties_set_int( properties, "height", *height );
-
- return 0;
-}
-
-static int filter_files( const struct dirent *de )
-{
- return de->d_name[ 0 ] != '.';
-}
-
-static mlt_properties parse_file_names( char *resource )
-{
- mlt_properties properties = mlt_properties_new( );
-
- if ( strstr( resource, "/.all." ) != NULL )
- {
- char *dir_name = strdup( resource );
- char *extension = strrchr( resource, '.' );
- *( strstr( dir_name, "/.all." ) + 1 ) = '\0';
- char fullname[ 1024 ];
- strcpy( fullname, dir_name );
- struct dirent **de = NULL;
- int n = scandir( fullname, &de, filter_files, alphasort );
- int i;
- struct stat info;
-
- for (i = 0; i < n; i++ )
- {
- snprintf( fullname, 1023, "%s%s", dir_name, de[i]->d_name );
- if ( strstr( fullname, extension ) && lstat( fullname, &info ) == 0 &&
- ( S_ISREG( info.st_mode ) || info.st_mode | S_IXUSR ) )
- {
- char temp[ 20 ];
- sprintf( temp, "%d", i );
- mlt_properties_set( properties, temp, fullname );
- }
- free( de[ i ] );
- }
-
- free( de );
- free( dir_name );
- }
- else
- {
- mlt_properties_set( properties, "0", resource );
- }
-
- return properties;
-}
-
-static SDL_Surface *load_image( mlt_producer producer )
-{
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
- char *resource = mlt_properties_get( properties, "resource" );
- char *last_resource = mlt_properties_get( properties, "_last_resource" );
- int image_idx = 0;
- char *this_resource = NULL;
- double ttl = mlt_properties_get_int( properties, "ttl" );
- mlt_position position = mlt_producer_position( producer );
- SDL_Surface *surface = mlt_properties_get_data( properties, "_surface", NULL );
- mlt_properties filenames = mlt_properties_get_data( properties, "_filenames", NULL );
-
- if ( filenames == NULL )
- {
- filenames = parse_file_names( resource );
- mlt_properties_set_data( properties, "_surface", surface, 0, ( mlt_destructor )SDL_FreeSurface, 0 );
- }
-
- if ( mlt_properties_count( filenames ) )
- {
- image_idx = ( int )floor( ( double )position / ttl ) % mlt_properties_count( filenames );
- this_resource = mlt_properties_get_value( filenames, image_idx );
-
- if ( surface == NULL || last_resource == NULL || strcmp( last_resource, this_resource ) )
- {
- surface = IMG_Load( this_resource );
- if ( surface != NULL )
- {
- surface->refcount ++;
- mlt_properties_set_data( properties, "_surface", surface, 0, ( mlt_destructor )SDL_FreeSurface, 0 );
- mlt_properties_set( properties, "_last_resource", this_resource );
- mlt_properties_set_int( properties, "_real_width", surface->w );
- mlt_properties_set_int( properties, "_real_height", surface->h );
- }
- }
- else if ( surface != NULL )
- {
- surface->refcount ++;
- }
- }
-
- return surface;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Generate a frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- if ( *frame != NULL )
- {
- // Create the surface for the current image
- SDL_Surface *surface = load_image( producer );
-
- if ( surface != NULL )
- {
- // Obtain properties of frame and producer
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Obtain properties of producer
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Set producer-specific frame properties
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
- mlt_properties_set_data( properties, "surface", surface, 0, ( mlt_destructor )SDL_FreeSurface, NULL );
- mlt_properties_set_int( properties, "real_width", surface->w );
- mlt_properties_set_int( properties, "real_height", surface->h );
-
- // Push the get_image method
- mlt_frame_push_get_image( *frame, producer_get_image );
- }
- }
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer producer )
-{
- producer->close = NULL;
- mlt_producer_close( producer );
- free( producer );
-}
-
-mlt_producer producer_sdl_image_init( mlt_profile profile, mlt_service_type type, const char *id, char *file )
-{
- mlt_producer producer = calloc( 1, sizeof( struct mlt_producer_s ) );
- if ( producer != NULL && mlt_producer_init( producer, NULL ) == 0 )
- {
- // Get the properties interface
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- // Callback registration
- producer->get_frame = producer_get_frame;
- producer->close = ( mlt_destructor )producer_close;
-
- // Set the default properties
- mlt_properties_set( properties, "resource", file );
- mlt_properties_set( properties, "_resource", "" );
- mlt_properties_set_double( properties, "aspect_ratio", 1 );
- mlt_properties_set_int( properties, "ttl", 25 );
- mlt_properties_set_int( properties, "progressive", 1 );
-
- // Validate the resource
- SDL_Surface *surface = NULL;
- if ( file && ( surface = load_image( producer ) ) )
- {
- SDL_FreeSurface( surface );
- mlt_properties_set_data( properties, "_surface", NULL, 0, NULL, NULL );
- }
- else
- {
- producer_close( producer );
- producer = NULL;
- }
- return producer;
- }
- free( producer );
- return NULL;
-}
-
-
+++ /dev/null
-include ../../../config.mak
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-include config.mak
-
-TARGET = ../libmltsox$(LIBSUF)
-
-OBJS = factory.o \
- filter_sox.o
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
- # Determine how to lookup dependencies of executable for OS
- targetos=$(uname -s)
- case $targetos in
- Darwin)
- LDD="otool -L"
- ;;
- Linux|FreeBSD)
- LDD="ldd"
- ;;
- *)
- ;;
- esac
-
- pkg-config sox
- if [ $? -eq 0 ]
- then
- disable_sox=0
- echo "CFLAGS += $(pkg-config --cflags sox) -I$(pkg-config --variable=prefix sox)" > config.mak
- echo "LDFLAGS += $(pkg-config --libs sox)" >> config.mak
- [ $(pkg-config --modversion sox | cut -d. -f1) -gt 13 ] && echo "CFLAGS += -DSOX14" >> config.mak
- else
- which libst-config > /dev/null 2>&1
- if [ $? -eq 0 ]
- then
- disable_sox=0
-
- # determine if we need libsndfile
- $LDD $(which sox) | grep libsndfile > /dev/null
- [ $? -eq 0 ] && libsndfile="-lsndfile"
-
- # determine if we need libsamplerate
- $LDD $(which sox) | grep libsamplerate > /dev/null
- [ $? -eq 0 ] && libsamplerate="-lsamplerate"
-
- echo "CFLAGS += $(libst-config --cflags) -I../.." > config.mak
- echo "LDFLAGS += -lst $(libst-config --libs) $libsndfile $libsamplerate" >> config.mak
- else
- sox --version 2> /dev/null | grep 'v14.' > /dev/null
- disable_sox=$?
- if [ $disable_sox -eq 0 ]
- then
- LIBDIR=lib
- bits=$(uname -m)
- case $bits in
- x86_64)
- [ -d /usr/lib/lib64 ] && export LIBDIR=lib64 || export LIBDIR=lib
- ;;
- *)
- export LIBDIR=lib
- ;;
- esac
-
- sox=$(which sox)
- # chop sox
- soxdir=$(dirname $sox)
- # chop bin
- soxdir=$(dirname $soxdir)
-
- # determine if we need libsamplerate
- $LDD "$sox" | grep libsamplerate > /dev/null
- [ $? -eq 0 ] && libsamplerate="-lsamplerate"
-
- # determine if we need libsfx
- $LDD $(which sox) | grep libsfx > /dev/null
- [ $? -eq 0 ] && libsfx="-lsfx"
-
- echo "CFLAGS += -DSOX14 -I$soxdir/include" > config.mak
- echo "LDFLAGS += -L$soxdir/$LIBDIR -lsox $libsfx $libsamplerate" >> config.mak
- fi
- fi
- fi
-
- if [ "$disable_sox" != "0" ]
- then
- echo "- sox not found: disabling"
- touch ../disable-sox
- fi
-
- exit 0
-fi
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_sox_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "sox", filter_sox_init );
-}
+++ /dev/null
-/*
- * filter_sox.c -- apply any number of SOX effects using libst
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt_filter.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_tokeniser.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-// TODO: does not support multiple effects with SoX v14.1.0+
-
-#ifdef SOX14
-# include <sox.h>
-# define ST_EOF SOX_EOF
-# define ST_SUCCESS SOX_SUCCESS
-# define st_sample_t sox_sample_t
-# define eff_t sox_effect_t*
-# define ST_LIB_VERSION_CODE SOX_LIB_VERSION_CODE
-# define ST_LIB_VERSION SOX_LIB_VERSION
-# if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,2,0))
-# define st_size_t size_t
-# else
-# define st_size_t sox_size_t
-# endif
-# define ST_SIGNED_WORD_TO_SAMPLE(d,clips) SOX_SIGNED_16BIT_TO_SAMPLE(d,clips)
-# if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
-# define ST_SSIZE_MIN SOX_SAMPLE_MIN
-# else
-# define ST_SSIZE_MIN SOX_SSIZE_MIN
-# endif
-# define ST_SAMPLE_TO_SIGNED_WORD(d,clips) SOX_SAMPLE_TO_SIGNED_16BIT(d,clips)
-#else
-# include <st.h>
-#endif
-
-#define BUFFER_LEN 8192
-#define AMPLITUDE_NORM 0.2511886431509580 /* -12dBFS */
-#define AMPLITUDE_MIN 0.00001
-
-/** Compute the mean of a set of doubles skipping unset values flagged as -1
-*/
-static inline double mean( double *buf, int count )
-{
- double mean = 0;
- int i;
- int j = 0;
-
- for ( i = 0; i < count; i++ )
- {
- if ( buf[ i ] != -1.0 )
- {
- mean += buf[ i ];
- j ++;
- }
- }
- if ( j > 0 )
- mean /= j;
-
- return mean;
-}
-
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
-static void delete_effect( eff_t effp )
-{
- free( effp->priv );
- free( (void*)effp->in_encoding );
- free( effp );
-}
-#endif
-
-/** Create an effect state instance for a channels
-*/
-static int create_effect( mlt_filter this, char *value, int count, int channel, int frequency )
-{
- mlt_tokeniser tokeniser = mlt_tokeniser_init();
- char id[ 256 ];
- int error = 1;
-
- // Tokenise the effect specification
- mlt_tokeniser_parse_new( tokeniser, value, " " );
- if ( tokeniser->count < 1 )
- return error;
-
- // Locate the effect
- mlt_destructor effect_destructor = mlt_pool_release;
-#ifdef SOX14
- //fprintf(stderr, "%s: effect %s count %d\n", __FUNCTION__, tokeniser->tokens[0], tokeniser->count );
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
- sox_effect_handler_t const *eff_handle = sox_find_effect( tokeniser->tokens[0] );
- if (eff_handle == NULL ) return error;
- eff_t eff = sox_create_effect( eff_handle );
- effect_destructor = ( mlt_destructor ) delete_effect;
- sox_encodinginfo_t *enc = calloc( 1, sizeof( sox_encodinginfo_t ) );
- enc->encoding = SOX_ENCODING_SIGN2;
- enc->bits_per_sample = 16;
- eff->in_encoding = eff->out_encoding = enc;
-#else
- eff_t eff = mlt_pool_alloc( sizeof( sox_effect_t ) );
- sox_create_effect( eff, sox_find_effect( tokeniser->tokens[0] ) );
-#endif
- int opt_count = tokeniser->count - 1;
-#else
- eff_t eff = mlt_pool_alloc( sizeof( struct st_effect ) );
- int opt_count = st_geteffect_opt( eff, tokeniser->count, tokeniser->tokens );
-#endif
-
- // If valid effect
- if ( opt_count != ST_EOF )
- {
- // Supply the effect parameters
-#ifdef SOX14
- if ( ( * eff->handler.getopts )( eff, opt_count, &tokeniser->tokens[ tokeniser->count > 1 ? 1 : 0 ] ) == ST_SUCCESS )
-#else
- if ( ( * eff->h->getopts )( eff, opt_count, &tokeniser->tokens[ tokeniser->count - opt_count ] ) == ST_SUCCESS )
-#endif
- {
- // Set the sox signal parameters
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
- eff->in_signal.rate = frequency;
- eff->out_signal.rate = frequency;
- eff->in_signal.channels = 1;
- eff->out_signal.channels = 1;
- eff->in_signal.precision = 16;
- eff->out_signal.precision = 16;
- eff->in_signal.length = 0;
- eff->out_signal.length = 0;
-#else
- eff->ininfo.rate = frequency;
- eff->outinfo.rate = frequency;
- eff->ininfo.channels = 1;
- eff->outinfo.channels = 1;
-#endif
-
- // Start the effect
-#ifdef SOX14
- if ( ( * eff->handler.start )( eff ) == ST_SUCCESS )
-#else
- if ( ( * eff->h->start )( eff ) == ST_SUCCESS )
-#endif
- {
- // Construct id
- sprintf( id, "_effect_%d_%d", count, channel );
-
- // Save the effect state
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), id, eff, 0, effect_destructor, NULL );
- error = 0;
- }
- }
- }
- // Some error occurred so delete the temp effect state
- if ( error == 1 )
- effect_destructor( eff );
-
- mlt_tokeniser_close( tokeniser );
-
- return error;
-}
-
-/** Get the audio.
-*/
-
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
- // Get the filter service
- mlt_filter filter = mlt_frame_pop_audio( frame );
-
- // Get the filter properties
- mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
-
- // Get the properties
- st_sample_t *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
- st_sample_t *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
- int channels_avail = *channels;
- int i; // channel
- int count = mlt_properties_get_int( filter_properties, "_effect_count" );
-
- // Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
- // Duplicate channels as necessary
- if ( channels_avail < *channels )
- {
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- int j, k = 0;
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
- k = ( k + 1 ) % channels_avail;
- }
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
- else if ( channels_avail == 6 && *channels == 2 )
- {
- // Nasty hack for ac3 5.1 audio - may be a cause of failure?
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- // Drop all but the first *channels
- for ( i = 0; i < *samples; i++ )
- {
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
-
- // Even though some effects are multi-channel aware, it is not reliable
- // We must maintain a separate effect state for each channel
- for ( i = 0; i < *channels; i++ )
- {
- char id[ 256 ];
- sprintf( id, "_effect_0_%d", i );
-
- // Get an existing effect state
- eff_t e = mlt_properties_get_data( filter_properties, id, NULL );
-
- // Validate the existing effect state
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
- if ( e != NULL && ( e->in_signal.rate != *frequency ||
- e->out_signal.rate != *frequency ) )
-#else
- if ( e != NULL && ( e->ininfo.rate != *frequency ||
- e->outinfo.rate != *frequency ) )
-#endif
- e = NULL;
-
- // (Re)Create the effect state
- if ( e == NULL )
- {
- int j = 0;
-
- // Reset the count
- count = 0;
-
- // Loop over all properties
- for ( j = 0; j < mlt_properties_count( filter_properties ); j ++ )
- {
- // Get the name of this property
- char *name = mlt_properties_get_name( filter_properties, j );
-
- // If the name does not contain a . and matches effect
- if ( !strncmp( name, "effect", 6 ) )
- {
- // Get the effect specification
- char *value = mlt_properties_get( filter_properties, name );
-
- // Create an instance
- if ( create_effect( filter, value, count, i, *frequency ) == 0 )
- count ++;
- }
- }
-
- // Save the number of filters
- mlt_properties_set_int( filter_properties, "_effect_count", count );
-
- }
- if ( *samples > 0 && count > 0 )
- {
- st_sample_t *p = input_buffer;
- st_sample_t *end = p + *samples;
- int16_t *q = *buffer + i;
- st_size_t isamp = *samples;
- st_size_t osamp = *samples;
- double rms = 0;
- int j;
- char *normalise = mlt_properties_get( filter_properties, "normalise" );
- double normalised_gain = 1.0;
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- st_sample_t dummy_clipped_count = 0;
-#endif
-
- // Convert to sox encoding
- while( p != end )
- {
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- *p = ST_SIGNED_WORD_TO_SAMPLE( *q, dummy_clipped_count );
-#else
- *p = ST_SIGNED_WORD_TO_SAMPLE( *q );
-#endif
- // Compute rms amplitude while we are accessing each sample
- rms += ( double )*p * ( double )*p;
-
- p ++;
- q += *channels;
- }
-
- // Compute final rms amplitude
- rms = sqrt( rms / *samples / ST_SSIZE_MIN / ST_SSIZE_MIN );
-
- if ( normalise )
- {
- int window = mlt_properties_get_int( filter_properties, "window" );
- double *smooth_buffer = mlt_properties_get_data( filter_properties, "smooth_buffer", NULL );
- double max_gain = mlt_properties_get_double( filter_properties, "max_gain" );
-
- // Default the maximum gain factor to 20dBFS
- if ( max_gain == 0 )
- max_gain = 10.0;
-
- // The smoothing buffer prevents radical shifts in the gain level
- if ( window > 0 && smooth_buffer != NULL )
- {
- int smooth_index = mlt_properties_get_int( filter_properties, "_smooth_index" );
- smooth_buffer[ smooth_index ] = rms;
-
- // Ignore very small values that adversely affect the mean
- if ( rms > AMPLITUDE_MIN )
- mlt_properties_set_int( filter_properties, "_smooth_index", ( smooth_index + 1 ) % window );
-
- // Smoothing is really just a mean over the past N values
- normalised_gain = AMPLITUDE_NORM / mean( smooth_buffer, window );
- }
- else if ( rms > 0 )
- {
- // Determine gain to apply as current amplitude
- normalised_gain = AMPLITUDE_NORM / rms;
- }
-
- //printf("filter_sox: rms %.3f gain %.3f\n", rms, normalised_gain );
-
- // Govern the maximum gain
- if ( normalised_gain > max_gain )
- normalised_gain = max_gain;
- }
-
- // For each effect
- for ( j = 0; j < count; j++ )
- {
- sprintf( id, "_effect_%d_%d", j, i );
- e = mlt_properties_get_data( filter_properties, id, NULL );
-
- // We better have this guy
- if ( e != NULL )
- {
- float saved_gain = 1.0;
-
- // XXX: hack to apply the normalised gain level to the vol effect
-#ifdef SOX14
- if ( normalise && strcmp( e->handler.name, "vol" ) == 0 )
-#else
- if ( normalise && strcmp( e->name, "vol" ) == 0 )
-#endif
- {
- float *f = ( float * )( e->priv );
- saved_gain = *f;
- *f = saved_gain * normalised_gain;
- }
-
- // Apply the effect
-#ifdef SOX14
- if ( ( * e->handler.flow )( e, input_buffer, output_buffer, &isamp, &osamp ) == ST_SUCCESS )
-#else
- if ( ( * e->h->flow )( e, input_buffer, output_buffer, &isamp, &osamp ) == ST_SUCCESS )
-#endif
- {
- // Swap input and output buffer pointers for subsequent effects
- p = input_buffer;
- input_buffer = output_buffer;
- output_buffer = p;
- }
-
- // XXX: hack to restore the original vol gain to prevent accumulation
-#ifdef SOX14
- if ( normalise && strcmp( e->handler.name, "vol" ) == 0 )
-#else
- if ( normalise && strcmp( e->name, "vol" ) == 0 )
-#endif
- {
- float *f = ( float * )( e->priv );
- *f = saved_gain;
- }
- }
- }
-
- // Convert back to signed 16bit
- p = input_buffer;
- q = *buffer + i;
- end = p + *samples;
- while ( p != end )
- {
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++, dummy_clipped_count );
-#else
- *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++ );
-#endif
- q += *channels;
- }
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- if ( mlt_frame_is_test_audio( frame ) == 0 )
- {
- // Add the filter to the frame
- mlt_frame_push_audio( frame, this );
- mlt_frame_push_audio( frame, filter_get_audio );
-
- // Parse the window property and allocate smoothing buffer if needed
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
- int window = mlt_properties_get_int( properties, "window" );
- if ( mlt_properties_get( properties, "smooth_buffer" ) == NULL && window > 1 )
- {
- // Create a smoothing buffer for the calculated "max power" of frame of audio used in normalisation
- double *smooth_buffer = (double*) calloc( window, sizeof( double ) );
- int i;
- for ( i = 0; i < window; i++ )
- smooth_buffer[ i ] = -1.0;
- mlt_properties_set_data( properties, "smooth_buffer", smooth_buffer, 0, free, NULL );
- }
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_sox_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- void *input_buffer = mlt_pool_alloc( BUFFER_LEN );
- void *output_buffer = mlt_pool_alloc( BUFFER_LEN );
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- this->process = filter_process;
-
- if ( arg != NULL )
- mlt_properties_set( properties, "effect", arg );
- mlt_properties_set_data( properties, "input_buffer", input_buffer, BUFFER_LEN, mlt_pool_release, NULL );
- mlt_properties_set_data( properties, "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "window", 75 );
- }
- return this;
-}
-
-// What to do when a libst internal failure occurs
-void cleanup(void){}
-
-// Is there a build problem with my sox-devel package?
-#ifndef gsm_create
-void gsm_create(void){}
-#endif
-#ifndef gsm_decode
-void gsm_decode(void){}
-#endif
-#ifndef gdm_encode
-void gsm_encode(void){}
-#endif
-#ifndef gsm_destroy
-void gsm_destroy(void){}
-#endif
-#ifndef gsm_option
-void gsm_option(void){}
-#endif
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltvalerie$(LIBSUF)
-
-OBJS = factory.o \
- consumer_valerie.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../valerie -lvalerie
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * consumer_valerie.c -- pushes a service via valerie
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@telenet.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <valerie/valerie.h>
-#include <valerie/valerie_remote.h>
-#include <framework/mlt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-
-static int consumer_is_stopped( mlt_consumer this );
-static int consumer_start( mlt_consumer this );
-
-/** This is what will be called by the factory
-*/
-
-mlt_consumer consumer_valerie_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the consumer object
- mlt_consumer this = calloc( sizeof( struct mlt_consumer_s ), 1 );
-
- // If no malloc'd and consumer init ok
- if ( this != NULL && mlt_consumer_init( this, NULL, profile ) == 0 )
- {
- if ( arg != NULL && strchr( arg, ':' ) )
- {
- char *temp = NULL;
- int port = atoi( strchr( arg, ':' ) + 1 );
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( this ), "server", arg );
- temp = mlt_properties_get( MLT_CONSUMER_PROPERTIES( this ), "server" );
- *( strchr( temp, ':' ) ) = '\0';
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "port", port );
- }
- else
- {
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( this ), "server", arg == NULL ? "localhost" : arg );
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "port", 5250 );
- }
-
- mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( this ), "unit", 0 );
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( this ), "command", "append" );
-
- // Allow thread to be started/stopped
- this->start = consumer_start;
- this->is_stopped = consumer_is_stopped;
-
- // Return the consumer produced
- return this;
- }
-
- // malloc or consumer init failed
- free( this );
-
- // Indicate failure
- return NULL;
-}
-
-static int consumer_start( mlt_consumer this )
-{
- // Get the producer service
- mlt_service service = mlt_service_producer( MLT_CONSUMER_SERVICE( this ) );
-
- // Get the properties object
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
-
- // Get all the properties now
- char *server = mlt_properties_get( properties, "server" );
- int port = mlt_properties_get_int( properties, "port" );
- char *cmd = mlt_properties_get( properties, "command" );
- int unit = mlt_properties_get_int( properties, "unit" );
- char *title = mlt_properties_get( properties, "title" );
- char command[ 2048 ];
-
- // If this is a reuse, then a valerie object will exist
- valerie connection = mlt_properties_get_data( properties, "connection", NULL );
-
- // Special case - we can get a doc too...
- char *doc = mlt_properties_get( properties, "westley" );
-
- // Set the title if provided
- if ( service != NULL )
- {
- if ( title != NULL )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", title );
- else if ( mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "title" ) == NULL )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", "Anonymous Submission" );
- title = mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "title" );
- }
-
- strcpy( command, cmd == NULL ? "" : cmd );
- if ( strstr( command, "title=" ) == NULL && title != NULL )
- {
- strcat( command, " title=\"" );
- strcat( command, title );
- strcat( command, "\"" );
- }
-
- if ( service != NULL || doc != NULL )
- {
- // Initiate the connection if required
- if ( connection == NULL )
- {
- valerie_parser parser = valerie_parser_init_remote( server, port );
- connection = valerie_init( parser );
- if ( valerie_connect( connection ) == valerie_ok )
- {
- mlt_properties_set_data( properties, "connection", connection, 0, ( mlt_destructor )valerie_close, NULL );
- mlt_properties_set_data( properties, "parser", parser, 0, ( mlt_destructor )valerie_parser_close, NULL );
- }
- else
- {
- fprintf( stderr, "Unable to connect to the server at %s:%d\n", server, port );
- mlt_properties_set_int( properties, "_error", 1 );
- valerie_close( connection );
- valerie_parser_close( parser );
- connection = NULL;
- }
- }
-
- // If we have connection, push the service over
- if ( connection != NULL )
- {
- if ( doc == NULL )
- {
- int error;
-
- // Push the service
- error = valerie_unit_push( connection, unit, command, service );
-
- // Report error
- if ( error != valerie_ok )
- fprintf( stderr, "Push failed on %s:%d %s u%d (%d)\n", server, port, command, unit, error );
- }
- else
- {
- // Push the service
- int error = valerie_unit_receive( connection, unit, command, doc );
-
- // Report error
- if ( error != valerie_ok )
- fprintf( stderr, "Send failed on %s:%d %s u%d (%d)\n", server, port, command, unit, error );
- }
- }
- }
-
- mlt_consumer_stop( this );
- mlt_consumer_stopped( this );
-
- return 0;
-}
-
-static int consumer_is_stopped( mlt_consumer this )
-{
- return 1;
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_consumer consumer_valerie_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "valerie", consumer_valerie_init );
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltvmfx$(LIBSUF)
-
-OBJS = factory.o \
- filter_chroma.o \
- filter_chroma_hold.o \
- filter_mono.o \
- filter_shape.o \
- producer_pgm.o
-
-CFLAGS += -I../..
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_chroma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_chroma_hold_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_filter filter_shape_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_pgm_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "chroma", filter_chroma_init );
- MLT_REGISTER( filter_type, "chroma_hold", filter_chroma_hold_init );
- MLT_REGISTER( filter_type, "threshold", filter_mono_init );
- MLT_REGISTER( filter_type, "shape", filter_shape_init );
- MLT_REGISTER( producer_type, "pgm", producer_pgm_init );
-}
+++ /dev/null
-/*
- * filter_chroma.c -- Maps a chroma key to the alpha channel
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <stdlib.h>
-#include <math.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_geometry.h>
-
-static inline int in_range( uint8_t v, uint8_t c, int var )
-{
- return ( ( int )v >= c - var ) && ( ( int )v <= c + var );
-}
-
-static inline uint8_t alpha_value( uint8_t a, uint8_t *p, uint8_t u, uint8_t v, int var, int odd )
-{
- if ( odd == 0 )
- return ( in_range( *( p + 1 ), u, var ) && in_range( *( p + 3 ), v, var ) ) ? 0 : a;
- else
- return ( in_range( ( *( p + 1 ) + *( p + 5 ) ) / 2, u, var ) && in_range( ( *( p + 3 ) + *( p + 7 ) ) / 2, v, var ) ) ? 0 : a;
-}
-
-/** Get the images and map the chroma to the alpha of the frame.
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_filter this = mlt_frame_pop_service( frame );
- int variance = 200 * mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "variance" );
- int32_t key_val = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "key" );
- uint8_t r = ( key_val >> 24 ) & 0xff;
- uint8_t g = ( key_val >> 16 ) & 0xff;
- uint8_t b = ( key_val >> 8 ) & 0xff;
- uint8_t y, u, v;
-
- RGB2YUV( r, g, b, y, u, v );
-
- if ( mlt_frame_get_image( frame, image, format, width, height, writable ) == 0 )
- {
- uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
- uint8_t *p = *image;
- int size = *width * *height / 2;
- while ( size -- )
- {
- *alpha = alpha_value( *alpha, p, u, v, variance, 0 );
- alpha ++;
- *alpha = alpha_value( *alpha, p, u, v, variance, 1 );
- alpha ++;
- p += 4;
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_service( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_chroma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "key", arg == NULL ? "0x0000ff00" : arg );
- mlt_properties_set_double( MLT_FILTER_PROPERTIES( this ), "variance", 0.15 );
- this->process = filter_process;
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_chroma.c -- Maps a chroma key to the alpha channel
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <stdlib.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_geometry.h>
-
-static inline int in_range( uint8_t v, uint8_t c, int var )
-{
- return ( ( int )v >= c - var ) && ( ( int )v <= c + var );
-}
-
-static inline uint8_t alpha_value( uint8_t a, uint8_t *p, uint8_t u, uint8_t v, int var, int odd )
-{
- if ( odd == 0 )
- return ( in_range( *( p + 1 ), u, var ) && in_range( *( p + 3 ), v, var ) ) ? 0 : a;
- else
- return ( in_range( ( *( p + 1 ) + *( p + 5 ) ) / 2, u, var ) && in_range( ( *( p + 3 ) + *( p + 7 ) ) / 2, v, var ) ) ? 0 : a;
-}
-
-/** Get the images and map the chroma to the alpha of the frame.
-*/
-
-static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_filter this = mlt_frame_pop_service( frame );
- int variance = 200 * mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "variance" );
- int32_t key_val = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "key" );
- uint8_t r = ( key_val >> 24 ) & 0xff;
- uint8_t g = ( key_val >> 16 ) & 0xff;
- uint8_t b = ( key_val >> 8 ) & 0xff;
- uint8_t y, u, v;
-
- RGB2YUV( r, g, b, y, u, v );
-
- if ( mlt_frame_get_image( frame, image, format, width, height, writable ) == 0 )
- {
- uint8_t alpha = 0;
- uint8_t *p = *image;
- int size = *width * *height / 2;
- while ( size -- )
- {
- alpha = alpha_value( 255, p, u, v, variance, 0 );
- if ( alpha )
- *( p + 1 )= 128;
- alpha = alpha_value( 255, p, u, v, variance, 1 );
- if ( alpha )
- *( p + 3 ) = 128;
- p += 4;
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- mlt_frame_push_service( frame, this );
- mlt_frame_push_service( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_chroma_hold_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "key", arg == NULL ? "0xc0000000" : arg );
- mlt_properties_set_double( MLT_FILTER_PROPERTIES( this ), "variance", 0.15 );
- this->process = filter_process;
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_mono.c -- Arbitrary alpha channel shaping
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include <string.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_geometry.h>
-
-/** Get the images and apply the luminance of the mask to the alpha of the frame.
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int use_alpha = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );
- int midpoint = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );
- int invert = mlt_deque_pop_back_int( MLT_FRAME_IMAGE_STACK( this ) );
-
- // Render the frame
- if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 )
- {
- uint8_t *p = *image;
- uint8_t A = invert? 235 : 16;
- uint8_t B = invert? 16 : 235;
- int size = *width * *height;
-
- if ( !use_alpha )
- {
- while( size -- )
- {
- if ( *p < midpoint )
- *p ++ = A;
- else
- *p ++ = B;
- *p ++ = 128;
- }
- }
- else
- {
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
- while( size -- )
- {
- if ( *alpha ++ < midpoint )
- *p ++ = A;
- else
- *p ++ = B;
- *p ++ = 128;
- }
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- int midpoint = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "midpoint" );
- int use_alpha = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "use_alpha" );
- int invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "invert" );
- mlt_deque_push_back_int( MLT_FRAME_IMAGE_STACK( frame ), invert );
- mlt_deque_push_back_int( MLT_FRAME_IMAGE_STACK( frame ), midpoint );
- mlt_deque_push_back_int( MLT_FRAME_IMAGE_STACK( frame ), use_alpha );
- mlt_frame_push_get_image( frame, filter_get_image );
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "midpoint", 128 );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "use_alpha", 0 );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "invert", 0 );
- this->process = filter_process;
- }
- return this;
-}
-
+++ /dev/null
-/*
- * filter_shape.c -- Arbitrary alpha channel shaping
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt.h>
-#include <string.h>
-#include <framework/mlt_factory.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_producer.h>
-#include <framework/mlt_geometry.h>
-
-inline double smoothstep( const double e1, const double e2, const double a )
-{
- if ( a < e1 ) return 0.0;
- if ( a > e2 ) return 1.0;
- double v = ( a - e1 ) / ( e2 - e1 );
- return ( v * v * ( 3 - 2 * v ) );
-}
-
-/** Get the images and apply the luminance of the mask to the alpha of the frame.
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- // Fetch the data from the stack (mix, mask, filter)
- double mix = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( this ) );
- mlt_frame mask = mlt_frame_pop_service( this );
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Obtain the constants
- double softness = mlt_properties_get_double( MLT_FILTER_PROPERTIES( filter ), "softness" );
- int use_luminance = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "use_luminance" );
- int invert = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "invert" ) * 255;
-
- // Render the frame
- if ( mlt_frame_get_image( this, image, format, width, height, writable ) == 0 && ( !use_luminance || ( int )mix != 1 ) )
- {
- // Get the alpha mask of the source
- uint8_t *alpha = mlt_frame_get_alpha_mask( this );
-
- // Obtain a scaled/distorted mask to match
- uint8_t *mask_img = NULL;
- mlt_image_format mask_fmt = mlt_image_yuv422;
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( mask ), "distort", 1 );
- mlt_properties_pass_list( MLT_FRAME_PROPERTIES( mask ), MLT_FRAME_PROPERTIES( this ), "deinterlace,deinterlace_method,rescale.interp" );
-
- if ( mlt_frame_get_image( mask, &mask_img, &mask_fmt, width, height, 0 ) == 0 )
- {
- int size = *width * *height;
- uint8_t *p = alpha;
- double a = 0;
- double b = 0;
- if ( !use_luminance )
- {
- uint8_t *q = mlt_frame_get_alpha_mask( mask );
- while( size -- )
- {
- a = ( double )*q ++ / 255.0;
- b = 1.0 - smoothstep( a, a + softness, mix );
- *p = ( uint8_t )( *p * b ) ^ invert;
- p ++;
- }
- }
- else if ( ( int )mix != 1 )
- {
- uint8_t *q = mask_img;
- // Ensure softness tends to zero has mix tends to 1
- softness *= ( 1.0 - mix );
- while( size -- )
- {
- a = ( ( double )*q - 16 ) / 235.0;
- b = smoothstep( a, a + softness, mix );
- *p = ( uint8_t )( *p * b ) ^ invert;
- p ++;
- q += 2;
- }
- }
- }
- }
-
- return 0;
-}
-
-/** Filter processing.
-*/
-
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
-{
- // Obtain the shape instance
- char *resource = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "resource" );
- char *last_resource = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "_resource" );
- mlt_producer producer = mlt_properties_get_data( MLT_FILTER_PROPERTIES( this ), "instance", NULL );
-
- // Get the key framed values
- mlt_geometry alpha = mlt_properties_get_data( MLT_FILTER_PROPERTIES( this ), "_alpha", NULL );
- char *alpha_data = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "mix" );
- double alpha_mix = 0.0;
-
- // Calculate the position and length
- int position = mlt_frame_get_position( frame ) - mlt_filter_get_in( this );
- int in = mlt_filter_get_in( this );
- int out = mlt_filter_get_out( this );
- int length;
-
- // Special case for attached filters - in/out come through on the frame
- if ( out == 0 )
- {
- in = mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "in" );
- out = mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "out" );
- position -= in;
- }
-
- // Duration of the shape
- length = out - in + 1;
-
- // If we haven't created the instance or it's changed
- if ( producer == NULL || strcmp( resource, last_resource ) )
- {
- char temp[ 512 ];
- char *extension = strrchr( resource, '.' );
-
- // Store the last resource now
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "_resource", resource );
-
- // This is a hack - the idea is that we can indirectly reference the
- // luma modules pgm or png images by a short cut like %luma01.pgm - we then replace
- // the % with the full path to the image and use it if it exists, if not, check for
- // the file ending in a .png, and failing that, default to a fade in
- if ( strchr( resource, '%' ) )
- {
- FILE *test;
- sprintf( temp, "%s/lumas/%s/%s", mlt_environment( "MLT_DATA" ), mlt_environment( "MLT_NORMALISATION" ), strchr( resource, '%' ) + 1 );
- test = fopen( temp, "r" );
-
- if ( test == NULL )
- {
- strcat( temp, ".png" );
- test = fopen( temp, "r" );
- }
-
- if ( test )
- fclose( test );
- else
- strcpy( temp, "colour:0x00000080" );
-
- resource = temp;
- extension = strrchr( resource, '.' );
- }
-
- mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
- producer = mlt_factory_producer( profile, NULL, resource );
- if ( producer != NULL )
- mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "loop" );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "instance", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
- }
-
- // Construct the geometry item if needed, otherwise refresh it
- if ( alpha == NULL )
- {
- alpha = mlt_geometry_init( );
- mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "_alpha", alpha, 0, ( mlt_destructor )mlt_geometry_close, NULL );
- mlt_geometry_parse( alpha, alpha_data, length, 100, 100 );
- }
- else
- {
- mlt_geometry_refresh( alpha, alpha_data, length, 100, 100 );
- }
-
- // We may still not have a producer in which case, we do nothing
- if ( producer != NULL )
- {
- mlt_frame mask = NULL;
- struct mlt_geometry_item_s item;
- mlt_geometry_fetch( alpha, &item, position );
- alpha_mix = item.x;
- mlt_properties_pass( MLT_PRODUCER_PROPERTIES( producer ), MLT_FILTER_PROPERTIES( this ), "producer." );
- mlt_producer_seek( producer, position );
- if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &mask, 0 ) == 0 )
- {
- char *name = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "_unique_id" );
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), name, mask, 0, ( mlt_destructor )mlt_frame_close, NULL );
- mlt_frame_push_service( frame, this );
- mlt_frame_push_service( frame, mask );
- mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( frame ), alpha_mix / 100.0 );
- mlt_frame_push_get_image( frame, filter_get_image );
- if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "audio_match" ) )
- {
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "meta.mixdown", 1 );
- mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "meta.volume", alpha_mix / 100.0 );
- }
- }
- }
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_shape_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "resource", arg );
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "mix", "100" );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "audio_match", 1 );
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "invert", 0 );
- mlt_properties_set_double( MLT_FILTER_PROPERTIES( this ), "softness", 0.1 );
- this->process = filter_process;
- }
- return this;
-}
-
+++ /dev/null
-/*
- * producer_pgm.c -- PGM producer
- * Copyright (C) 2005 Visual Media Fx Inc.
- * Author: Charles Yates <charles.yates@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <stdlib.h>
-#include <string.h>
-
-static int read_pgm( char *name, uint8_t **image, int *width, int *height, int *maxval );
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
-static void producer_close( mlt_producer parent );
-
-mlt_producer producer_pgm_init( mlt_profile profile, mlt_service_type type, const char *id, char *resource )
-{
- mlt_producer this = NULL;
- uint8_t *image = NULL;
- int width = 0;
- int height = 0;
- int maxval = 0;
-
- if ( read_pgm( resource, &image, &width, &height, &maxval ) == 0 )
- {
- this = calloc( 1, sizeof( struct mlt_producer_s ) );
- if ( this != NULL && mlt_producer_init( this, NULL ) == 0 )
- {
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
- this->get_frame = producer_get_frame;
- this->close = ( mlt_destructor )producer_close;
- mlt_properties_set( properties, "resource", resource );
- mlt_properties_set_data( properties, "image", image, 0, mlt_pool_release, NULL );
- mlt_properties_set_int( properties, "real_width", width );
- mlt_properties_set_int( properties, "real_height", height );
- }
- else
- {
- mlt_pool_release( image );
- free( this );
- this = NULL;
- }
- }
-
- return this;
-}
-
-/** Load the PGM file.
-*/
-
-static int read_pgm( char *name, uint8_t **image, int *width, int *height, int *maxval )
-{
- uint8_t *input = NULL;
- int error = 0;
- FILE *f = fopen( name, "r" );
- char data[ 512 ];
-
- // Initialise
- *image = NULL;
- *width = 0;
- *height = 0;
- *maxval = 0;
-
- // Get the magic code
- if ( f != NULL && fgets( data, 511, f ) != NULL && data[ 0 ] == 'P' && data[ 1 ] == '5' )
- {
- char *p = data + 2;
- int i = 0;
- int val = 0;
-
- // PGM Header parser (probably needs to be strengthened)
- for ( i = 0; !error && i < 3; i ++ )
- {
- if ( *p != '\0' && *p != '\n' )
- val = strtol( p, &p, 10 );
- else
- p = NULL;
-
- while ( error == 0 && p == NULL )
- {
- if ( fgets( data, 511, f ) == NULL )
- error = 1;
- else if ( data[ 0 ] != '#' )
- val = strtol( data, &p, 10 );
- }
-
- switch( i )
- {
- case 0: *width = val; break;
- case 1: *height = val; break;
- case 2: *maxval = val; break;
- }
- }
-
- if ( !error )
- {
- // Determine if this is one or two bytes per pixel
- int bpp = *maxval > 255 ? 2 : 1;
- int size = *width * *height * bpp;
- uint8_t *p;
-
- // Allocate temporary storage for the data and the image
- input = mlt_pool_alloc( *width * *height * bpp );
- *image = mlt_pool_alloc( *width * *height * sizeof( uint8_t ) * 2 );
- p = *image;
-
- error = *image == NULL || input == NULL;
-
- if ( !error )
- {
- // Read the raw data
- error = fread( input, *width * *height * bpp, 1, f ) != 1;
-
- if ( !error )
- {
- // Convert to yuv422 (very lossy - need to extend this to allow 16 bit alpha out)
- for ( i = 0; i < size; i += bpp )
- {
- *p ++ = 16 + ( input[ i ] * 219 ) / 255;
- *p ++ = 128;
- }
- }
- }
- }
-
- if ( error )
- mlt_pool_release( *image );
- mlt_pool_release( input );
- }
- else
- {
- error = 1;
- }
-
- if ( f != NULL )
- fclose( f );
-
- return error;
-}
-
-static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
-{
- mlt_producer producer = mlt_frame_pop_service( this );
- int real_width = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "real_width" );
- int real_height = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "real_height" );
- int size = real_width * real_height;
- uint8_t *image = mlt_pool_alloc( size * 2 );
- uint8_t *source = mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( producer ), "image", NULL );
-
- mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image, size * 2, mlt_pool_release, NULL );
-
- *width = real_width;
- *height = real_height;
- *format = mlt_image_yuv422;
- *buffer = image;
-
- if ( image != NULL && source != NULL )
- memcpy( image, source, size * 2 );
-
- return 0;
-}
-
-static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
-{
- // Construct a test frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-
- // Get the frames properties
- mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
-
- // Pass the data on the frame properties
- mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( producer ), "real_width,real_height" );
- mlt_properties_set_int( properties, "has_image", 1 );
- mlt_properties_set_int( properties, "progressive", 1 );
- mlt_properties_set_double( properties, "aspect_ratio", 1 );
-
- // Push the image callback
- mlt_frame_push_service( *frame, producer );
- mlt_frame_push_get_image( *frame, producer_get_image );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( producer );
-
- return 0;
-}
-
-static void producer_close( mlt_producer parent )
-{
- parent->close = NULL;
- mlt_producer_close( parent );
- free( parent );
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltvorbis$(LIBSUF)
-
-OBJS = factory.o \
- producer_vorbis.o
-
-CFLAGS += -I../..
-CFLAGS += `pkg-config --cflags vorbis`
-CFLAGS += `pkg-config --cflags vorbisfile`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `pkg-config --libs vorbis`
-LDFLAGS += `pkg-config --libs vorbisfile`
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- pkg-config vorbisfile 2> /dev/null
- disable_vorbis=$?
-
- if [ "$disable_vorbis" != "0" ]
- then
- echo "- ogg vorbis not found: disabling"
- touch ../disable-vorbis
- fi
- exit 0
-fi
-
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_producer producer_vorbis_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( producer_type, "vorbis", producer_vorbis_init );
-}
+++ /dev/null
-/*
- * producer_vorbis.c -- vorbis producer
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// MLT Header files
-#include <framework/mlt_producer.h>
-#include <framework/mlt_frame.h>
-#include <framework/mlt_profile.h>
-
-// vorbis Header files
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-
-// System header files
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-// Forward references.
-static int producer_open( mlt_producer this, mlt_profile profile, char *file );
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
-
-/** Structure for metadata reading
-*/
-
-typedef struct _sw_metadata sw_metadata;
-
-struct _sw_metadata {
- char * name;
- char * content;
-};
-
-static sw_metadata *vorbis_metadata_from_str (char * str)
-{
- sw_metadata * meta = NULL;
- int i;
-
- for (i = 0; str[i]; i++) {
- str[i] = tolower(str[i]);
- if (str[i] == '=') {
- str[i] = '\0';
- meta = malloc (sizeof (sw_metadata));
- meta->name = malloc( strlen(str) + 18 );
- sprintf(meta->name, "meta.attr.%s.markup", str);
- meta->content = strdup (&str[i+1]);
- break;
- }
- }
- return meta;
-}
-
-/** Constructor for libvorbis.
-*/
-
-mlt_producer producer_vorbis_init( mlt_profile profile, mlt_service_type type, const char *id, char *file )
-{
- mlt_producer this = NULL;
-
- // Check that we have a non-NULL argument
- if ( file != NULL )
- {
- // Construct the producer
- this = calloc( 1, sizeof( struct mlt_producer_s ) );
-
- // Initialise it
- if ( mlt_producer_init( this, NULL ) == 0 )
- {
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Set the resource property (required for all producers)
- mlt_properties_set( properties, "resource", file );
-
- // Register our get_frame implementation
- this->get_frame = producer_get_frame;
-
- // Open the file
- if ( producer_open( this, profile, file ) != 0 )
- {
- // Clean up
- mlt_producer_close( this );
- this = NULL;
- }
- }
- }
-
- return this;
-}
-
-/** Destuctor for ogg files.
-*/
-
-static void producer_file_close( void *file )
-{
- if ( file != NULL )
- {
- // Close the ogg vorbis structure
- ov_clear( file );
-
- // Free the memory
- free( file );
- }
-}
-
-/** Open the file.
-*/
-
-static int producer_open( mlt_producer this, mlt_profile profile, char *file )
-{
- // FILE pointer for file
- FILE *input = fopen( file, "r" );
-
- // Error code to return
- int error = input == NULL;
-
- // Continue if file is open
- if ( error == 0 )
- {
- // OggVorbis file structure
- OggVorbis_File *ov = calloc( 1, sizeof( OggVorbis_File ) );
-
- // Attempt to open the stream
- error = ov == NULL || ov_open( input, ov, NULL, 0 ) != 0;
-
- // Assign to producer properties if successful
- if ( error == 0 )
- {
- // Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Assign the ov structure
- mlt_properties_set_data( properties, "ogg_vorbis_file", ov, 0, producer_file_close, NULL );
-
- // Read metadata
- sw_metadata * metadata = NULL;
- char **ptr = ov_comment(ov, -1)->user_comments;
- while(*ptr) {
- metadata = vorbis_metadata_from_str (*ptr);
- if (metadata != NULL)
- mlt_properties_set(properties, metadata->name, metadata->content);
- ++ptr;
- }
-
- if ( ov_seekable( ov ) )
- {
- // Get the length of the file
- double length = ov_time_total( ov, -1 );
-
- // We will treat everything with the producer fps
- double fps = mlt_profile_fps( profile );
-
- // Set out and length of file
- mlt_properties_set_position( properties, "out", ( length * fps ) - 1 );
- mlt_properties_set_position( properties, "length", ( length * fps ) );
-
- // Get the vorbis info
- vorbis_info *vi = ov_info( ov, -1 );
- mlt_properties_set_int( properties, "frequency", (int) vi->rate );
- mlt_properties_set_int( properties, "channels", vi->channels );
-
- // Set some media metadata
- mlt_properties_set_int( properties, "meta.media.nb_streams", 1 );
- mlt_properties_set_int( properties, "audio_index", 0 );
- mlt_properties_set( properties, "meta.media.0.stream.type", "audio" );
- mlt_properties_set( properties, "meta.media.0.codec.name", "vorbis" );
- mlt_properties_set( properties, "meta.media.0.codec.long_name", "Vorbis" );
- }
- }
- else
- {
- // Clean up
- free( ov );
-
- // Must close input file when open fails
- fclose( input );
- }
- }
-
- return error;
-}
-
-/** Convert a frame position to a time code.
-*/
-
-static double producer_time_of_frame( mlt_producer this, mlt_position position )
-{
- return ( double )position / mlt_producer_get_fps( this );
-}
-
-/** Get the audio from a frame.
-*/
-
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- // Get the properties from the frame
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-
- // Obtain the frame number of this frame
- mlt_position position = mlt_properties_get_position( frame_properties, "vorbis_position" );
-
- // Get the producer
- mlt_producer this = mlt_frame_pop_audio( frame );
-
- // Get the producer properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( this );
-
- // Get the ogg vorbis file
- OggVorbis_File *ov = mlt_properties_get_data( properties, "ogg_vorbis_file", NULL );
-
- // Obtain the expected frame numer
- mlt_position expected = mlt_properties_get_position( properties, "audio_expected" );
-
- // Get the fps for this producer
- double fps = mlt_producer_get_fps( this );
-
- // Get the vorbis info
- vorbis_info *vi = ov_info( ov, -1 );
-
- // Obtain the audio buffer
- int16_t *audio_buffer = mlt_properties_get_data( properties, "audio_buffer", NULL );
-
- // Get amount of audio used
- int audio_used = mlt_properties_get_int( properties, "audio_used" );
-
- // Number of frames to ignore (for ffwd)
- int ignore = 0;
-
- // Flag for paused (silence)
- int paused = 0;
-
- // Check for audio buffer and create if necessary
- if ( audio_buffer == NULL )
- {
- // Allocate the audio buffer
- audio_buffer = mlt_pool_alloc( 131072 * sizeof( int16_t ) );
-
- // And store it on properties for reuse
- mlt_properties_set_data( properties, "audio_buffer", audio_buffer, 0, mlt_pool_release, NULL );
- }
-
- // Seek if necessary
- if ( position != expected )
- {
- if ( position + 1 == expected )
- {
- // We're paused - silence required
- paused = 1;
- }
- else if ( position > expected && ( position - expected ) < 250 )
- {
- // Fast forward - seeking is inefficient for small distances - just ignore following frames
- ignore = position - expected;
- }
- else
- {
- // Seek to the required position
- ov_time_seek( ov, producer_time_of_frame( this, position ) );
- expected = position;
- audio_used = 0;
- }
- }
-
- // Return info in frame
- *frequency = vi->rate;
- *channels = vi->channels;
-
- // Get the audio if required
- if ( !paused )
- {
- // Bitstream section
- int current_section;
-
- // Get the number of samples for the current frame
- *samples = mlt_sample_calculator( fps, *frequency, expected ++ );
-
- while( *samples > audio_used )
- {
- // Read the samples
- int bytes = ov_read( ov, ( char * )( &audio_buffer[ audio_used * 2 ] ), 4096, 0, 2, 1, ¤t_section );
-
- // Break if error or eof
- if ( bytes <= 0 )
- break;
-
- // Increment number of samples used
- audio_used += bytes / ( sizeof( int16_t ) * *channels );
-
- // Handle ignore
- while ( ignore && audio_used >= *samples )
- {
- ignore --;
- audio_used -= *samples;
- memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * sizeof( int16_t ) );
- *samples = mlt_sample_calculator( fps, *frequency, expected ++ );
- }
- }
-
- // Now handle the audio if we have enough
- if ( audio_used >= *samples )
- {
- *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
- memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
- audio_used -= *samples;
- memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, mlt_pool_release, NULL );
- }
- else
- {
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- audio_used = 0;
- }
-
- // Store the number of audio samples still available
- mlt_properties_set_int( properties, "audio_used", audio_used );
- }
- else
- {
- // Get silence and don't touch the context
- *samples = mlt_sample_calculator( fps, *frequency, position );
- mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- }
-
- // Regardless of speed, we expect to get the next frame (cos we ain't too bright)
- mlt_properties_set_position( properties, "audio_expected", position + 1 );
-
- return 0;
-}
-
-/** Our get frame implementation.
-*/
-
-static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
-{
- // Create an empty frame
- *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-
- // Update timecode on the frame we're creating
- mlt_frame_set_position( *frame, mlt_producer_position( this ) );
-
- // Set the position of this producer
- mlt_properties frame_properties = MLT_FRAME_PROPERTIES( *frame );
- mlt_properties_set_position( frame_properties, "vorbis_position", mlt_producer_frame( this ) );
-
- // Set up the audio
- mlt_frame_push_audio( *frame, this );
- mlt_frame_push_audio( *frame, producer_get_audio );
-
- // Pass audio properties to the frame
- mlt_properties_pass_list( frame_properties, MLT_PRODUCER_PROPERTIES( this ), "frequency, channels" );
-
- // Calculate the next timecode
- mlt_producer_prepare_next( this );
-
- return 0;
-}
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltwestley$(LIBSUF)
-
-OBJS = factory.o \
- consumer_westley.o \
- producer_westley.o
-
-CFLAGS += -I../..
-CFLAGS += `xml2-config --cflags`
-
-LDFLAGS += -L../../framework -lmlt
-LDFLAGS += `xml2-config --libs`
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
- install -m 644 westley.dtd "$(DESTDIR)$(prefix)/share/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#!/bin/sh
-
-if [ "$help" != "1" ]
-then
-
- which xml2-config > /dev/null 2>&1
- disable_xml2=$?
-
- if [ "$disable_xml2" != "0" ]
- then
- echo "- xml2 not found: disabling westley modules"
- touch ../disable-westley
- fi
- exit 0
-fi
-
+++ /dev/null
-/*
- * consumer_westley.c -- a libxml2 serialiser of mlt service networks
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <framework/mlt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <libxml/tree.h>
-
-#define ID_SIZE 128
-
-#define _x (const xmlChar*)
-#define _s (const char*)
-
-// This maintains counters for adding ids to elements
-struct serialise_context_s
-{
- mlt_properties id_map;
- int producer_count;
- int multitrack_count;
- int playlist_count;
- int tractor_count;
- int filter_count;
- int transition_count;
- int pass;
- mlt_properties hide_map;
- char *root;
- char *store;
-};
-typedef struct serialise_context_s* serialise_context;
-
-/** Forward references to static functions.
-*/
-
-static int consumer_start( mlt_consumer parent );
-static int consumer_is_stopped( mlt_consumer this );
-static void serialise_service( serialise_context context, mlt_service service, xmlNode *node );
-
-typedef enum
-{
- westley_existing,
- westley_producer,
- westley_multitrack,
- westley_playlist,
- westley_tractor,
- westley_filter,
- westley_transition
-}
-westley_type;
-
-/** Create or retrieve an id associated to this service.
-*/
-
-static char *westley_get_id( serialise_context context, mlt_service service, westley_type type )
-{
- char *id = NULL;
- int i = 0;
- mlt_properties map = context->id_map;
-
- // Search the map for the service
- for ( i = 0; i < mlt_properties_count( map ); i ++ )
- if ( mlt_properties_get_data_at( map, i, NULL ) == service )
- break;
-
- // If the service is not in the map, and the type indicates a new id is needed...
- if ( i >= mlt_properties_count( map ) && type != westley_existing )
- {
- // Attempt to reuse existing id
- id = mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "id" );
-
- // If no id, or the id is used in the map (for another service), then
- // create a new one.
- if ( id == NULL || mlt_properties_get_data( map, id, NULL ) != NULL )
- {
- char temp[ ID_SIZE ];
- do
- {
- switch( type )
- {
- case westley_producer:
- sprintf( temp, "producer%d", context->producer_count ++ );
- break;
- case westley_multitrack:
- sprintf( temp, "multitrack%d", context->multitrack_count ++ );
- break;
- case westley_playlist:
- sprintf( temp, "playlist%d", context->playlist_count ++ );
- break;
- case westley_tractor:
- sprintf( temp, "tractor%d", context->tractor_count ++ );
- break;
- case westley_filter:
- sprintf( temp, "filter%d", context->filter_count ++ );
- break;
- case westley_transition:
- sprintf( temp, "transition%d", context->transition_count ++ );
- break;
- case westley_existing:
- // Never gets here
- break;
- }
- }
- while( mlt_properties_get_data( map, temp, NULL ) != NULL );
-
- // Set the data at the generated name
- mlt_properties_set_data( map, temp, service, 0, NULL, NULL );
-
- // Get the pointer to the name (i is the end of the list)
- id = mlt_properties_get_name( map, i );
- }
- else
- {
- // Store the existing id in the map
- mlt_properties_set_data( map, id, service, 0, NULL, NULL );
- }
- }
- else if ( type == westley_existing )
- {
- id = mlt_properties_get_name( map, i );
- }
-
- return id;
-}
-
-/** This is what will be called by the factory - anything can be passed in
- via the argument, but keep it simple.
-*/
-
-mlt_consumer consumer_westley_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- // Create the consumer object
- mlt_consumer this = calloc( sizeof( struct mlt_consumer_s ), 1 );
-
- // If no malloc'd and consumer init ok
- if ( this != NULL && mlt_consumer_init( this, NULL, profile ) == 0 )
- {
- // Allow thread to be started/stopped
- this->start = consumer_start;
- this->is_stopped = consumer_is_stopped;
-
- mlt_properties_set( MLT_CONSUMER_PROPERTIES( this ), "resource", arg );
-
- // Return the consumer produced
- return this;
- }
-
- // malloc or consumer init failed
- free( this );
-
- // Indicate failure
- return NULL;
-}
-
-static void serialise_properties( serialise_context context, mlt_properties properties, xmlNode *node )
-{
- int i;
- xmlNode *p;
-
- // Enumerate the properties
- for ( i = 0; i < mlt_properties_count( properties ); i++ )
- {
- char *name = mlt_properties_get_name( properties, i );
- if ( name != NULL &&
- name[ 0 ] != '_' &&
- mlt_properties_get_value( properties, i ) != NULL &&
- strcmp( name, "westley" ) != 0 &&
- strcmp( name, "in" ) != 0 &&
- strcmp( name, "out" ) != 0 &&
- strcmp( name, "id" ) != 0 &&
- strcmp( name, "title" ) != 0 &&
- strcmp( name, "root" ) != 0 &&
- strcmp( name, "width" ) != 0 &&
- strcmp( name, "height" ) != 0 )
- {
- char *value = mlt_properties_get_value( properties, i );
- if ( strcmp( context->root, "" ) && !strncmp( value, context->root, strlen( context->root ) ) )
- value += strlen( context->root ) + 1;
- p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
- xmlNewProp( p, _x("name"), _x(name) );
- }
- }
-}
-
-static void serialise_store_properties( serialise_context context, mlt_properties properties, xmlNode *node, const char *store )
-{
- int i;
- xmlNode *p;
-
- // Enumerate the properties
- for ( i = 0; store != NULL && i < mlt_properties_count( properties ); i++ )
- {
- char *name = mlt_properties_get_name( properties, i );
- if ( !strncmp( name, store, strlen( store ) ) )
- {
- char *value = mlt_properties_get_value( properties, i );
- if ( value != NULL )
- {
- if ( strcmp( context->root, "" ) && !strncmp( value, context->root, strlen( context->root ) ) )
- value += strlen( context->root ) + 1;
- p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
- xmlNewProp( p, _x("name"), _x(name) );
- }
- }
- }
-}
-
-static inline void serialise_service_filters( serialise_context context, mlt_service service, xmlNode *node )
-{
- int i;
- xmlNode *p;
- mlt_filter filter = NULL;
-
- // Enumerate the filters
- for ( i = 0; ( filter = mlt_producer_filter( MLT_PRODUCER( service ), i ) ) != NULL; i ++ )
- {
- mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
- if ( mlt_properties_get_int( properties, "_fezzik" ) == 0 )
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, MLT_FILTER_SERVICE( filter ), westley_filter );
- if ( id != NULL )
- {
- int in = mlt_properties_get_position( properties, "in" );
- int out = mlt_properties_get_position( properties, "out" );
- p = xmlNewChild( node, NULL, _x("filter"), NULL );
- xmlNewProp( p, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( p, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- if ( in != 0 || out != 0 )
- {
- char temp[ 20 ];
- sprintf( temp, "%d", in );
- xmlNewProp( p, _x("in"), _x(temp) );
- sprintf( temp, "%d", out );
- xmlNewProp( p, _x("out"), _x(temp) );
- }
- serialise_properties( context, properties, p );
- serialise_service_filters( context, MLT_FILTER_SERVICE( filter ), p );
- }
- }
- }
-}
-
-static void serialise_producer( serialise_context context, mlt_service service, xmlNode *node )
-{
- xmlNode *child = node;
- mlt_service parent = MLT_SERVICE( mlt_producer_cut_parent( MLT_PRODUCER( service ) ) );
-
- if ( context->pass == 0 )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( parent );
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, parent, westley_producer );
- if ( id == NULL )
- return;
-
- child = xmlNewChild( node, NULL, _x("producer"), NULL );
-
- // Set the id
- xmlNewProp( child, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( child, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- xmlNewProp( child, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( child, _x("out"), _x(mlt_properties_get( properties, "out" )) );
- serialise_properties( context, properties, child );
- serialise_service_filters( context, service, child );
-
- // Add producer to the map
- mlt_properties_set_int( context->hide_map, id, mlt_properties_get_int( properties, "hide" ) );
- }
- else
- {
- char *id = westley_get_id( context, parent, westley_existing );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- xmlNewProp( node, _x("parent"), _x(id) );
- xmlNewProp( node, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( node, _x("out"), _x(mlt_properties_get( properties, "out" )) );
- }
-}
-
-static void serialise_tractor( serialise_context context, mlt_service service, xmlNode *node );
-
-static void serialise_multitrack( serialise_context context, mlt_service service, xmlNode *node )
-{
- int i;
-
- if ( context->pass == 0 )
- {
- // Iterate over the tracks to collect the producers
- for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ )
- {
- mlt_producer producer = mlt_producer_cut_parent( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) );
- serialise_service( context, MLT_SERVICE( producer ), node );
- }
- }
- else
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, service, westley_multitrack );
- if ( id == NULL )
- return;
-
- // Serialise the tracks
- for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ )
- {
- xmlNode *track = xmlNewChild( node, NULL, _x("track"), NULL );
- int hide = 0;
- mlt_producer producer = mlt_multitrack_track( MLT_MULTITRACK( service ), i );
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
-
- mlt_service parent = MLT_SERVICE( mlt_producer_cut_parent( producer ) );
-
- char *id = westley_get_id( context, MLT_SERVICE( parent ), westley_existing );
- xmlNewProp( track, _x("producer"), _x(id) );
- if ( mlt_producer_is_cut( producer ) )
- {
- xmlNewProp( track, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( track, _x("out"), _x(mlt_properties_get( properties, "out" )) );
- serialise_store_properties( context, MLT_PRODUCER_PROPERTIES( producer ), track, context->store );
- serialise_store_properties( context, MLT_PRODUCER_PROPERTIES( producer ), track, "meta." );
- serialise_service_filters( context, MLT_PRODUCER_SERVICE( producer ), track );
- }
-
- hide = mlt_properties_get_int( context->hide_map, id );
- if ( hide )
- xmlNewProp( track, _x("hide"), _x( hide == 1 ? "video" : ( hide == 2 ? "audio" : "both" ) ) );
- }
- serialise_service_filters( context, service, node );
- }
-}
-
-static void serialise_playlist( serialise_context context, mlt_service service, xmlNode *node )
-{
- int i;
- xmlNode *child = node;
- mlt_playlist_clip_info info;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- if ( context->pass == 0 )
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, service, westley_playlist );
- if ( id == NULL )
- return;
-
- // Iterate over the playlist entries to collect the producers
- for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ )
- {
- if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) )
- {
- if ( info.producer != NULL )
- {
- mlt_producer producer = mlt_producer_cut_parent( info.producer );
- char *service_s = mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "mlt_service" );
- char *resource_s = mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "resource" );
- if ( resource_s != NULL && !strcmp( resource_s, "<playlist>" ) )
- serialise_playlist( context, MLT_SERVICE( producer ), node );
- else if ( service_s != NULL && strcmp( service_s, "blank" ) != 0 )
- serialise_service( context, MLT_SERVICE( producer ), node );
- }
- }
- }
-
- child = xmlNewChild( node, NULL, _x("playlist"), NULL );
-
- // Set the id
- xmlNewProp( child, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( child, _x("title"), _x(mlt_properties_get( properties, "title" )) );
-
- // Store application specific properties
- serialise_store_properties( context, properties, child, context->store );
- serialise_store_properties( context, properties, child, "meta." );
-
- // Add producer to the map
- mlt_properties_set_int( context->hide_map, id, mlt_properties_get_int( properties, "hide" ) );
-
- // Iterate over the playlist entries
- for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ )
- {
- if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) )
- {
- mlt_producer producer = mlt_producer_cut_parent( info.producer );
- char *service_s = mlt_properties_get( MLT_PRODUCER_PROPERTIES( producer ), "mlt_service" );
- if ( service_s != NULL && strcmp( service_s, "blank" ) == 0 )
- {
- char length[ 20 ];
- length[ 19 ] = '\0';
- xmlNode *entry = xmlNewChild( child, NULL, _x("blank"), NULL );
- snprintf( length, 19, "%d", (int)info.frame_count );
- xmlNewProp( entry, _x("length"), _x(length) );
- }
- else
- {
- char temp[ 20 ];
- xmlNode *entry = xmlNewChild( child, NULL, _x("entry"), NULL );
- id = westley_get_id( context, MLT_SERVICE( producer ), westley_existing );
- xmlNewProp( entry, _x("producer"), _x(id) );
- sprintf( temp, "%d", (int)info.frame_in );
- xmlNewProp( entry, _x("in"), _x(temp) );
- sprintf( temp, "%d", (int)info.frame_out );
- xmlNewProp( entry, _x("out"), _x(temp) );
- if ( info.repeat > 1 )
- {
- sprintf( temp, "%d", info.repeat );
- xmlNewProp( entry, _x("repeat"), _x(temp) );
- }
- if ( mlt_producer_is_cut( info.cut ) )
- {
- serialise_store_properties( context, MLT_PRODUCER_PROPERTIES( info.cut ), entry, context->store );
- serialise_store_properties( context, MLT_PRODUCER_PROPERTIES( info.cut ), entry, "meta." );
- serialise_service_filters( context, MLT_PRODUCER_SERVICE( info.cut ), entry );
- }
- }
- }
- }
-
- serialise_service_filters( context, service, child );
- }
- else if ( xmlStrcmp( node->name, _x("tractor") ) != 0 )
- {
- char *id = westley_get_id( context, service, westley_existing );
- xmlNewProp( node, _x("producer"), _x(id) );
- }
-}
-
-static void serialise_tractor( serialise_context context, mlt_service service, xmlNode *node )
-{
- xmlNode *child = node;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- if ( context->pass == 0 )
- {
- // Recurse on connected producer
- serialise_service( context, mlt_service_producer( service ), node );
- }
- else
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, service, westley_tractor );
- if ( id == NULL )
- return;
-
- child = xmlNewChild( node, NULL, _x("tractor"), NULL );
-
- // Set the id
- xmlNewProp( child, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( child, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- if ( mlt_properties_get( properties, "global_feed" ) )
- xmlNewProp( child, _x("global_feed"), _x(mlt_properties_get( properties, "global_feed" )) );
- xmlNewProp( child, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( child, _x("out"), _x(mlt_properties_get( properties, "out" )) );
-
- // Store application specific properties
- serialise_store_properties( context, MLT_SERVICE_PROPERTIES( service ), child, context->store );
- serialise_store_properties( context, MLT_SERVICE_PROPERTIES( service ), child, "meta." );
-
- // Recurse on connected producer
- serialise_service( context, mlt_service_producer( service ), child );
- serialise_service_filters( context, service, child );
- }
-}
-
-static void serialise_filter( serialise_context context, mlt_service service, xmlNode *node )
-{
- xmlNode *child = node;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- // Recurse on connected producer
- serialise_service( context, mlt_service_producer( service ), node );
-
- if ( context->pass == 1 )
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, service, westley_filter );
- if ( id == NULL )
- return;
-
- child = xmlNewChild( node, NULL, _x("filter"), NULL );
-
- // Set the id
- xmlNewProp( child, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( child, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- xmlNewProp( child, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( child, _x("out"), _x(mlt_properties_get( properties, "out" )) );
-
- serialise_properties( context, properties, child );
- serialise_service_filters( context, service, child );
- }
-}
-
-static void serialise_transition( serialise_context context, mlt_service service, xmlNode *node )
-{
- xmlNode *child = node;
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- // Recurse on connected producer
- serialise_service( context, MLT_SERVICE( MLT_TRANSITION( service )->producer ), node );
-
- if ( context->pass == 1 )
- {
- // Get a new id - if already allocated, do nothing
- char *id = westley_get_id( context, service, westley_transition );
- if ( id == NULL )
- return;
-
- child = xmlNewChild( node, NULL, _x("transition"), NULL );
-
- // Set the id
- xmlNewProp( child, _x("id"), _x(id) );
- if ( mlt_properties_get( properties, "title" ) )
- xmlNewProp( child, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- xmlNewProp( child, _x("in"), _x(mlt_properties_get( properties, "in" )) );
- xmlNewProp( child, _x("out"), _x(mlt_properties_get( properties, "out" )) );
-
- serialise_properties( context, properties, child );
- serialise_service_filters( context, service, child );
- }
-}
-
-static void serialise_service( serialise_context context, mlt_service service, xmlNode *node )
-{
- // Iterate over consumer/producer connections
- while ( service != NULL )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- char *mlt_type = mlt_properties_get( properties, "mlt_type" );
-
- // Tell about the producer
- if ( strcmp( mlt_type, "producer" ) == 0 )
- {
- char *mlt_service = mlt_properties_get( properties, "mlt_service" );
- if ( mlt_properties_get( properties, "westley" ) == NULL && ( mlt_service != NULL && !strcmp( mlt_service, "tractor" ) ) )
- {
- context->pass = 0;
- serialise_tractor( context, service, node );
- context->pass = 1;
- serialise_tractor( context, service, node );
- context->pass = 0;
- break;
- }
- else
- {
- serialise_producer( context, service, node );
- }
- if ( mlt_properties_get( properties, "westley" ) != NULL )
- break;
- }
-
- // Tell about the framework container producers
- else if ( strcmp( mlt_type, "mlt_producer" ) == 0 )
- {
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Recurse on multitrack's tracks
- if ( strcmp( resource, "<multitrack>" ) == 0 )
- {
- serialise_multitrack( context, service, node );
- break;
- }
-
- // Recurse on playlist's clips
- else if ( strcmp( resource, "<playlist>" ) == 0 )
- {
- serialise_playlist( context, service, node );
- }
-
- // Recurse on tractor's producer
- else if ( strcmp( resource, "<tractor>" ) == 0 )
- {
- context->pass = 0;
- serialise_tractor( context, service, node );
- context->pass = 1;
- serialise_tractor( context, service, node );
- context->pass = 0;
- break;
- }
-
- // Treat it as a normal producer
- else
- {
- serialise_producer( context, service, node );
- }
- }
-
- // Tell about a filter
- else if ( strcmp( mlt_type, "filter" ) == 0 )
- {
- serialise_filter( context, service, node );
- break;
- }
-
- // Tell about a transition
- else if ( strcmp( mlt_type, "transition" ) == 0 )
- {
- serialise_transition( context, service, node );
- break;
- }
-
- // Get the next connected service
- service = mlt_service_producer( service );
- }
-}
-
-xmlDocPtr westley_make_doc( mlt_consumer consumer, mlt_service service )
-{
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- xmlDocPtr doc = xmlNewDoc( _x("1.0") );
- xmlNodePtr root = xmlNewNode( NULL, _x("westley") );
- struct serialise_context_s *context = calloc( 1, sizeof( struct serialise_context_s ) );
-
- xmlDocSetRootElement( doc, root );
-
- // If we have root, then deal with it now
- if ( mlt_properties_get( properties, "root" ) != NULL )
- {
- xmlNewProp( root, _x("root"), _x(mlt_properties_get( properties, "root" )) );
- context->root = strdup( mlt_properties_get( properties, "root" ) );
- }
- else
- {
- context->root = strdup( "" );
- }
-
- // Assign the additional 'storage' pattern for properties
- context->store = mlt_properties_get( MLT_CONSUMER_PROPERTIES( consumer ), "store" );
-
- // Assign a title property
- if ( mlt_properties_get( properties, "title" ) != NULL )
- xmlNewProp( root, _x("title"), _x(mlt_properties_get( properties, "title" )) );
- mlt_properties_set_int( properties, "global_feed", 1 );
-
- // Construct the context maps
- context->id_map = mlt_properties_new();
- context->hide_map = mlt_properties_new();
-
- // Ensure producer is a framework producer
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "mlt_type", "mlt_producer" );
-
- // In pass one, we serialise the end producers and playlists,
- // adding them to a map keyed by address.
- serialise_service( context, service, root );
-
- // In pass two, we serialise the tractor and reference the
- // producers and playlists
- context->pass++;
- serialise_service( context, service, root );
-
- // Cleanup resource
- mlt_properties_close( context->id_map );
- mlt_properties_close( context->hide_map );
- free( context->root );
- free( context );
-
- return doc;
-}
-
-static int consumer_start( mlt_consumer this )
-{
- xmlDocPtr doc = NULL;
-
- // Get the producer service
- mlt_service service = mlt_service_producer( MLT_CONSUMER_SERVICE( this ) );
- if ( service != NULL )
- {
- mlt_properties properties = MLT_CONSUMER_PROPERTIES( this );
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Set the title if provided
- if ( mlt_properties_get( properties, "title" ) )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", mlt_properties_get( properties, "title" ) );
- else if ( mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "title" ) == NULL )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "title", "Anonymous Submission" );
-
- // Check for a root on the consumer properties and pass to service
- if ( mlt_properties_get( properties, "root" ) )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", mlt_properties_get( properties, "root" ) );
-
- // Specify roots in other cases...
- if ( resource != NULL && mlt_properties_get( properties, "root" ) == NULL )
- {
- // Get the current working directory
- char *cwd = getcwd( NULL, 0 );
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "root", cwd );
- free( cwd );
- }
-
- // Make the document
- doc = westley_make_doc( this, service );
-
- // Handle the output
- if ( resource == NULL || !strcmp( resource, "" ) )
- {
- xmlDocFormatDump( stdout, doc, 1 );
- }
- else if ( strchr( resource, '.' ) == NULL )
- {
- xmlChar *buffer = NULL;
- int length = 0;
- xmlDocDumpMemoryEnc( doc, &buffer, &length, "utf-8" );
- mlt_properties_set( properties, resource, _s(buffer) );
- xmlFree( buffer );
- }
- else
- {
- xmlSaveFormatFileEnc( resource, doc, "utf-8", 1 );
- }
-
- // Close the document
- xmlFreeDoc( doc );
- }
-
- mlt_consumer_stop( this );
-
- mlt_consumer_stopped( this );
-
- return 0;
-}
-
-static int consumer_is_stopped( mlt_consumer this )
-{
- return 1;
-}
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_consumer consumer_westley_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-extern mlt_producer producer_westley_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( consumer_type, "westley", consumer_westley_init );
- MLT_REGISTER( producer_type, "westley", producer_westley_init );
- MLT_REGISTER( producer_type, "westley-xml", producer_westley_init );
-}
+++ /dev/null
-/*
- * producer_westley.c -- a libxml2 parser of mlt service networks
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Dan Dennedy <dan@dennedy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-// TODO: destroy unreferenced producers (they are currently destroyed
-// when the returned producer is closed).
-
-#include <framework/mlt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h> // for xmlCreateFileParserCtxt
-#include <libxml/tree.h>
-
-#define STACK_SIZE 1000
-#define BRANCH_SIG_LEN 4000
-
-#define _x (const xmlChar*)
-#define _s (const char*)
-
-#undef DEBUG
-#ifdef DEBUG
-extern xmlDocPtr westley_make_doc( mlt_service service );
-#endif
-
-enum service_type
-{
- mlt_invalid_type,
- mlt_unknown_type,
- mlt_producer_type,
- mlt_playlist_type,
- mlt_entry_type,
- mlt_tractor_type,
- mlt_multitrack_type,
- mlt_filter_type,
- mlt_transition_type,
- mlt_consumer_type,
- mlt_field_type,
- mlt_services_type,
- mlt_dummy_filter_type,
- mlt_dummy_transition_type,
- mlt_dummy_producer_type,
-};
-
-struct deserialise_context_s
-{
- enum service_type stack_types[ STACK_SIZE ];
- mlt_service stack_service[ STACK_SIZE ];
- int stack_service_size;
- mlt_properties producer_map;
- mlt_properties destructors;
- char *property;
- int is_value;
- xmlDocPtr value_doc;
- xmlNodePtr stack_node[ STACK_SIZE ];
- int stack_node_size;
- xmlDocPtr entity_doc;
- int entity_is_replace;
- int depth;
- int branch[ STACK_SIZE ];
- const xmlChar *publicId;
- const xmlChar *systemId;
- mlt_properties params;
- mlt_profile profile;
-};
-typedef struct deserialise_context_s *deserialise_context;
-
-/** Convert the numerical current branch address to a dot-delimited string.
-*/
-static char *serialise_branch( deserialise_context this, char *s )
-{
- int i;
-
- s[0] = 0;
- for ( i = 0; i < this->depth; i++ )
- {
- int len = strlen( s );
- snprintf( s + len, BRANCH_SIG_LEN - len, "%d.", this->branch[ i ] );
- }
- return s;
-}
-
-/** Push a service.
-*/
-
-static int context_push_service( deserialise_context this, mlt_service that, enum service_type type )
-{
- int ret = this->stack_service_size >= STACK_SIZE - 1;
- if ( ret == 0 )
- {
- this->stack_service[ this->stack_service_size ] = that;
- this->stack_types[ this->stack_service_size++ ] = type;
-
- // Record the tree branch on which this service lives
- if ( that != NULL && mlt_properties_get( MLT_SERVICE_PROPERTIES( that ), "_westley_branch" ) == NULL )
- {
- char s[ BRANCH_SIG_LEN ];
- mlt_properties_set( MLT_SERVICE_PROPERTIES( that ), "_westley_branch", serialise_branch( this, s ) );
- }
- }
- return ret;
-}
-
-/** Pop a service.
-*/
-
-static mlt_service context_pop_service( deserialise_context this, enum service_type *type )
-{
- mlt_service result = NULL;
- if ( this->stack_service_size > 0 )
- {
- result = this->stack_service[ -- this->stack_service_size ];
- if ( type != NULL )
- *type = this->stack_types[ this->stack_service_size ];
- }
- return result;
-}
-
-/** Push a node.
-*/
-
-static int context_push_node( deserialise_context this, xmlNodePtr node )
-{
- int ret = this->stack_node_size >= STACK_SIZE - 1;
- if ( ret == 0 )
- this->stack_node[ this->stack_node_size ++ ] = node;
- return ret;
-}
-
-/** Pop a node.
-*/
-
-static xmlNodePtr context_pop_node( deserialise_context this )
-{
- xmlNodePtr result = NULL;
- if ( this->stack_node_size > 0 )
- result = this->stack_node[ -- this->stack_node_size ];
- return result;
-}
-
-
-// Set the destructor on a new service
-static void track_service( mlt_properties properties, void *service, mlt_destructor destructor )
-{
- int registered = mlt_properties_get_int( properties, "registered" );
- char *key = mlt_properties_get( properties, "registered" );
- mlt_properties_set_data( properties, key, service, 0, destructor, NULL );
- mlt_properties_set_int( properties, "registered", ++ registered );
-}
-
-
-// Prepend the property value with the document root
-static inline void qualify_property( deserialise_context context, mlt_properties properties, const char *name )
-{
- char *resource = mlt_properties_get( properties, name );
- if ( resource != NULL && resource[0] )
- {
- // Qualify file name properties
- char *root = mlt_properties_get( context->producer_map, "root" );
- if ( root != NULL && strcmp( root, "" ) )
- {
- char *full_resource = malloc( strlen( root ) + strlen( resource ) + 2 );
- if ( resource[ 0 ] != '/' && strchr( resource, ':' ) == NULL )
- {
- strcpy( full_resource, root );
- strcat( full_resource, "/" );
- strcat( full_resource, resource );
- }
- else
- {
- strcpy( full_resource, resource );
- }
- mlt_properties_set( properties, name, full_resource );
- free( full_resource );
- }
- }
-}
-
-
-/** This function adds a producer to a playlist or multitrack when
- there is no entry or track element.
-*/
-
-static int add_producer( deserialise_context context, mlt_service service, mlt_position in, mlt_position out )
-{
- // Return value (0 = service remains top of stack, 1 means it can be removed)
- int result = 0;
-
- // Get the parent producer
- enum service_type type = mlt_invalid_type;
- mlt_service container = context_pop_service( context, &type );
- int contained = 0;
-
- if ( service != NULL && container != NULL )
- {
- char *container_branch = mlt_properties_get( MLT_SERVICE_PROPERTIES( container ), "_westley_branch" );
- char *service_branch = mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "_westley_branch" );
- contained = !strncmp( container_branch, service_branch, strlen( container_branch ) );
- }
-
- if ( contained )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- char *hide_s = mlt_properties_get( properties, "hide" );
-
- // Indicate that this service is no longer top of stack
- result = 1;
-
- switch( type )
- {
- case mlt_tractor_type:
- {
- mlt_multitrack multitrack = mlt_tractor_multitrack( MLT_TRACTOR( container ) );
- mlt_multitrack_connect( multitrack, MLT_PRODUCER( service ), mlt_multitrack_count( multitrack ) );
- }
- break;
- case mlt_multitrack_type:
- {
- mlt_multitrack_connect( MLT_MULTITRACK( container ),
- MLT_PRODUCER( service ),
- mlt_multitrack_count( MLT_MULTITRACK( container ) ) );
- }
- break;
- case mlt_playlist_type:
- {
- mlt_playlist_append_io( MLT_PLAYLIST( container ), MLT_PRODUCER( service ), in, out );
- }
- break;
- default:
- result = 0;
- fprintf( stderr, "Producer defined inside something that isn't a container\n" );
- break;
- };
-
- // Set the hide state of the track producer
- if ( hide_s != NULL )
- {
- if ( strcmp( hide_s, "video" ) == 0 )
- mlt_properties_set_int( properties, "hide", 1 );
- else if ( strcmp( hide_s, "audio" ) == 0 )
- mlt_properties_set_int( properties, "hide", 2 );
- else if ( strcmp( hide_s, "both" ) == 0 )
- mlt_properties_set_int( properties, "hide", 3 );
- }
- }
-
- // Put the parent producer back
- if ( container != NULL )
- context_push_service( context, container, type );
-
- return result;
-}
-
-/** Attach filters defined on that to this.
-*/
-
-static void attach_filters( mlt_service this, mlt_service that )
-{
- if ( that != NULL )
- {
- int i = 0;
- mlt_filter filter = NULL;
- for ( i = 0; ( filter = mlt_service_filter( that, i ) ) != NULL; i ++ )
- {
- mlt_service_attach( this, filter );
- attach_filters( MLT_FILTER_SERVICE( filter ), MLT_FILTER_SERVICE( filter ) );
- }
- }
-}
-
-static void on_start_tractor( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- mlt_tractor tractor = mlt_tractor_new( );
- mlt_service service = MLT_TRACTOR_SERVICE( tractor );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- track_service( context->destructors, service, (mlt_destructor) mlt_tractor_close );
-
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-
- mlt_properties_set_int( MLT_TRACTOR_PROPERTIES( tractor ), "global_feed", 1 );
-
- if ( mlt_properties_get( properties, "id" ) != NULL )
- mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL );
-
- context_push_service( context, service, mlt_tractor_type );
-}
-
-static void on_end_tractor( deserialise_context context, const xmlChar *name )
-{
- // Get the tractor
- enum service_type type;
- mlt_service tractor = context_pop_service( context, &type );
-
- if ( tractor != NULL && type == mlt_tractor_type )
- {
- // See if the tractor should be added to a playlist or multitrack
- if ( add_producer( context, tractor, 0, mlt_producer_get_out( MLT_PRODUCER( tractor ) ) ) == 0 )
- context_push_service( context, tractor, type );
- }
- else
- {
- fprintf( stderr, "Invalid state for tractor\n" );
- }
-}
-
-static void on_start_multitrack( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- enum service_type type;
- mlt_service parent = context_pop_service( context, &type );
-
- // If we don't have a parent, then create one now, providing we're in a state where we can
- if ( parent == NULL || ( type == mlt_playlist_type || type == mlt_multitrack_type ) )
- {
- mlt_tractor tractor = NULL;
- // Push the parent back
- if ( parent != NULL )
- context_push_service( context, parent, type );
-
- // Create a tractor to contain the multitrack
- tractor = mlt_tractor_new( );
- parent = MLT_TRACTOR_SERVICE( tractor );
- track_service( context->destructors, parent, (mlt_destructor) mlt_tractor_close );
- type = mlt_tractor_type;
-
- // Flag it as a synthesised tractor for clean up later
- mlt_properties_set_int( MLT_SERVICE_PROPERTIES( parent ), "fezzik_synth", 1 );
- }
-
- if ( type == mlt_tractor_type )
- {
- mlt_service service = MLT_SERVICE( mlt_tractor_multitrack( MLT_TRACTOR( parent ) ) );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-
- if ( mlt_properties_get( properties, "id" ) != NULL )
- mlt_properties_set_data( context->producer_map, mlt_properties_get( properties,"id" ), service, 0, NULL, NULL );
-
- context_push_service( context, parent, type );
- context_push_service( context, service, mlt_multitrack_type );
- }
- else
- {
- fprintf( stderr, "Invalid multitrack position\n" );
- }
-}
-
-static void on_end_multitrack( deserialise_context context, const xmlChar *name )
-{
- // Get the multitrack from the stack
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
-
- if ( service == NULL || type != mlt_multitrack_type )
- fprintf( stderr, "End multitrack in the wrong state...\n" );
-}
-
-static void on_start_playlist( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- mlt_playlist playlist = mlt_playlist_init( );
- mlt_service service = MLT_PLAYLIST_SERVICE( playlist );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- track_service( context->destructors, service, (mlt_destructor) mlt_playlist_close );
-
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- {
- mlt_properties_set( properties, (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-
- // Out will be overwritten later as we append, so we need to save it
- if ( xmlStrcmp( atts[ 0 ], _x("out") ) == 0 )
- mlt_properties_set( properties, "_westley.out", ( const char* )atts[ 1 ] );
- }
-
- if ( mlt_properties_get( properties, "id" ) != NULL )
- mlt_properties_set_data( context->producer_map, mlt_properties_get( properties, "id" ), service, 0, NULL, NULL );
-
- context_push_service( context, service, mlt_playlist_type );
-}
-
-static void on_end_playlist( deserialise_context context, const xmlChar *name )
-{
- // Get the playlist from the stack
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
-
- if ( service != NULL && type == mlt_playlist_type )
- {
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- mlt_position in = mlt_properties_get_position( properties, "in" );
- mlt_position out = mlt_properties_get_position( properties, "out" );
-
- // See if the playlist should be added to a playlist or multitrack
- if ( add_producer( context, service, in, out ) == 0 )
- context_push_service( context, service, type );
- }
- else
- {
- fprintf( stderr, "Invalid state of playlist end\n" );
- }
-}
-
-static void on_start_producer( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- // use a dummy service to hold properties to allow arbitrary nesting
- mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
- mlt_service_init( service, NULL );
-
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- context_push_service( context, service, mlt_dummy_producer_type );
-
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-}
-
-// Parse a SMIL clock value (as produced by Kino 0.9.1) and return position in frames
-static mlt_position parse_clock_value( char *value, double fps )
-{
- // This implementation expects a fully specified clock value - no optional
- // parts (e.g. 1:05)
- char *pos, *copy = strdup( value );
- int hh, mm, ss, ms;
- mlt_position result = -1;
-
- value = copy;
- pos = strchr( value, ':' );
- if ( !pos )
- return result;
- *pos = '\0';
- hh = atoi( value );
- value = pos + 1;
-
- pos = strchr( value, ':' );
- if ( !pos )
- return result;
- *pos = '\0';
- mm = atoi( value );
- value = pos + 1;
-
- pos = strchr( value, '.' );
- if ( !pos )
- return result;
- *pos = '\0';
- ss = atoi( value );
- value = pos + 1;
-
- ms = atoi( value );
- free( copy );
- result = ( fps * ( ( (hh * 3600) + (mm * 60) + ss ) * 1000 + ms ) / 1000 + 0.5 );
-
- return result;
-}
-
-static void on_end_producer( deserialise_context context, const xmlChar *name )
-{
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- if ( service != NULL && type == mlt_dummy_producer_type )
- {
- mlt_service producer = NULL;
-
- qualify_property( context, properties, "resource" );
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Let Kino-SMIL src be a synonym for resource
- if ( resource == NULL )
- {
- qualify_property( context, properties, "src" );
- resource = mlt_properties_get( properties, "src" );
- }
-
- // Instantiate the producer
- if ( mlt_properties_get( properties, "mlt_service" ) != NULL )
- {
- char temp[ 1024 ];
- strncpy( temp, mlt_properties_get( properties, "mlt_service" ), 1024 );
- if ( resource != NULL )
- {
- strcat( temp, ":" );
- strncat( temp, resource, 1023 - strlen( temp ) );
- }
- producer = MLT_SERVICE( mlt_factory_producer( context->profile, "fezzik", temp ) );
- }
-
- // Just in case the plugin requested doesn't exist...
- if ( producer == NULL && resource != NULL )
- producer = MLT_SERVICE( mlt_factory_producer( context->profile, "fezzik", resource ) );
-
- if ( producer == NULL )
- producer = MLT_SERVICE( mlt_factory_producer( context->profile, "fezzik", "+INVALID.txt" ) );
-
- if ( producer == NULL )
- producer = MLT_SERVICE( mlt_factory_producer( context->profile, "fezzik", "colour:red" ) );
-
- // Track this producer
- track_service( context->destructors, producer, (mlt_destructor) mlt_producer_close );
-
- // Propogate the properties
- qualify_property( context, properties, "resource" );
- qualify_property( context, properties, "luma" );
- qualify_property( context, properties, "luma.resource" );
- qualify_property( context, properties, "composite.luma" );
- qualify_property( context, properties, "producer.resource" );
-
- // Handle in/out properties separately
- mlt_position in = -1;
- mlt_position out = -1;
-
- // Get in
- if ( mlt_properties_get( properties, "in" ) != NULL )
- in = mlt_properties_get_position( properties, "in" );
- // Let Kino-SMIL clipBegin be a synonym for in
- if ( mlt_properties_get( properties, "clipBegin" ) != NULL )
- {
- if ( strchr( mlt_properties_get( properties, "clipBegin" ), ':' ) )
- // Parse clock value
- in = parse_clock_value( mlt_properties_get( properties, "clipBegin" ),
- mlt_producer_get_fps( MLT_PRODUCER( producer ) ) );
- else
- // Parse frames value
- in = mlt_properties_get_position( properties, "clipBegin" );
- }
- // Get out
- if ( mlt_properties_get( properties, "out" ) != NULL )
- out = mlt_properties_get_position( properties, "out" );
- // Let Kino-SMIL clipEnd be a synonym for out
- if ( mlt_properties_get( properties, "clipEnd" ) != NULL )
- {
- if ( strchr( mlt_properties_get( properties, "clipEnd" ), ':' ) )
- // Parse clock value
- out = parse_clock_value( mlt_properties_get( properties, "clipEnd" ),
- mlt_producer_get_fps( MLT_PRODUCER( producer ) ) );
- else
- // Parse frames value
- out = mlt_properties_get_position( properties, "clipEnd" );
- }
- // Remove in and out
- mlt_properties_set( properties, "in", NULL );
- mlt_properties_set( properties, "out", NULL );
-
- // Inherit the properties
- mlt_properties_inherit( MLT_SERVICE_PROPERTIES( producer ), properties );
-
- // Attach all filters from service onto producer
- attach_filters( producer, service );
-
- // Add the producer to the producer map
- if ( mlt_properties_get( properties, "id" ) != NULL )
- mlt_properties_set_data( context->producer_map, mlt_properties_get(properties, "id"), producer, 0, NULL, NULL );
-
- // See if the producer should be added to a playlist or multitrack
- if ( add_producer( context, producer, in, out ) == 0 )
- {
- // Otherwise, set in and out on...
- if ( in != -1 || out != -1 )
- {
- // Get the parent service
- enum service_type type;
- mlt_service parent = context_pop_service( context, &type );
- if ( parent != NULL )
- {
- // Get the parent properties
- properties = MLT_SERVICE_PROPERTIES( parent );
-
- char *resource = mlt_properties_get( properties, "resource" );
-
- // Put the parent producer back
- context_push_service( context, parent, type );
-
- // If the parent is a track or entry
- if ( resource && ( strcmp( resource, "<entry>" ) == 0 ) )
- {
- mlt_properties_set_position( properties, "in", in );
- mlt_properties_set_position( properties, "out", out );
- }
- else
- {
- // Otherwise, set in and out on producer directly
- mlt_producer_set_in_and_out( MLT_PRODUCER( producer ), in, out );
- }
- }
- else
- {
- // Otherwise, set in and out on producer directly
- mlt_producer_set_in_and_out( MLT_PRODUCER( producer ), in, out );
- }
- }
-
- // Push the producer onto the stack
- context_push_service( context, producer, mlt_producer_type );
- }
-
- mlt_service_close( service );
- }
-}
-
-static void on_start_blank( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- // Get the playlist from the stack
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_position length = 0;
-
- if ( type == mlt_playlist_type && service != NULL )
- {
- // Look for the length attribute
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- {
- if ( xmlStrcmp( atts[0], _x("length") ) == 0 )
- {
- length = atoll( _s(atts[1]) );
- break;
- }
- }
-
- // Append a blank to the playlist
- mlt_playlist_blank( MLT_PLAYLIST( service ), length - 1 );
-
- // Push the playlist back onto the stack
- context_push_service( context, service, type );
- }
- else
- {
- fprintf( stderr, "blank without a playlist - a definite no no\n" );
- }
-}
-
-static void on_start_entry( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- mlt_producer entry = NULL;
- mlt_properties temp = mlt_properties_new( );
-
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- {
- mlt_properties_set( temp, (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-
- // Look for the producer attribute
- if ( xmlStrcmp( atts[ 0 ], _x("producer") ) == 0 )
- {
- mlt_producer producer = mlt_properties_get_data( context->producer_map, (const char*) atts[1], NULL );
- if ( producer != NULL )
- mlt_properties_set_data( temp, "producer", producer, 0, NULL, NULL );
- }
- }
-
- // If we have a valid entry
- if ( mlt_properties_get_data( temp, "producer", NULL ) != NULL )
- {
- mlt_playlist_clip_info info;
- enum service_type parent_type = invalid_type;
- mlt_service parent = context_pop_service( context, &parent_type );
- mlt_producer producer = mlt_properties_get_data( temp, "producer", NULL );
-
- if ( parent_type == mlt_playlist_type )
- {
- // Append the producer to the playlist
- if ( mlt_properties_get( temp, "in" ) != NULL || mlt_properties_get( temp, "out" ) != NULL )
- {
- mlt_playlist_append_io( MLT_PLAYLIST( parent ), producer,
- mlt_properties_get_position( temp, "in" ),
- mlt_properties_get_position( temp, "out" ) );
- }
- else
- {
- mlt_playlist_append( MLT_PLAYLIST( parent ), producer );
- }
-
- // Handle the repeat property
- if ( mlt_properties_get_int( temp, "repeat" ) > 0 )
- {
- mlt_playlist_repeat_clip( MLT_PLAYLIST( parent ),
- mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1,
- mlt_properties_get_int( temp, "repeat" ) );
- }
-
- mlt_playlist_get_clip_info( MLT_PLAYLIST( parent ), &info, mlt_playlist_count( MLT_PLAYLIST( parent ) ) - 1 );
- entry = info.cut;
- }
- else
- {
- fprintf( stderr, "Entry not part of a playlist...\n" );
- }
-
- context_push_service( context, parent, parent_type );
- }
-
- // Push the cut onto the stack
- context_push_service( context, MLT_PRODUCER_SERVICE( entry ), mlt_entry_type );
-
- mlt_properties_close( temp );
-}
-
-static void on_end_entry( deserialise_context context, const xmlChar *name )
-{
- // Get the entry from the stack
- enum service_type entry_type = invalid_type;
- mlt_service entry = context_pop_service( context, &entry_type );
-
- if ( entry == NULL && entry_type != mlt_entry_type )
- {
- fprintf( stderr, "Invalid state at end of entry\n" );
- }
-}
-
-static void on_start_track( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- // use a dummy service to hold properties to allow arbitrary nesting
- mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
- mlt_service_init( service, NULL );
-
- // Push the dummy service onto the stack
- context_push_service( context, service, mlt_entry_type );
-
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), "resource", "<track>" );
-
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- {
- mlt_properties_set( MLT_SERVICE_PROPERTIES( service ), (const char*) atts[0], atts[1] == NULL ? "" : (const char*) atts[1] );
-
- // Look for the producer attribute
- if ( xmlStrcmp( atts[ 0 ], _x("producer") ) == 0 )
- {
- mlt_producer producer = mlt_properties_get_data( context->producer_map, (const char*) atts[1], NULL );
- if ( producer != NULL )
- mlt_properties_set_data( MLT_SERVICE_PROPERTIES( service ), "producer", producer, 0, NULL, NULL );
- }
- }
-}
-
-static void on_end_track( deserialise_context context, const xmlChar *name )
-{
- // Get the track from the stack
- enum service_type track_type;
- mlt_service track = context_pop_service( context, &track_type );
-
- if ( track != NULL && track_type == mlt_entry_type )
- {
- mlt_properties track_props = MLT_SERVICE_PROPERTIES( track );
- enum service_type parent_type = invalid_type;
- mlt_service parent = context_pop_service( context, &parent_type );
- mlt_multitrack multitrack = NULL;
-
- mlt_producer producer = mlt_properties_get_data( track_props, "producer", NULL );
- mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
-
- if ( parent_type == mlt_tractor_type )
- multitrack = mlt_tractor_multitrack( MLT_TRACTOR( parent ) );
- else if ( parent_type == mlt_multitrack_type )
- multitrack = MLT_MULTITRACK( parent );
- else
- fprintf( stderr, "track contained in an invalid container\n" );
-
- if ( multitrack != NULL )
- {
- // Set producer i/o if specified
- if ( mlt_properties_get( track_props, "in" ) != NULL ||
- mlt_properties_get( track_props, "out" ) != NULL )
- {
- mlt_producer cut = mlt_producer_cut( MLT_PRODUCER( producer ),
- mlt_properties_get_position( track_props, "in" ),
- mlt_properties_get_position( track_props, "out" ) );
- mlt_multitrack_connect( multitrack, cut, mlt_multitrack_count( multitrack ) );
- mlt_properties_inherit( MLT_PRODUCER_PROPERTIES( cut ), track_props );
- track_props = MLT_PRODUCER_PROPERTIES( cut );
- mlt_producer_close( cut );
- }
- else
- {
- mlt_multitrack_connect( multitrack, producer, mlt_multitrack_count( multitrack ) );
- }
-
- // Set the hide state of the track producer
- char *hide_s = mlt_properties_get( track_props, "hide" );
- if ( hide_s != NULL )
- {
- if ( strcmp( hide_s, "video" ) == 0 )
- mlt_properties_set_int( producer_props, "hide", 1 );
- else if ( strcmp( hide_s, "audio" ) == 0 )
- mlt_properties_set_int( producer_props, "hide", 2 );
- else if ( strcmp( hide_s, "both" ) == 0 )
- mlt_properties_set_int( producer_props, "hide", 3 );
- }
- }
-
- if ( parent != NULL )
- context_push_service( context, parent, parent_type );
-
- mlt_service_close( track );
- }
- else
- {
- fprintf( stderr, "Invalid state at end of track\n" );
- }
-}
-
-static void on_start_filter( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- // use a dummy service to hold properties to allow arbitrary nesting
- mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
- mlt_service_init( service, NULL );
-
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- context_push_service( context, service, mlt_dummy_filter_type );
-
- // Set the properties
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (const char*) atts[0], (const char*) atts[1] );
-}
-
-static void on_end_filter( deserialise_context context, const xmlChar *name )
-{
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- enum service_type parent_type = invalid_type;
- mlt_service parent = context_pop_service( context, &parent_type );
-
- if ( service != NULL && type == mlt_dummy_filter_type )
- {
- mlt_service filter = MLT_SERVICE( mlt_factory_filter( context->profile, mlt_properties_get( properties, "mlt_service" ), NULL ) );
- mlt_properties filter_props = MLT_SERVICE_PROPERTIES( filter );
-
- track_service( context->destructors, filter, (mlt_destructor) mlt_filter_close );
-
- // Propogate the properties
- qualify_property( context, properties, "resource" );
- qualify_property( context, properties, "luma" );
- qualify_property( context, properties, "luma.resource" );
- qualify_property( context, properties, "composite.luma" );
- qualify_property( context, properties, "producer.resource" );
- mlt_properties_inherit( filter_props, properties );
-
- // Attach all filters from service onto filter
- attach_filters( filter, service );
-
- // Associate the filter with the parent
- if ( parent != NULL )
- {
- if ( parent_type == mlt_tractor_type )
- {
- mlt_field field = mlt_tractor_field( MLT_TRACTOR( parent ) );
- mlt_field_plant_filter( field, MLT_FILTER( filter ), mlt_properties_get_int( properties, "track" ) );
- mlt_filter_set_in_and_out( MLT_FILTER( filter ),
- mlt_properties_get_int( properties, "in" ),
- mlt_properties_get_int( properties, "out" ) );
- }
- else
- {
- mlt_service_attach( parent, MLT_FILTER( filter ) );
- }
-
- // Put the parent back on the stack
- context_push_service( context, parent, parent_type );
- }
- else
- {
- fprintf( stderr, "filter closed with invalid parent...\n" );
- }
-
- // Close the dummy filter service
- mlt_service_close( service );
- }
- else
- {
- fprintf( stderr, "Invalid top of stack on filter close\n" );
- }
-}
-
-static void on_start_transition( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- // use a dummy service to hold properties to allow arbitrary nesting
- mlt_service service = calloc( 1, sizeof( struct mlt_service_s ) );
- mlt_service_init( service, NULL );
-
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- context_push_service( context, service, mlt_dummy_transition_type );
-
- // Set the properties
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( properties, (const char*) atts[0], (const char*) atts[1] );
-}
-
-static void on_end_transition( deserialise_context context, const xmlChar *name )
-{
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- enum service_type parent_type = invalid_type;
- mlt_service parent = context_pop_service( context, &parent_type );
-
- if ( service != NULL && type == mlt_dummy_transition_type )
- {
- char *id = mlt_properties_get( properties, "mlt_service" );
- mlt_service effect = MLT_SERVICE( mlt_factory_transition( context->profile, id, NULL ) );
- mlt_properties effect_props = MLT_SERVICE_PROPERTIES( effect );
-
- track_service( context->destructors, effect, (mlt_destructor) mlt_transition_close );
-
- // Propogate the properties
- qualify_property( context, properties, "resource" );
- qualify_property( context, properties, "luma" );
- qualify_property( context, properties, "luma.resource" );
- qualify_property( context, properties, "composite.luma" );
- qualify_property( context, properties, "producer.resource" );
- mlt_properties_inherit( effect_props, properties );
-
- // Attach all filters from service onto effect
- attach_filters( effect, service );
-
- // Associate the filter with the parent
- if ( parent != NULL )
- {
- if ( parent_type == mlt_tractor_type )
- {
- mlt_field field = mlt_tractor_field( MLT_TRACTOR( parent ) );
- if ( mlt_properties_get_int( properties, "a_track" ) == mlt_properties_get_int( properties, "b_track" ) )
- mlt_properties_set_int( properties, "b_track", mlt_properties_get_int( properties, "a_track" ) + 1 );
- mlt_field_plant_transition( field, MLT_TRANSITION( effect ),
- mlt_properties_get_int( properties, "a_track" ),
- mlt_properties_get_int( properties, "b_track" ) );
- mlt_transition_set_in_and_out( MLT_TRANSITION( effect ),
- mlt_properties_get_int( properties, "in" ),
- mlt_properties_get_int( properties, "out" ) );
- }
- else
- {
- fprintf( stderr, "Misplaced transition - ignoring\n" );
- }
-
- // Put the parent back on the stack
- context_push_service( context, parent, parent_type );
- }
- else
- {
- fprintf( stderr, "transition closed with invalid parent...\n" );
- }
-
- // Close the dummy filter service
- mlt_service_close( service );
- }
- else
- {
- fprintf( stderr, "Invalid top of stack on transition close\n" );
- }
-}
-
-static void on_start_property( deserialise_context context, const xmlChar *name, const xmlChar **atts)
-{
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
- const char *value = NULL;
-
- if ( service != NULL )
- {
- // Set the properties
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- {
- if ( xmlStrcmp( atts[ 0 ], _x("name") ) == 0 )
- context->property = strdup( _s(atts[ 1 ]) );
- else if ( xmlStrcmp( atts[ 0 ], _x("value") ) == 0 )
- value = _s(atts[ 1 ]);
- }
-
- if ( context->property != NULL )
- mlt_properties_set( properties, context->property, value == NULL ? "" : value );
-
- // Tell parser to collect any further nodes for serialisation
- context->is_value = 1;
-
- context_push_service( context, service, type );
- }
- else
- {
- fprintf( stderr, "Property without a service '%s'?\n", ( const char * )name );
- }
-}
-
-static void on_end_property( deserialise_context context, const xmlChar *name )
-{
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- if ( service != NULL )
- {
- // Tell parser to stop building a tree
- context->is_value = 0;
-
- // See if there is a xml tree for the value
- if ( context->property != NULL && context->value_doc != NULL )
- {
- xmlChar *value;
- int size;
-
- // Serialise the tree to get value
- xmlDocDumpMemory( context->value_doc, &value, &size );
- mlt_properties_set( properties, context->property, _s(value) );
- xmlFree( value );
- xmlFreeDoc( context->value_doc );
- context->value_doc = NULL;
- }
-
- // Close this property handling
- free( context->property );
- context->property = NULL;
-
- context_push_service( context, service, type );
- }
- else
- {
- fprintf( stderr, "Property without a service '%s'??\n", (const char *)name );
- }
-}
-
-static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **atts)
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
-
-//printf("on_start_element: %s\n", name );
- context->branch[ context->depth ] ++;
- context->depth ++;
-
- // Build a tree from nodes within a property value
- if ( context->is_value == 1 )
- {
- xmlNodePtr node = xmlNewNode( NULL, name );
-
- if ( context->value_doc == NULL )
- {
- // Start a new tree
- context->value_doc = xmlNewDoc( _x("1.0") );
- xmlDocSetRootElement( context->value_doc, node );
- }
- else
- {
- // Append child to tree
- xmlAddChild( context->stack_node[ context->stack_node_size - 1 ], node );
- }
- context_push_node( context, node );
-
- // Set the attributes
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- xmlSetProp( node, atts[ 0 ], atts[ 1 ] );
- }
- else if ( xmlStrcmp( name, _x("tractor") ) == 0 )
- on_start_tractor( context, name, atts );
- else if ( xmlStrcmp( name, _x("multitrack") ) == 0 )
- on_start_multitrack( context, name, atts );
- else if ( xmlStrcmp( name, _x("playlist") ) == 0 || xmlStrcmp( name, _x("seq") ) == 0 || xmlStrcmp( name, _x("smil") ) == 0 )
- on_start_playlist( context, name, atts );
- else if ( xmlStrcmp( name, _x("producer") ) == 0 || xmlStrcmp( name, _x("video") ) == 0 )
- on_start_producer( context, name, atts );
- else if ( xmlStrcmp( name, _x("blank") ) == 0 )
- on_start_blank( context, name, atts );
- else if ( xmlStrcmp( name, _x("entry") ) == 0 )
- on_start_entry( context, name, atts );
- else if ( xmlStrcmp( name, _x("track") ) == 0 )
- on_start_track( context, name, atts );
- else if ( xmlStrcmp( name, _x("filter") ) == 0 )
- on_start_filter( context, name, atts );
- else if ( xmlStrcmp( name, _x("transition") ) == 0 )
- on_start_transition( context, name, atts );
- else if ( xmlStrcmp( name, _x("property") ) == 0 )
- on_start_property( context, name, atts );
- else if ( xmlStrcmp( name, _x("westley") ) == 0 )
- for ( ; atts != NULL && *atts != NULL; atts += 2 )
- mlt_properties_set( context->producer_map, ( const char * )atts[ 0 ], ( const char * )atts[ 1 ] );
-}
-
-static void on_end_element( void *ctx, const xmlChar *name )
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
-
-//printf("on_end_element: %s\n", name );
- if ( context->is_value == 1 && xmlStrcmp( name, _x("property") ) != 0 )
- context_pop_node( context );
- else if ( xmlStrcmp( name, _x("multitrack") ) == 0 )
- on_end_multitrack( context, name );
- else if ( xmlStrcmp( name, _x("playlist") ) == 0 || xmlStrcmp( name, _x("seq") ) == 0 || xmlStrcmp( name, _x("smil") ) == 0 )
- on_end_playlist( context, name );
- else if ( xmlStrcmp( name, _x("track") ) == 0 )
- on_end_track( context, name );
- else if ( xmlStrcmp( name, _x("entry") ) == 0 )
- on_end_entry( context, name );
- else if ( xmlStrcmp( name, _x("tractor") ) == 0 )
- on_end_tractor( context, name );
- else if ( xmlStrcmp( name, _x("property") ) == 0 )
- on_end_property( context, name );
- else if ( xmlStrcmp( name, _x("producer") ) == 0 || xmlStrcmp( name, _x("video") ) == 0 )
- on_end_producer( context, name );
- else if ( xmlStrcmp( name, _x("filter") ) == 0 )
- on_end_filter( context, name );
- else if ( xmlStrcmp( name, _x("transition") ) == 0 )
- on_end_transition( context, name );
-
- context->branch[ context->depth ] = 0;
- context->depth --;
-}
-
-static void on_characters( void *ctx, const xmlChar *ch, int len )
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
- char *value = calloc( len + 1, 1 );
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-
- if ( service != NULL )
- context_push_service( context, service, type );
-
- value[ len ] = 0;
- strncpy( value, (const char*) ch, len );
-
- if ( context->stack_node_size > 0 )
- xmlNodeAddContent( context->stack_node[ context->stack_node_size - 1 ], ( xmlChar* )value );
-
- // libxml2 generates an on_characters immediately after a get_entity within
- // an element value, and we ignore it because it is called again during
- // actual substitution.
- else if ( context->property != NULL && context->entity_is_replace == 0 )
- {
- char *s = mlt_properties_get( properties, context->property );
- if ( s != NULL )
- {
- // Append new text to existing content
- char *new = calloc( strlen( s ) + len + 1, 1 );
- strcat( new, s );
- strcat( new, value );
- mlt_properties_set( properties, context->property, new );
- free( new );
- }
- else
- mlt_properties_set( properties, context->property, value );
- }
- context->entity_is_replace = 0;
-
- free( value);
-}
-
-/** Convert parameters parsed from resource into entity declarations.
-*/
-static void params_to_entities( deserialise_context context )
-{
- if ( context->params != NULL )
- {
- int i;
-
- // Add our params as entitiy declarations
- for ( i = 0; i < mlt_properties_count( context->params ); i++ )
- {
- xmlChar *name = ( xmlChar* )mlt_properties_get_name( context->params, i );
- xmlAddDocEntity( context->entity_doc, name, XML_INTERNAL_GENERAL_ENTITY,
- context->publicId, context->systemId, ( xmlChar* )mlt_properties_get( context->params, _s(name) ) );
- }
-
- // Flag completion
- mlt_properties_close( context->params );
- context->params = NULL;
- }
-}
-
-// The following 3 facilitate entity substitution in the SAX parser
-static void on_internal_subset( void *ctx, const xmlChar* name,
- const xmlChar* publicId, const xmlChar* systemId )
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
-
- context->publicId = publicId;
- context->systemId = systemId;
- xmlCreateIntSubset( context->entity_doc, name, publicId, systemId );
-
- // Override default entities with our parameters
- params_to_entities( context );
-}
-
-// TODO: Check this with Dan... I think this is for westley parameterisation
-// but it's breaking standard escaped entities (like < etc).
-static void on_entity_declaration( void *ctx, const xmlChar* name, int type,
- const xmlChar* publicId, const xmlChar* systemId, xmlChar* content)
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
-
- xmlAddDocEntity( context->entity_doc, name, type, publicId, systemId, content );
-}
-
-// TODO: Check this functionality (see on_entity_declaration)
-static xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
-{
- struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
- deserialise_context context = ( deserialise_context )( xmlcontext->_private );
- xmlEntityPtr e = NULL;
-
- // Setup for entity declarations if not ready
- if ( xmlGetIntSubset( context->entity_doc ) == NULL )
- {
- xmlCreateIntSubset( context->entity_doc, _x("westley"), _x(""), _x("") );
- context->publicId = _x("");
- context->systemId = _x("");
- }
-
- // Add our parameters if not already
- params_to_entities( context );
-
- e = xmlGetPredefinedEntity( name );
-
- // Send signal to on_characters that an entity substitutin is pending
- if ( e == NULL )
- {
- e = xmlGetDocEntity( context->entity_doc, name );
- if ( e != NULL )
- context->entity_is_replace = 1;
- }
-
- return e;
-}
-
-/** Convert a hexadecimal character to its value.
-*/
-static int tohex( char p )
-{
- return isdigit( p ) ? p - '0' : tolower( p ) - 'a' + 10;
-}
-
-/** Decode a url-encoded string containing hexadecimal character sequences.
-*/
-static char *url_decode( char *dest, char *src )
-{
- char *p = dest;
-
- while ( *src )
- {
- if ( *src == '%' )
- {
- *p ++ = ( tohex( *( src + 1 ) ) << 4 ) | tohex( *( src + 2 ) );
- src += 3;
- }
- else
- {
- *p ++ = *src ++;
- }
- }
-
- *p = *src;
- return dest;
-}
-
-/** Extract the filename from a URL attaching parameters to a properties list.
-*/
-static void parse_url( mlt_properties properties, char *url )
-{
- int i;
- int n = strlen( url );
- char *name = NULL;
- char *value = NULL;
-
- for ( i = 0; i < n; i++ )
- {
- switch ( url[ i ] )
- {
- case '?':
- url[ i++ ] = '\0';
- name = &url[ i ];
- break;
-
- case ':':
- case '=':
- url[ i++ ] = '\0';
- value = &url[ i ];
- break;
-
- case '&':
- url[ i++ ] = '\0';
- if ( name != NULL && value != NULL )
- mlt_properties_set( properties, name, value );
- name = &url[ i ];
- value = NULL;
- break;
- }
- }
- if ( name != NULL && value != NULL )
- mlt_properties_set( properties, name, value );
-}
-
-// Quick workaround to avoid unecessary libxml2 warnings
-static int file_exists( char *file )
-{
- char *name = strdup( file );
- int exists = 0;
- if ( name != NULL && strchr( name, '?' ) )
- *( strchr( name, '?' ) ) = '\0';
- if ( name != NULL )
- {
- FILE *f = fopen( name, "r" );
- exists = f != NULL;
- if ( exists ) fclose( f );
- }
- free( name );
- return exists;
-}
-
-mlt_producer producer_westley_init( mlt_profile profile, mlt_service_type servtype, const char *id, char *data )
-{
- xmlSAXHandler *sax = calloc( 1, sizeof( xmlSAXHandler ) );
- struct deserialise_context_s *context = calloc( 1, sizeof( struct deserialise_context_s ) );
- mlt_properties properties = NULL;
- int i = 0;
- struct _xmlParserCtxt *xmlcontext;
- int well_formed = 0;
- char *filename = NULL;
- int info = strcmp( id, "westley-xml" ) ? 0 : 1;
-
- if ( data == NULL || !strcmp( data, "" ) || ( info == 0 && !file_exists( data ) ) )
- return NULL;
-
- context = calloc( 1, sizeof( struct deserialise_context_s ) );
- if ( context == NULL )
- return NULL;
-
- context->producer_map = mlt_properties_new();
- context->destructors = mlt_properties_new();
- context->params = mlt_properties_new();
- context->profile = profile;
-
- // Decode URL and parse parameters
- mlt_properties_set( context->producer_map, "root", "" );
- if ( info == 0 )
- {
- filename = strdup( data );
- parse_url( context->params, url_decode( filename, data ) );
-
- // We need the directory prefix which was used for the westley
- if ( strchr( filename, '/' ) )
- {
- char *root = NULL;
- mlt_properties_set( context->producer_map, "root", filename );
- root = mlt_properties_get( context->producer_map, "root" );
- *( strrchr( root, '/' ) ) = '\0';
-
- // If we don't have an absolute path here, we're heading for disaster...
- if ( root[ 0 ] != '/' )
- {
- char *cwd = getcwd( NULL, 0 );
- char *real = malloc( strlen( cwd ) + strlen( root ) + 2 );
- sprintf( real, "%s/%s", cwd, root );
- mlt_properties_set( context->producer_map, "root", real );
- free( real );
- free( cwd );
- }
- }
- }
-
- // We need to track the number of registered filters
- mlt_properties_set_int( context->destructors, "registered", 0 );
-
- // Setup SAX callbacks
- sax->startElement = on_start_element;
- sax->endElement = on_end_element;
- sax->characters = on_characters;
- sax->cdataBlock = on_characters;
- sax->internalSubset = on_internal_subset;
- sax->entityDecl = on_entity_declaration;
- sax->getEntity = on_get_entity;
-
- // Setup libxml2 SAX parsing
- xmlInitParser();
- xmlSubstituteEntitiesDefault( 1 );
- // This is used to facilitate entity substitution in the SAX parser
- context->entity_doc = xmlNewDoc( _x("1.0") );
- if ( info == 0 )
- xmlcontext = xmlCreateFileParserCtxt( filename );
- else
- xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
-
- // Invalid context - clean up and return NULL
- if ( xmlcontext == NULL )
- {
- mlt_properties_close( context->producer_map );
- mlt_properties_close( context->destructors );
- mlt_properties_close( context->params );
- free( context );
- free( sax );
- free( filename );
- return NULL;
- }
-
- xmlcontext->sax = sax;
- xmlcontext->_private = ( void* )context;
-
- // Parse
- xmlParseDocument( xmlcontext );
- well_formed = xmlcontext->wellFormed;
-
- // Cleanup after parsing
- xmlFreeDoc( context->entity_doc );
- free( sax );
- xmlcontext->sax = NULL;
- xmlcontext->_private = NULL;
- xmlFreeParserCtxt( xmlcontext );
- xmlMemoryDump( ); // for debugging
-
- // Get the last producer on the stack
- enum service_type type;
- mlt_service service = context_pop_service( context, &type );
- if ( well_formed && service != NULL )
- {
- // Verify it is a producer service (mlt_type="mlt_producer")
- // (producer, playlist, multitrack)
- char *type = mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "mlt_type" );
- if ( type == NULL || ( strcmp( type, "mlt_producer" ) != 0 && strcmp( type, "producer" ) != 0 ) )
- service = NULL;
- }
-
-#ifdef DEBUG
- xmlDocPtr doc = westley_make_doc( service );
- xmlDocFormatDump( stdout, doc, 1 );
- xmlFreeDoc( doc );
- service = NULL;
-#endif
-
- if ( well_formed && service != NULL )
- {
- char *title = mlt_properties_get( context->producer_map, "title" );
-
- // Need the complete producer list for various reasons
- properties = context->destructors;
-
- // Now make sure we don't have a reference to the service in the properties
- for ( i = mlt_properties_count( properties ) - 1; i >= 1; i -- )
- {
- char *name = mlt_properties_get_name( properties, i );
- if ( mlt_properties_get_data( properties, name, NULL ) == service )
- {
- mlt_properties_set_data( properties, name, service, 0, NULL, NULL );
- break;
- }
- }
-
- // We are done referencing destructor property list
- // Set this var to service properties for convenience
- properties = MLT_SERVICE_PROPERTIES( service );
-
- // Assign the title
- mlt_properties_set( properties, "title", title );
-
- // Optimise for overlapping producers
- mlt_producer_optimise( MLT_PRODUCER( service ) );
-
- // Handle deep copies
- if ( getenv( "MLT_WESTLEY_DEEP" ) == NULL )
- {
- // Now assign additional properties
- if ( info == 0 )
- mlt_properties_set( properties, "resource", data );
-
- // This tells consumer_westley not to deep copy
- mlt_properties_set( properties, "westley", "was here" );
- }
- else
- {
- // Allow the project to be edited
- mlt_properties_set( properties, "_westley", "was here" );
- mlt_properties_set_int( properties, "_mlt_service_hidden", 1 );
- }
- }
- else
- {
- // Return null if not well formed
- service = NULL;
- }
-
- // Clean up
- mlt_properties_close( context->producer_map );
- if ( context->params != NULL )
- mlt_properties_close( context->params );
- mlt_properties_close( context->destructors );
- free( context );
- free( filename );
-
- return MLT_PRODUCER( service );
-}
+++ /dev/null
-<?xml version='1.0' encoding='utf-8'?>
-
-<!-- MLT westley DTD v0.1.0 -->
-
-<!ELEMENT westley (producer | playlist | tractor | multitrack)+ >
-<!ELEMENT property ANY >
-<!ATTLIST property
- name CDATA #REQUIRED
- value CDATA #IMPLIED
->
-<!ELEMENT producer (property)* >
-<!ATTLIST producer
- id ID #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
- mlt_service CDATA #IMPLIED
->
-<!ELEMENT filter (property)* >
-<!ATTLIST filter
- id ID #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
- mlt_service CDATA #IMPLIED
- track CDATA #IMPLIED
->
-<!ELEMENT transition (property)* >
-<!ATTLIST transition
- id ID #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
- mlt_service CDATA #IMPLIED
- a_track CDATA #IMPLIED
- b_track CDATA #IMPLIED
->
-<!ELEMENT playlist (entry | blank | producer | playlist | tractor | multitrack)+ >
-<!ATTLIST playlist
- id ID #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
->
-<!ELEMENT entry (producer | playlist | tractor | multitrack | filter | transition)* >
-<!ATTLIST entry
- producer IDREF #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
->
-<!ELEMENT blank EMPTY >
-<!ATTLIST blank
- length CDATA #REQUIRED
->
-<!ELEMENT tractor (multitrack, (filter | transition)*) >
-<!ATTLIST tractor
- id ID #IMPLIED
- in CDATA #IMPLIED
- out CDATA #IMPLIED
->
-<!ELEMENT multitrack (track | producer | playlist | tractor | multitrack)+ >
-<!ATTLIST multitrack
- id ID #IMPLIED
->
-<!ELEMENT track (producer | playlist | tractor | multitrack | filter | transition)* >
-<!ATTLIST track
- producer IDREF #IMPLIED
->
+++ /dev/null
-include ../../../config.mak
-
-TARGET = ../libmltxine$(LIBSUF)
-
-OBJS = factory.o \
- deinterlace.o \
- filter_deinterlace.o
-
-ifdef MMX_FLAGS
-OBJS += cpu_accel.o
-endif
-
-CFLAGS += -I../../ -DARCH_X86
-
-LDFLAGS += -L../../framework -lmlt
-
-SRCS := $(OBJS:.o=.c)
-
-all: $(TARGET)
-
-$(TARGET): $(OBJS)
- $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
-
-depend: $(SRCS)
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-distclean: clean
- rm -f .depend
-
-clean:
- rm -f $(OBJS) $(TARGET)
-
-install: all
- install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-/*
- * attributes.h
- * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *
- * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
- *
- * mpeg2dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpeg2dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* use gcc attribs to align critical data structures */
-
-#ifndef ATTRIBUTE_H_
-#define ATTRIBUTE_H_
-
-#ifdef ATTRIBUTE_ALIGNED_MAX
-#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
-#else
-#define ATTR_ALIGN(align)
-#endif
-
-/* disable GNU __attribute__ extension, when not compiling with GNU C */
-#if defined(__GNUC__) || defined (__ICC)
-#ifndef ATTRIBUTE_PACKED
-#define ATTRIBUTE_PACKED 1
-#endif
-#else
-#undef ATTRIBUTE_PACKED
-#ifndef __attribute__
-#define __attribute__(x) /**/
-#endif /* __attribute __*/
-#endif
-
-#endif /* ATTRIBUTE_H_ */
-
+++ /dev/null
-/*
- * cpu_accel.c
- * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *
- * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
- *
- * mpeg2dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpeg2dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-//#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <dlfcn.h>
-
-#define LOG_MODULE "cpu_accel"
-#define LOG_VERBOSE
-/*
-#define LOG
-*/
-
-#include "xineutils.h"
-
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
-#if defined __x86_64__
-static uint32_t arch_accel (void)
-{
- uint32_t caps;
- /* No need to test for this on AMD64, we know what the
- platform has. */
- caps = MM_ACCEL_X86_MMX | MM_ACCEL_X86_SSE | MM_ACCEL_X86_MMXEXT | MM_ACCEL_X86_SSE2;
-
- return caps;
-}
-#else
-static uint32_t arch_accel (void)
-{
-#ifndef _MSC_VER
-
- uint32_t eax, ebx, ecx, edx;
- int AMD;
- uint32_t caps;
-
-#ifndef PIC
-#define cpuid(op,eax,ebx,ecx,edx) \
- __asm__ ("cpuid" \
- : "=a" (eax), \
- "=b" (ebx), \
- "=c" (ecx), \
- "=d" (edx) \
- : "a" (op) \
- : "cc")
-#else /* PIC version : save ebx */
-#define cpuid(op,eax,ebx,ecx,edx) \
- __asm__ ("pushl %%ebx\n\t" \
- "cpuid\n\t" \
- "movl %%ebx,%1\n\t" \
- "popl %%ebx" \
- : "=a" (eax), \
- "=r" (ebx), \
- "=c" (ecx), \
- "=d" (edx) \
- : "a" (op) \
- : "cc")
-#endif
-
- __asm__ ("pushfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "movl %0,%1\n\t"
- "xorl $0x200000,%0\n\t"
- "pushl %0\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "popfl"
- : "=r" (eax),
- "=r" (ebx)
- :
- : "cc");
-
- if (eax == ebx) /* no cpuid */
- return 0;
-
- cpuid (0x00000000, eax, ebx, ecx, edx);
- if (!eax) /* vendor string only */
- return 0;
-
- AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
-
- cpuid (0x00000001, eax, ebx, ecx, edx);
- if (! (edx & 0x00800000)) /* no MMX */
- return 0;
-
- caps = MM_ACCEL_X86_MMX;
- if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
- caps |= MM_ACCEL_X86_SSE | MM_ACCEL_X86_MMXEXT;
-
- if (edx & 0x04000000) /* SSE2 */
- caps |= MM_ACCEL_X86_SSE2;
-
- cpuid (0x80000000, eax, ebx, ecx, edx);
- if (eax < 0x80000001) /* no extended capabilities */
- return caps;
-
- cpuid (0x80000001, eax, ebx, ecx, edx);
-
- if (edx & 0x80000000)
- caps |= MM_ACCEL_X86_3DNOW;
-
- if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
- caps |= MM_ACCEL_X86_MMXEXT;
-
- return caps;
-#else /* _MSC_VER */
- return 0;
-#endif
-}
-#endif /* x86_64 */
-
-static jmp_buf sigill_return;
-
-static void sigill_handler (int n) {
- longjmp(sigill_return, 1);
-}
-#endif /* ARCH_X86 */
-
-#if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
-static sigjmp_buf jmpbuf;
-static volatile sig_atomic_t canjump = 0;
-
-static void sigill_handler (int sig)
-{
- if (!canjump) {
- signal (sig, SIG_DFL);
- raise (sig);
- }
-
- canjump = 0;
- siglongjmp (jmpbuf, 1);
-}
-
-static uint32_t arch_accel (void)
-{
- signal (SIGILL, sigill_handler);
- if (sigsetjmp (jmpbuf, 1)) {
- signal (SIGILL, SIG_DFL);
- return 0;
- }
-
- canjump = 1;
-
- __asm__ volatile ("mtspr 256, %0\n\t"
- "vand %%v0, %%v0, %%v0"
- :
- : "r" (-1));
-
- signal (SIGILL, SIG_DFL);
- return MM_ACCEL_PPC_ALTIVEC;
-}
-#endif /* ARCH_PPC */
-
-uint32_t xine_mm_accel (void)
-{
- static int initialized = 0;
- static uint32_t accel;
-
- if (!initialized) {
-#if defined (ARCH_X86) || (defined (ARCH_PPC) && defined (ENABLE_ALTIVEC))
- accel = arch_accel ();
-#elif defined (HAVE_MLIB)
-#ifdef MLIB_LAZYLOAD
- void *hndl;
-
- if ((hndl = dlopen("libmlib.so.2", RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE)) == NULL) {
- accel = 0;
- }
- else {
- dlclose(hndl);
- accel = MM_ACCEL_MLIB;
- }
-#else
- accel = MM_ACCEL_MLIB;
-#endif
-#else
- accel = 0;
-#endif
-
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
-#ifndef _MSC_VER
- /* test OS support for SSE */
- if( accel & MM_ACCEL_X86_SSE ) {
- void (*old_sigill_handler)(int);
-
- old_sigill_handler = signal (SIGILL, sigill_handler);
-
- if (setjmp(sigill_return)) {
- lprintf ("OS doesn't support SSE instructions.\n");
- accel &= ~(MM_ACCEL_X86_SSE|MM_ACCEL_X86_SSE2);
- } else {
- __asm__ volatile ("xorps %xmm0, %xmm0");
- }
-
- signal (SIGILL, old_sigill_handler);
- }
-#endif /* _MSC_VER */
-#endif /* ARCH_X86 || ARCH_X86_64 */
-
- if(getenv("XINE_NO_ACCEL")) {
- accel = 0;
- }
-
- initialized = 1;
- }
-
- return accel;
-}
+++ /dev/null
- /*
- * Copyright (C) 2001 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Deinterlace routines by Miguel Freitas
- * based of DScaler project sources (deinterlace.sourceforge.net)
- *
- * Currently only available for Xv driver and MMX extensions
- *
- * small todo list:
- * - implement non-MMX versions for all methods
- * - support MMX2 instructions
- * - move some generic code from xv driver to this file
- * - make it also work for yuy2 frames
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "deinterlace.h"
-#include "xineutils.h"
-
-#define xine_fast_memcpy memcpy
-#define xine_fast_memmove memmove
-
-/*
- DeinterlaceFieldBob algorithm
- Based on Virtual Dub plugin by Gunnar Thalin
- MMX asm version from dscaler project (deinterlace.sourceforge.net)
- Linux version for Xine player by Miguel Freitas
-*/
-static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
-#ifdef USE_MMX
- int Line;
- uint64_t *YVal1;
- uint64_t *YVal2;
- uint64_t *YVal3;
- uint64_t *Dest;
- uint8_t* pEvenLines = psrc[0];
- uint8_t* pOddLines = psrc[0]+width;
- int LineLength = width;
- int SourcePitch = width * 2;
- int IsOdd = 1;
- long EdgeDetect = 625;
- long JaggieThreshold = 73;
-
- int n;
-
- uint64_t qwEdgeDetect;
- uint64_t qwThreshold;
-
- static mmx_t YMask = {ub:{0xff,0,0xff,0,0xff,0,0xff,0}};
- static mmx_t Mask = {ub:{0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}};
-
- qwEdgeDetect = EdgeDetect;
- qwEdgeDetect += (qwEdgeDetect << 48) + (qwEdgeDetect << 32) + (qwEdgeDetect << 16);
- qwThreshold = JaggieThreshold;
- qwThreshold += (qwThreshold << 48) + (qwThreshold << 32) + (qwThreshold << 16);
-
-
- // copy first even line no matter what, and the first odd line if we're
- // processing an odd field.
- xine_fast_memcpy(pdst, pEvenLines, LineLength);
- if (IsOdd)
- xine_fast_memcpy(pdst + LineLength, pOddLines, LineLength);
-
- height = height / 2;
- for (Line = 0; Line < height - 1; ++Line)
- {
- if (IsOdd)
- {
- YVal1 = (uint64_t *)(pOddLines + Line * SourcePitch);
- YVal2 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- YVal3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength);
- }
- else
- {
- YVal1 = (uint64_t *)(pEvenLines + Line * SourcePitch);
- YVal2 = (uint64_t *)(pOddLines + Line * SourcePitch);
- YVal3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength);
- }
-
- // For ease of reading, the comments below assume that we're operating on an odd
- // field (i.e., that bIsOdd is true). The exact same processing is done when we
- // operate on an even field, but the roles of the odd and even fields are reversed.
- // It's just too cumbersome to explain the algorithm in terms of "the next odd
- // line if we're doing an odd field, or the next even line if we're doing an
- // even field" etc. So wherever you see "odd" or "even" below, keep in mind that
- // half the time this function is called, those words' meanings will invert.
-
- // Copy the odd line to the overlay verbatim.
- xine_fast_memcpy((char *)Dest + LineLength, YVal3, LineLength);
-
- n = LineLength >> 3;
- while( n-- )
- {
- movq_m2r (*YVal1++, mm0);
- movq_m2r (*YVal2++, mm1);
- movq_m2r (*YVal3++, mm2);
-
- // get intensities in mm3 - 4
- movq_r2r ( mm0, mm3 );
- pand_m2r ( YMask, mm3 );
- movq_r2r ( mm1, mm4 );
- pand_m2r ( YMask, mm4 );
- movq_r2r ( mm2, mm5 );
- pand_m2r ( YMask, mm5 );
-
- // get average in mm0
- pand_m2r ( Mask, mm0 );
- pand_m2r ( Mask, mm2 );
- psrlw_i2r ( 01, mm0 );
- psrlw_i2r ( 01, mm2 );
- paddw_r2r ( mm2, mm0 );
-
- // work out (O1 - E) * (O2 - E) / 2 - EdgeDetect * (O1 - O2) ^ 2 >> 12
- // result will be in mm6
-
- psrlw_i2r ( 01, mm3 );
- psrlw_i2r ( 01, mm4 );
- psrlw_i2r ( 01, mm5 );
-
- movq_r2r ( mm3, mm6 );
- psubw_r2r ( mm4, mm6 ); //mm6 = O1 - E
-
- movq_r2r ( mm5, mm7 );
- psubw_r2r ( mm4, mm7 ); //mm7 = O2 - E
-
- pmullw_r2r ( mm7, mm6 ); // mm6 = (O1 - E) * (O2 - E)
-
- movq_r2r ( mm3, mm7 );
- psubw_r2r ( mm5, mm7 ); // mm7 = (O1 - O2)
- pmullw_r2r ( mm7, mm7 ); // mm7 = (O1 - O2) ^ 2
- psrlw_i2r ( 12, mm7 ); // mm7 = (O1 - O2) ^ 2 >> 12
- pmullw_m2r ( *&qwEdgeDetect, mm7 );// mm7 = EdgeDetect * (O1 - O2) ^ 2 >> 12
-
- psubw_r2r ( mm7, mm6 ); // mm6 is what we want
-
- pcmpgtw_m2r ( *&qwThreshold, mm6 );
-
- movq_r2r ( mm6, mm7 );
-
- pand_r2r ( mm6, mm0 );
-
- pandn_r2r ( mm1, mm7 );
-
- por_r2r ( mm0, mm7 );
-
- movq_r2m ( mm7, *Dest++ );
- }
- }
-
- // Copy last odd line if we're processing an even field.
- if (! IsOdd)
- {
- xine_fast_memcpy(pdst + (height * 2 - 1) * LineLength,
- pOddLines + (height - 1) * SourcePitch,
- LineLength);
- }
-
- // clear out the MMX registers ready for doing floating point
- // again
- emms();
-#endif
-}
-
-/* Deinterlace the latest field, with a tendency to weave rather than bob.
- Good for high detail on low-movement scenes.
- Seems to produce bad output in general case, need to check if this
- is normal or if the code is broken.
-*/
-static int deinterlace_weave_yuv_mmx( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
-#ifdef USE_MMX
-
- int Line;
- uint64_t *YVal1;
- uint64_t *YVal2;
- uint64_t *YVal3;
- uint64_t *YVal4;
- uint64_t *Dest;
- uint8_t* pEvenLines = psrc[0];
- uint8_t* pOddLines = psrc[0]+width;
- uint8_t* pPrevLines;
-
- int LineLength = width;
- int SourcePitch = width * 2;
- int IsOdd = 1;
-
- long TemporalTolerance = 300;
- long SpatialTolerance = 600;
- long SimilarityThreshold = 25;
-
- int n;
-
- uint64_t qwSpatialTolerance;
- uint64_t qwTemporalTolerance;
- uint64_t qwThreshold;
-
- static mmx_t YMask = {ub:{0xff,0,0xff,0,0xff,0,0xff,0}};
- static mmx_t Mask = {ub:{0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}};
-
-
- // Make sure we have all the data we need.
- if ( psrc[0] == NULL || psrc[1] == NULL )
- return 0;
-
- if (IsOdd)
- pPrevLines = psrc[1] + width;
- else
- pPrevLines = psrc[1];
-
- // Since the code uses MMX to process 4 pixels at a time, we need our constants
- // to be represented 4 times per quadword.
- qwSpatialTolerance = SpatialTolerance;
- qwSpatialTolerance += (qwSpatialTolerance << 48) + (qwSpatialTolerance << 32) + (qwSpatialTolerance << 16);
- qwTemporalTolerance = TemporalTolerance;
- qwTemporalTolerance += (qwTemporalTolerance << 48) + (qwTemporalTolerance << 32) + (qwTemporalTolerance << 16);
- qwThreshold = SimilarityThreshold;
- qwThreshold += (qwThreshold << 48) + (qwThreshold << 32) + (qwThreshold << 16);
-
- // copy first even line no matter what, and the first odd line if we're
- // processing an even field.
- xine_fast_memcpy(pdst, pEvenLines, LineLength);
- if (!IsOdd)
- xine_fast_memcpy(pdst + LineLength, pOddLines, LineLength);
-
- height = height / 2;
- for (Line = 0; Line < height - 1; ++Line)
- {
- if (IsOdd)
- {
- YVal1 = (uint64_t *)(pEvenLines + Line * SourcePitch);
- YVal2 = (uint64_t *)(pOddLines + Line * SourcePitch);
- YVal3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- YVal4 = (uint64_t *)(pPrevLines + Line * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength);
- }
- else
- {
- YVal1 = (uint64_t *)(pOddLines + Line * SourcePitch);
- YVal2 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- YVal3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch);
- YVal4 = (uint64_t *)(pPrevLines + (Line + 1) * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength);
- }
-
- // For ease of reading, the comments below assume that we're operating on an odd
- // field (i.e., that bIsOdd is true). The exact same processing is done when we
- // operate on an even field, but the roles of the odd and even fields are reversed.
- // It's just too cumbersome to explain the algorithm in terms of "the next odd
- // line if we're doing an odd field, or the next even line if we're doing an
- // even field" etc. So wherever you see "odd" or "even" below, keep in mind that
- // half the time this function is called, those words' meanings will invert.
-
- // Copy the even scanline below this one to the overlay buffer, since we'll be
- // adapting the current scanline to the even lines surrounding it. The scanline
- // above has already been copied by the previous pass through the loop.
- xine_fast_memcpy((char *)Dest + LineLength, YVal3, LineLength);
-
- n = LineLength >> 3;
- while( n-- )
- {
- movq_m2r ( *YVal1++, mm0 ); // mm0 = E1
- movq_m2r ( *YVal2++, mm1 ); // mm1 = O
- movq_m2r ( *YVal3++, mm2 ); // mm2 = E2
-
- movq_r2r ( mm0, mm3 ); // mm3 = intensity(E1)
- movq_r2r ( mm1, mm4 ); // mm4 = intensity(O)
- movq_r2r ( mm2, mm6 ); // mm6 = intensity(E2)
-
- pand_m2r ( YMask, mm3 );
- pand_m2r ( YMask, mm4 );
- pand_m2r ( YMask, mm6 );
-
- // Average E1 and E2 for interpolated bobbing.
- // leave result in mm0
- pand_m2r ( Mask, mm0 ); // mm0 = E1 with lower chroma bit stripped off
- pand_m2r ( Mask, mm2 ); // mm2 = E2 with lower chroma bit stripped off
- psrlw_i2r ( 01, mm0 ); // mm0 = E1 / 2
- psrlw_i2r ( 01, mm2 ); // mm2 = E2 / 2
- paddb_r2r ( mm2, mm0 );
-
- // The meat of the work is done here. We want to see whether this pixel is
- // close in luminosity to ANY of: its top neighbor, its bottom neighbor,
- // or its predecessor. To do this without branching, we use MMX's
- // saturation feature, which gives us Z(x) = x if x>=0, or 0 if x<0.
- //
- // The formula we're computing here is
- // Z(ST - (E1 - O) ^ 2) + Z(ST - (E2 - O) ^ 2) + Z(TT - (Oold - O) ^ 2)
- // where ST is spatial tolerance and TT is temporal tolerance. The idea
- // is that if a pixel is similar to none of its neighbors, the resulting
- // value will be pretty low, probably zero. A high value therefore indicates
- // that the pixel had a similar neighbor. The pixel in the same position
- // in the field before last (Oold) is considered a neighbor since we want
- // to be able to display 1-pixel-high horizontal lines.
-
- movq_m2r ( *&qwSpatialTolerance, mm7 );
- movq_r2r ( mm3, mm5 ); // mm5 = E1
- psubsw_r2r ( mm4, mm5 ); // mm5 = E1 - O
- psraw_i2r ( 1, mm5 );
- pmullw_r2r ( mm5, mm5 ); // mm5 = (E1 - O) ^ 2
- psubusw_r2r ( mm5, mm7 ); // mm7 = ST - (E1 - O) ^ 2, or 0 if that's negative
-
- movq_m2r ( *&qwSpatialTolerance, mm3 );
- movq_r2r ( mm6, mm5 ); // mm5 = E2
- psubsw_r2r ( mm4, mm5 ); // mm5 = E2 - O
- psraw_i2r ( 1, mm5 );
- pmullw_r2r ( mm5, mm5 ); // mm5 = (E2 - O) ^ 2
- psubusw_r2r ( mm5, mm3 ); // mm0 = ST - (E2 - O) ^ 2, or 0 if that's negative
- paddusw_r2r ( mm3, mm7 ); // mm7 = (ST - (E1 - O) ^ 2) + (ST - (E2 - O) ^ 2)
-
- movq_m2r ( *&qwTemporalTolerance, mm3 );
- movq_m2r ( *YVal4++, mm5 ); // mm5 = Oold
- pand_m2r ( YMask, mm5 );
- psubsw_r2r ( mm4, mm5 ); // mm5 = Oold - O
- psraw_i2r ( 1, mm5 ); // XXX
- pmullw_r2r ( mm5, mm5 ); // mm5 = (Oold - O) ^ 2
- psubusw_r2r ( mm5, mm3 ); /* mm0 = TT - (Oold - O) ^ 2, or 0 if that's negative */
- paddusw_r2r ( mm3, mm7 ); // mm7 = our magic number
-
- /*
- * Now compare the similarity totals against our threshold. The pcmpgtw
- * instruction will populate the target register with a bunch of mask bits,
- * filling words where the comparison is true with 1s and ones where it's
- * false with 0s. A few ANDs and NOTs and an OR later, we have bobbed
- * values for pixels under the similarity threshold and weaved ones for
- * pixels over the threshold.
- */
-
- pcmpgtw_m2r( *&qwThreshold, mm7 ); // mm7 = 0xffff where we're greater than the threshold, 0 elsewhere
- movq_r2r ( mm7, mm6 ); // mm6 = 0xffff where we're greater than the threshold, 0 elsewhere
- pand_r2r ( mm1, mm7 ); // mm7 = weaved data where we're greater than the threshold, 0 elsewhere
- pandn_r2r ( mm0, mm6 ); // mm6 = bobbed data where we're not greater than the threshold, 0 elsewhere
- por_r2r ( mm6, mm7 ); // mm7 = bobbed and weaved data
-
- movq_r2m ( mm7, *Dest++ );
- }
- }
-
- // Copy last odd line if we're processing an odd field.
- if (IsOdd)
- {
- xine_fast_memcpy(pdst + (height * 2 - 1) * LineLength,
- pOddLines + (height - 1) * SourcePitch,
- LineLength);
- }
-
- // clear out the MMX registers ready for doing floating point
- // again
- emms();
-
-#endif
-
- return 1;
-}
-
-
-// This is a simple lightweight DeInterlace method that uses little CPU time
-// but gives very good results for low or intermedite motion. (MORE CPU THAN BOB)
-// It defers frames by one field, but that does not seem to produce noticeable
-// lip sync problems.
-//
-// The method used is to take either the older or newer weave pixel depending
-// upon which give the smaller comb factor, and then clip to avoid large damage
-// when wrong.
-//
-// I'd intended this to be part of a larger more elaborate method added to
-// Blended Clip but this give too good results for the CPU to ignore here.
-static int deinterlace_greedy_yuv_mmx( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
-#ifdef USE_MMX
- int Line;
- int LoopCtr;
- uint64_t *L1; // ptr to Line1, of 3
- uint64_t *L2; // ptr to Line2, the weave line
- uint64_t *L3; // ptr to Line3
- uint64_t *LP2; // ptr to prev Line2
- uint64_t *Dest;
- uint8_t* pEvenLines = psrc[0];
- uint8_t* pOddLines = psrc[0]+width;
- uint8_t* pPrevLines;
-
- static mmx_t ShiftMask = {ub:{0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}};
-
- int LineLength = width;
- int SourcePitch = width * 2;
- int IsOdd = 1;
- long GreedyMaxComb = 15;
- static mmx_t MaxComb;
- int i;
-
- if ( psrc[0] == NULL || psrc[1] == NULL )
- return 0;
-
- if (IsOdd)
- pPrevLines = psrc[1] + width;
- else
- pPrevLines = psrc[1];
-
-
- for( i = 0; i < 8; i++ )
- MaxComb.ub[i] = GreedyMaxComb; // How badly do we let it weave? 0-255
-
-
- // copy first even line no matter what, and the first odd line if we're
- // processing an EVEN field. (note diff from other deint rtns.)
- xine_fast_memcpy(pdst, pEvenLines, LineLength); //DL0
- if (!IsOdd)
- xine_fast_memcpy(pdst + LineLength, pOddLines, LineLength); //DL1
-
- height = height / 2;
- for (Line = 0; Line < height - 1; ++Line)
- {
- LoopCtr = LineLength / 8; // there are LineLength / 8 qwords per line
-
- if (IsOdd)
- {
- L1 = (uint64_t *)(pEvenLines + Line * SourcePitch);
- L2 = (uint64_t *)(pOddLines + Line * SourcePitch);
- L3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- LP2 = (uint64_t *)(pPrevLines + Line * SourcePitch); // prev Odd lines
- Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength);
- }
- else
- {
- L1 = (uint64_t *)(pOddLines + Line * SourcePitch);
- L2 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- L3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch);
- LP2 = (uint64_t *)(pPrevLines + (Line + 1) * SourcePitch); //prev even lines
- Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength);
- }
-
- xine_fast_memcpy((char *)Dest + LineLength, L3, LineLength);
-
-// For ease of reading, the comments below assume that we're operating on an odd
-// field (i.e., that info->IsOdd is true). Assume the obvious for even lines..
-
- while( LoopCtr-- )
- {
- movq_m2r ( *L1++, mm1 );
- movq_m2r ( *L2++, mm2 );
- movq_m2r ( *L3++, mm3 );
- movq_m2r ( *LP2++, mm0 );
-
- // average L1 and L3 leave result in mm4
- movq_r2r ( mm1, mm4 ); // L1
-
- pand_m2r ( ShiftMask, mm4 );
- psrlw_i2r ( 01, mm4 );
- movq_r2r ( mm3, mm5 ); // L3
- pand_m2r ( ShiftMask, mm5 );
- psrlw_i2r ( 01, mm5 );
- paddb_r2r ( mm5, mm4 ); // the average, for computing comb
-
- // get abs value of possible L2 comb
- movq_r2r ( mm2, mm7 ); // L2
- psubusb_r2r ( mm4, mm7 ); // L2 - avg
- movq_r2r ( mm4, mm5 ); // avg
- psubusb_r2r ( mm2, mm5 ); // avg - L2
- por_r2r ( mm7, mm5 ); // abs(avg-L2)
- movq_r2r ( mm4, mm6 ); // copy of avg for later
-
- // get abs value of possible LP2 comb
- movq_r2r ( mm0, mm7 ); // LP2
- psubusb_r2r ( mm4, mm7 ); // LP2 - avg
- psubusb_r2r ( mm0, mm4 ); // avg - LP2
- por_r2r ( mm7, mm4 ); // abs(avg-LP2)
-
- // use L2 or LP2 depending upon which makes smaller comb
- psubusb_r2r ( mm5, mm4 ); // see if it goes to zero
- psubusb_r2r ( mm5, mm5 ); // 0
- pcmpeqb_r2r ( mm5, mm4 ); // if (mm4=0) then FF else 0
- pcmpeqb_r2r ( mm4, mm5 ); // opposite of mm4
-
- // if Comb(LP2) <= Comb(L2) then mm4=ff, mm5=0 else mm4=0, mm5 = 55
- pand_r2r ( mm2, mm5 ); // use L2 if mm5 == ff, else 0
- pand_r2r ( mm0, mm4 ); // use LP2 if mm4 = ff, else 0
- por_r2r ( mm5, mm4 ); // may the best win
-
- // Now lets clip our chosen value to be not outside of the range
- // of the high/low range L1-L3 by more than abs(L1-L3)
- // This allows some comb but limits the damages and also allows more
- // detail than a boring oversmoothed clip.
-
- movq_r2r ( mm1, mm2 ); // copy L1
- psubusb_r2r ( mm3, mm2 ); // - L3, with saturation
- paddusb_r2r ( mm3, mm2 ); // now = Max(L1,L3)
-
- pcmpeqb_r2r ( mm7, mm7 ); // all ffffffff
- psubusb_r2r ( mm1, mm7 ); // - L1
- paddusb_r2r ( mm7, mm3 ); // add, may sat at fff..
- psubusb_r2r ( mm7, mm3 ); // now = Min(L1,L3)
-
- // allow the value to be above the high or below the low by amt of MaxComb
- paddusb_m2r ( MaxComb, mm2 ); // increase max by diff
- psubusb_m2r ( MaxComb, mm3 ); // lower min by diff
-
- psubusb_r2r ( mm3, mm4 ); // best - Min
- paddusb_r2r ( mm3, mm4 ); // now = Max(best,Min(L1,L3)
-
- pcmpeqb_r2r ( mm7, mm7 ); // all ffffffff
- psubusb_r2r ( mm4, mm7 ); // - Max(best,Min(best,L3)
- paddusb_r2r ( mm7, mm2 ); // add may sat at FFF..
- psubusb_r2r ( mm7, mm2 ); // now = Min( Max(best, Min(L1,L3), L2 )=L2 clipped
-
- movq_r2m ( mm2, *Dest++ ); // move in our clipped best
-
- }
- }
-
- /* Copy last odd line if we're processing an Odd field. */
- if (IsOdd)
- {
- xine_fast_memcpy(pdst + (height * 2 - 1) * LineLength,
- pOddLines + (height - 1) * SourcePitch,
- LineLength);
- }
-
- /* clear out the MMX registers ready for doing floating point again */
- emms();
-
-#endif
-
- return 1;
-}
-
-/* Use one field to interpolate the other (low cpu utilization)
- Will lose resolution but does not produce weaving effect
- (good for fast moving scenes) also know as "linear interpolation"
-*/
-static void deinterlace_onefield_yuv_mmx( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
-#ifdef USE_MMX
- int Line;
- uint64_t *YVal1;
- uint64_t *YVal3;
- uint64_t *Dest;
- uint8_t* pEvenLines = psrc[0];
- uint8_t* pOddLines = psrc[0]+width;
- int LineLength = width;
- int SourcePitch = width * 2;
- int IsOdd = 1;
-
- int n;
-
- static mmx_t Mask = {ub:{0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}};
-
- /*
- * copy first even line no matter what, and the first odd line if we're
- * processing an odd field.
- */
-
- xine_fast_memcpy(pdst, pEvenLines, LineLength);
- if (IsOdd)
- xine_fast_memcpy(pdst + LineLength, pOddLines, LineLength);
-
- height = height / 2;
- for (Line = 0; Line < height - 1; ++Line)
- {
- if (IsOdd)
- {
- YVal1 = (uint64_t *)(pOddLines + Line * SourcePitch);
- YVal3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength);
- }
- else
- {
- YVal1 = (uint64_t *)(pEvenLines + Line * SourcePitch);
- YVal3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch);
- Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength);
- }
-
- // Copy the odd line to the overlay verbatim.
- xine_fast_memcpy((char *)Dest + LineLength, YVal3, LineLength);
-
- n = LineLength >> 3;
- while( n-- )
- {
- movq_m2r (*YVal1++, mm0);
- movq_m2r (*YVal3++, mm2);
-
- // get average in mm0
- pand_m2r ( Mask, mm0 );
- pand_m2r ( Mask, mm2 );
- psrlw_i2r ( 01, mm0 );
- psrlw_i2r ( 01, mm2 );
- paddw_r2r ( mm2, mm0 );
-
- movq_r2m ( mm0, *Dest++ );
- }
- }
-
- /* Copy last odd line if we're processing an even field. */
- if (! IsOdd)
- {
- xine_fast_memcpy(pdst + (height * 2 - 1) * LineLength,
- pOddLines + (height - 1) * SourcePitch,
- LineLength);
- }
-
- /* clear out the MMX registers ready for doing floating point
- * again
- */
- emms();
-#endif
-}
-
-/* Linear Blend filter - does a kind of vertical blurring on the image.
- (idea borrowed from mplayer's sources)
-*/
-static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
-#ifdef USE_MMX
- int Line;
- uint64_t *YVal1;
- uint64_t *YVal2;
- uint64_t *YVal3;
- uint64_t *Dest;
- int LineLength = width;
-
- int n;
-
- /* Copy first line */
- xine_fast_memmove(pdst, psrc[0], LineLength);
-
- for (Line = 1; Line < height - 1; ++Line)
- {
- YVal1 = (uint64_t *)(psrc[0] + (Line - 1) * LineLength);
- YVal2 = (uint64_t *)(psrc[0] + (Line) * LineLength);
- YVal3 = (uint64_t *)(psrc[0] + (Line + 1) * LineLength);
- Dest = (uint64_t *)(pdst + Line * LineLength);
-
- n = LineLength >> 3;
- while( n-- )
- {
- /* load data from 3 lines */
- movq_m2r (*YVal1++, mm0);
- movq_m2r (*YVal2++, mm1);
- movq_m2r (*YVal3++, mm2);
-
- /* expand bytes to words */
- punpckhbw_r2r (mm0, mm3);
- punpckhbw_r2r (mm1, mm4);
- punpckhbw_r2r (mm2, mm5);
- punpcklbw_r2r (mm0, mm0);
- punpcklbw_r2r (mm1, mm1);
- punpcklbw_r2r (mm2, mm2);
-
- /*
- * deinterlacing:
- * deint_line = (line0 + 2*line1 + line2) / 4
- */
- psrlw_i2r (07, mm0);
- psrlw_i2r (06, mm1);
- psrlw_i2r (07, mm2);
- psrlw_i2r (07, mm3);
- psrlw_i2r (06, mm4);
- psrlw_i2r (07, mm5);
- paddw_r2r (mm1, mm0);
- paddw_r2r (mm2, mm0);
- paddw_r2r (mm4, mm3);
- paddw_r2r (mm5, mm3);
- psrlw_i2r (03, mm0);
- psrlw_i2r (03, mm3);
-
- /* pack 8 words to 8 bytes in mm0 */
- packuswb_r2r (mm3, mm0);
-
- movq_r2m ( mm0, *Dest++ );
- }
- }
-
- /* Copy last line */
- xine_fast_memmove(pdst + Line * LineLength,
- psrc[0] + Line * LineLength, LineLength);
-
- /* clear out the MMX registers ready for doing floating point
- * again
- */
- emms();
-#endif
-}
-
-/* Linear Blend filter - C version contributed by Rogerio Brito.
- This algorithm has the same interface as the other functions.
-
- The destination "screen" (pdst) is constructed from the source
- screen (psrc[0]) line by line.
-
- The i-th line of the destination screen is the average of 3 lines
- from the source screen: the (i-1)-th, i-th and (i+1)-th lines, with
- the i-th line having weight 2 in the computation.
-
- Remarks:
- * each line on pdst doesn't depend on previous lines;
- * due to the way the algorithm is defined, the first & last lines of the
- screen aren't deinterlaced.
-
-*/
-static void deinterlace_linearblend_yuv( uint8_t *pdst, uint8_t *psrc[],
- int width, int height )
-{
- register int x, y;
- register uint8_t *l0, *l1, *l2, *l3;
-
- l0 = pdst; /* target line */
- l1 = psrc[0]; /* 1st source line */
- l2 = l1 + width; /* 2nd source line = line that follows l1 */
- l3 = l2 + width; /* 3rd source line = line that follows l2 */
-
- /* Copy the first line */
- xine_fast_memcpy(l0, l1, width);
- l0 += width;
-
- for (y = 1; y < height-1; ++y) {
- /* computes avg of: l1 + 2*l2 + l3 */
-
- for (x = 0; x < width; ++x) {
- l0[x] = (l1[x] + (l2[x]<<1) + l3[x]) >> 2;
- }
-
- /* updates the line pointers */
- l1 = l2; l2 = l3; l3 += width;
- l0 += width;
- }
-
- /* Copy the last line */
- xine_fast_memcpy(l0, l1, width);
-}
-
-static int check_for_mmx(void)
-{
-#ifdef USE_MMX
-static int config_flags = -1;
-
- if ( config_flags == -1 )
- config_flags = xine_mm_accel();
- if (config_flags & MM_ACCEL_X86_MMX)
- return 1;
- return 0;
-#else
- return 0;
-#endif
-}
-
-/* generic YUV deinterlacer
- pdst -> pointer to destination bitmap
- psrc -> array of pointers to source bitmaps ([0] = most recent)
- width,height -> dimension for bitmaps
- method -> DEINTERLACE_xxx
-*/
-
-void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[],
- int width, int height, int method )
-{
- switch( method ) {
- case DEINTERLACE_NONE:
- xine_fast_memcpy(pdst,psrc[0],width*height);
- break;
- case DEINTERLACE_BOB:
- if( check_for_mmx() )
- deinterlace_bob_yuv_mmx(pdst,psrc,width,height);
- else /* FIXME: provide an alternative? */
- xine_fast_memcpy(pdst,psrc[0],width*height);
- break;
- case DEINTERLACE_WEAVE:
- if( check_for_mmx() )
- {
- if( !deinterlace_weave_yuv_mmx(pdst,psrc,width,height) )
- xine_fast_memcpy(pdst,psrc[0],width*height);
- }
- else /* FIXME: provide an alternative? */
- xine_fast_memcpy(pdst,psrc[0],width*height);
- break;
- case DEINTERLACE_GREEDY:
- if( check_for_mmx() )
- {
- if( !deinterlace_greedy_yuv_mmx(pdst,psrc,width,height) )
- xine_fast_memcpy(pdst,psrc[0],width*height);
- }
- else /* FIXME: provide an alternative? */
- xine_fast_memcpy(pdst,psrc[0],width*height);
- break;
- case DEINTERLACE_ONEFIELD:
- if( check_for_mmx() )
- deinterlace_onefield_yuv_mmx(pdst,psrc,width,height);
- else /* FIXME: provide an alternative? */
- xine_fast_memcpy(pdst,psrc[0],width*height);
- break;
- case DEINTERLACE_ONEFIELDXV:
- lprintf("ONEFIELDXV must be handled by the video driver.\n");
- break;
- case DEINTERLACE_LINEARBLEND:
- if( check_for_mmx() )
- deinterlace_linearblend_yuv_mmx(pdst,psrc,width,height);
- else
- deinterlace_linearblend_yuv(pdst,psrc,width,height);
- break;
- default:
- lprintf("unknown method %d.\n",method);
- break;
- }
-}
-
-int deinterlace_yuv_supported ( int method )
-{
- switch( method ) {
- case DEINTERLACE_NONE:
- return 1;
- case DEINTERLACE_BOB:
- case DEINTERLACE_WEAVE:
- case DEINTERLACE_GREEDY:
- case DEINTERLACE_ONEFIELD:
- return check_for_mmx();
- case DEINTERLACE_ONEFIELDXV:
- lprintf ("ONEFIELDXV must be handled by the video driver.\n");
- return 0;
- case DEINTERLACE_LINEARBLEND:
- return 1;
- }
-
- return 0;
-}
-
-const char *deinterlace_methods[] = {
- "none",
- "bob",
- "weave",
- "greedy",
- "onefield",
- "onefield_xv",
- "linearblend",
- NULL
-};
-
-
+++ /dev/null
- /*
- * Copyright (C) 2001 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Deinterlace routines by Miguel Freitas
- * based of DScaler project sources (deinterlace.sourceforge.net)
- *
- * Currently only available for Xv driver and MMX extensions
- *
- */
-
-#ifndef __DEINTERLACE_H__
-#define __DEINTERLACE_H__
-
-//#include "video_out.h"
-#include <stdint.h>
-
-int deinterlace_yuv_supported ( int method );
-void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[],
- int width, int height, int method );
-
-#define DEINTERLACE_NONE 0
-#define DEINTERLACE_BOB 1
-#define DEINTERLACE_WEAVE 2
-#define DEINTERLACE_GREEDY 3
-#define DEINTERLACE_ONEFIELD 4
-#define DEINTERLACE_ONEFIELDXV 5
-#define DEINTERLACE_LINEARBLEND 6
-
-extern const char *deinterlace_methods[];
-
-#endif
+++ /dev/null
-/*
- * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-#include <framework/mlt.h>
-
-extern mlt_filter filter_deinterlace_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
-
-MLT_REPOSITORY
-{
- MLT_REGISTER( filter_type, "deinterlace", filter_deinterlace_init );
-}
+++ /dev/null
-/*
- * filter_deinterlace.c -- deinterlace filter
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <framework/mlt_filter.h>
-#include "deinterlace.h"
-
-#include <framework/mlt_frame.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-/** Do it :-).
-*/
-
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
-{
- int error = 0;
- int deinterlace = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "consumer_deinterlace" );
-
- // Pop the service off the stack
- mlt_filter filter = mlt_frame_pop_service( this );
-
- // Determine if we need a writable version or not
- if ( deinterlace && !writable )
- writable = !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" );
-
- // Get the input image
- error = mlt_frame_get_image( this, image, format, width, height, writable );
-
- // Check that we want progressive and we aren't already progressive
- if ( deinterlace && *format == mlt_image_yuv422 && *image != NULL && !mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "progressive" ) )
- {
- // Determine deinterlace method
- char *method_str = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "method" );
- int method = DEINTERLACE_LINEARBLEND;
- char *frame_method_str = mlt_properties_get( MLT_FRAME_PROPERTIES( this ), "deinterlace_method" );
-
- if ( frame_method_str != NULL )
- method_str = frame_method_str;
-
- if ( method_str == NULL )
- method = DEINTERLACE_LINEARBLEND;
- else if ( strcmp( method_str, "bob" ) == 0 )
- method = DEINTERLACE_BOB;
- else if ( strcmp( method_str, "weave" ) == 0 )
- method = DEINTERLACE_BOB;
- else if ( strcmp( method_str, "greedy" ) == 0 )
- method = DEINTERLACE_GREEDY;
- else if ( strcmp( method_str, "onefield" ) == 0 )
- method = DEINTERLACE_ONEFIELD;
-
- // Deinterlace the image
- deinterlace_yuv( *image, image, *width * 2, *height, method );
-
- // Make sure that others know the frame is deinterlaced
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "progressive", 1 );
- }
-
- return error;
-}
-
-/** Deinterlace filter processing - this should be lazy evaluation here...
-*/
-
-static mlt_frame deinterlace_process( mlt_filter this, mlt_frame frame )
-{
- // Push this on to the service stack
- mlt_frame_push_service( frame, this );
-
- // Push the get_image method on to the stack
- mlt_frame_push_get_image( frame, filter_get_image );
-
- return frame;
-}
-
-/** Constructor for the filter.
-*/
-
-mlt_filter filter_deinterlace_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
-{
- mlt_filter this = mlt_filter_new( );
- if ( this != NULL )
- {
- this->process = deinterlace_process;
- mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "method", arg );
- }
- return this;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2000-2004 the xine project
- *
- * This file is part of xine, a free video player.
- *
- * xine is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * xine is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * $Id$
- *
- */
-#ifndef XINEUTILS_H
-#define XINEUTILS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <inttypes.h>
-#include <pthread.h>
-#if HAVE_LIBGEN_H
-# include <libgen.h>
-#endif
-
-//#ifdef XINE_COMPILE
-# include "attributes.h"
-//# include "compat.h"
-//# include "xmlparser.h"
-//# include "xine_buffer.h"
-//# include "configfile.h"
-//#else
-//# include <xine/attributes.h>
-//# include <xine/compat.h>
-//# include <xine/xmlparser.h>
-//# include <xine/xine_buffer.h>
-//# include <xine/configfile.h>
-//#endif
-
-//#ifdef HAVE_CONFIG_H
-//#include "config.h"
-//#endif
-
-#include <stdio.h>
-#include <string.h>
-
- /*
- * debugable mutexes
- */
-
- typedef struct {
- pthread_mutex_t mutex;
- char id[80];
- char *locked_by;
- } xine_mutex_t;
-
- int xine_mutex_init (xine_mutex_t *mutex, const pthread_mutexattr_t *mutexattr,
- char *id);
-
- int xine_mutex_lock (xine_mutex_t *mutex, char *who);
- int xine_mutex_unlock (xine_mutex_t *mutex, char *who);
- int xine_mutex_destroy (xine_mutex_t *mutex);
-
-
-
- /* CPU Acceleration */
-
-/*
- * The type of an value that fits in an MMX register (note that long
- * long constant values MUST be suffixed by LL and unsigned long long
- * values by ULL, lest they be truncated by the compiler)
- */
-
-/* generic accelerations */
-#define MM_ACCEL_MLIB 0x00000001
-
-/* x86 accelerations */
-#define MM_ACCEL_X86_MMX 0x80000000
-#define MM_ACCEL_X86_3DNOW 0x40000000
-#define MM_ACCEL_X86_MMXEXT 0x20000000
-#define MM_ACCEL_X86_SSE 0x10000000
-#define MM_ACCEL_X86_SSE2 0x08000000
-/* powerpc accelerations */
-#define MM_ACCEL_PPC_ALTIVEC 0x04000000
-/* x86 compat defines */
-#define MM_MMX MM_ACCEL_X86_MMX
-#define MM_3DNOW MM_ACCEL_X86_3DNOW
-#define MM_MMXEXT MM_ACCEL_X86_MMXEXT
-#define MM_SSE MM_ACCEL_X86_SSE
-#define MM_SSE2 MM_ACCEL_X86_SSE2
-
-uint32_t xine_mm_accel (void);
-
-#ifdef USE_MMX
-
-typedef union {
- int64_t q; /* Quadword (64-bit) value */
- uint64_t uq; /* Unsigned Quadword */
- int d[2]; /* 2 Doubleword (32-bit) values */
- unsigned int ud[2]; /* 2 Unsigned Doubleword */
- short w[4]; /* 4 Word (16-bit) values */
- unsigned short uw[4]; /* 4 Unsigned Word */
- char b[8]; /* 8 Byte (8-bit) values */
- unsigned char ub[8]; /* 8 Unsigned Byte */
- float s[2]; /* Single-precision (32-bit) value */
-} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */
-
-
-
-#define mmx_i2r(op,imm,reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "i" (imm) )
-
-#define mmx_m2r(op,mem,reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "m" (mem))
-
-#define mmx_r2m(op,reg,mem) \
- __asm__ __volatile__ (#op " %%" #reg ", %0" \
- : "=m" (mem) \
- : /* nothing */ )
-
-#define mmx_r2r(op,regs,regd) \
- __asm__ __volatile__ (#op " %" #regs ", %" #regd)
-
-
-#define emms() __asm__ __volatile__ ("emms")
-
-#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
-#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
-#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
-
-#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
-#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
-#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
-
-#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
-#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
-#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
-#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
-
-#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
-#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
-
-#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
-#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
-#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
-#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
-#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
-#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
-
-#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
-#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
-#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
-#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
-
-#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
-#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
-#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
-#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
-
-#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
-#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
-
-#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
-#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
-
-#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
-#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
-#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
-#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
-#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
-#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
-
-#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
-#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
-#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
-#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
-#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
-#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
-
-#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
-#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
-
-#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
-#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
-
-#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
-#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
-
-#define por_m2r(var,reg) mmx_m2r (por, var, reg)
-#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
-
-#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
-#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
-#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
-#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
-#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
-#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
-#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
-#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
-#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
-
-#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
-#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
-#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
-#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
-#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
-#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
-
-#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
-#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
-#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
-#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
-#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
-#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
-#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
-#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
-#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
-
-#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
-#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
-#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
-#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
-#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
-#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
-
-#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
-#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
-#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
-#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
-
-#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
-#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
-#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
-#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
-
-#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
-#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
-#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
-#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
-#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
-#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
-
-#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
-#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
-#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
-#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
-#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
-#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
-
-#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
-#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
-
-
-/* 3DNOW extensions */
-
-#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
-#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
-
-
-/* AMD MMX extensions - also available in intel SSE */
-
-
-#define mmx_m2ri(op,mem,reg,imm) \
- __asm__ __volatile__ (#op " %1, %0, %%" #reg \
- : /* nothing */ \
- : "X" (mem), "X" (imm))
-#define mmx_r2ri(op,regs,regd,imm) \
- __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
- : /* nothing */ \
- : "X" (imm) )
-
-#define mmx_fetch(mem,hint) \
- __asm__ __volatile__ ("prefetch" #hint " %0" \
- : /* nothing */ \
- : "X" (mem))
-
-
-#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
-
-#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
-
-#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
-#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
-#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
-#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
-
-#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
-
-#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
-
-#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
-#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
-
-#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
-#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
-
-#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
-#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
-
-#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
-#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
-
-#define pmovmskb(mmreg,reg) \
- __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
-
-#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
-#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
-
-#define prefetcht0(mem) mmx_fetch (mem, t0)
-#define prefetcht1(mem) mmx_fetch (mem, t1)
-#define prefetcht2(mem) mmx_fetch (mem, t2)
-#define prefetchnta(mem) mmx_fetch (mem, nta)
-
-#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
-#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
-
-#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
-#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
-
-#define sfence() __asm__ __volatile__ ("sfence\n\t")
-
-typedef union {
- float sf[4]; /* Single-precision (32-bit) value */
-} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */
-
-
-#define sse_i2r(op, imm, reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "X" (imm) )
-
-#define sse_m2r(op, mem, reg) \
- __asm__ __volatile__ (#op " %0, %%" #reg \
- : /* nothing */ \
- : "X" (mem))
-
-#define sse_r2m(op, reg, mem) \
- __asm__ __volatile__ (#op " %%" #reg ", %0" \
- : "=X" (mem) \
- : /* nothing */ )
-
-#define sse_r2r(op, regs, regd) \
- __asm__ __volatile__ (#op " %" #regs ", %" #regd)
-
-#define sse_r2ri(op, regs, regd, imm) \
- __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
- : /* nothing */ \
- : "X" (imm) )
-
-#define sse_m2ri(op, mem, reg, subop) \
- __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \
- : /* nothing */ \
- : "X" (mem))
-
-
-#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg)
-#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var)
-#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd)
-
-#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var)
-
-#define movups_m2r(var, reg) sse_m2r(movups, var, reg)
-#define movups_r2m(reg, var) sse_r2m(movups, reg, var)
-#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd)
-
-#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd)
-
-#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd)
-
-#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg)
-#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var)
-
-#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg)
-#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var)
-
-#define movss_m2r(var, reg) sse_m2r(movss, var, reg)
-#define movss_r2m(reg, var) sse_r2m(movss, reg, var)
-#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd)
-
-#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index)
-#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index)
-
-#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg)
-#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg)
-
-#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg)
-#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg)
-
-#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg)
-#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg)
-
-#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg)
-#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg)
-
-#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg)
-#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg)
-
-#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg)
-#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg)
-
-#define movmskps(xmmreg, reg) \
- __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg)
-
-#define addps_m2r(var, reg) sse_m2r(addps, var, reg)
-#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd)
-
-#define addss_m2r(var, reg) sse_m2r(addss, var, reg)
-#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd)
-
-#define subps_m2r(var, reg) sse_m2r(subps, var, reg)
-#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd)
-
-#define subss_m2r(var, reg) sse_m2r(subss, var, reg)
-#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd)
-
-#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg)
-#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd)
-
-#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg)
-#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd)
-
-#define divps_m2r(var, reg) sse_m2r(divps, var, reg)
-#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd)
-
-#define divss_m2r(var, reg) sse_m2r(divss, var, reg)
-#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd)
-
-#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg)
-#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd)
-
-#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg)
-#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd)
-
-#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg)
-#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd)
-
-#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg)
-#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd)
-
-#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg)
-#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd)
-
-#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg)
-#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd)
-
-#define andps_m2r(var, reg) sse_m2r(andps, var, reg)
-#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd)
-
-#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg)
-#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd)
-
-#define orps_m2r(var, reg) sse_m2r(orps, var, reg)
-#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd)
-
-#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg)
-#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd)
-
-#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg)
-#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd)
-
-#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg)
-#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd)
-
-#define minps_m2r(var, reg) sse_m2r(minps, var, reg)
-#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd)
-
-#define minss_m2r(var, reg) sse_m2r(minss, var, reg)
-#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd)
-
-#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op)
-#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op)
-
-#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0)
-#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0)
-
-#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1)
-#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1)
-
-#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2)
-#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2)
-
-#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3)
-#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3)
-
-#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4)
-#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4)
-
-#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5)
-#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5)
-
-#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6)
-#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6)
-
-#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7)
-#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7)
-
-#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op)
-#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op)
-
-#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0)
-#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0)
-
-#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1)
-#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1)
-
-#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2)
-#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2)
-
-#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3)
-#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3)
-
-#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4)
-#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4)
-
-#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5)
-#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5)
-
-#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6)
-#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6)
-
-#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7)
-#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7)
-
-#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg)
-#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd)
-
-#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg)
-#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd)
-
-#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg)
-#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd)
-
-#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg)
-#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd)
-
-#define fxrstor(mem) \
- __asm__ __volatile__ ("fxrstor %0" \
- : /* nothing */ \
- : "X" (mem))
-
-#define fxsave(mem) \
- __asm__ __volatile__ ("fxsave %0" \
- : /* nothing */ \
- : "X" (mem))
-
-#define stmxcsr(mem) \
- __asm__ __volatile__ ("stmxcsr %0" \
- : /* nothing */ \
- : "X" (mem))
-
-#define ldmxcsr(mem) \
- __asm__ __volatile__ ("ldmxcsr %0" \
- : /* nothing */ \
- : "X" (mem))
-#endif /* USE_MMX */
-
-
-
- /* Optimized/fast memcpy */
-
-/*
- TODO : fix dll linkage problem for xine_fast_memcpy on win32
-
- xine_fast_memcpy dll linkage is screwy here.
- declaring as dllimport seems to fix the problem
- but causes compiler warning with libxineutils
-*/
-#ifdef _MSC_VER
-__declspec( dllimport ) extern void *(* xine_fast_memcpy)(void *to, const void *from, size_t len);
-#else
-extern void *(* xine_fast_memcpy)(void *to, const void *from, size_t len);
-#endif
-
-#ifdef HAVE_XINE_INTERNAL_H
-/* Benchmark available memcpy methods */
-void xine_probe_fast_memcpy(xine_t *xine);
-#endif
-
-
-/*
- * Debug stuff
- */
-/*
- * profiling (unworkable in non DEBUG isn't defined)
- */
-void xine_profiler_init (void);
-int xine_profiler_allocate_slot (char *label);
-void xine_profiler_start_count (int id);
-void xine_profiler_stop_count (int id);
-void xine_profiler_print_results (void);
-
-/*
- * Allocate and clean memory size_t 'size', then return the pointer
- * to the allocated memory.
- */
-#if !defined(__GNUC__) || __GNUC__ < 3
-void *xine_xmalloc(size_t size);
-#else
-void *xine_xmalloc(size_t size) __attribute__ ((__malloc__));
-#endif
-
-/*
- * Same as above, but memory is aligned to 'alignement'.
- * **base is used to return pointer to un-aligned memory, use
- * this to free the mem chunk
- */
-void *xine_xmalloc_aligned(size_t alignment, size_t size, void **base);
-
-/*
- * Get user home directory.
- */
-const char *xine_get_homedir(void);
-
-/*
- * Clean a string (remove spaces and '=' at the begin,
- * and '\n', '\r' and spaces at the end.
- */
-char *xine_chomp (char *str);
-
-/*
- * A thread-safe usecond sleep
- */
-void xine_usec_sleep(unsigned usec);
-
-
- /*
- * Some string functions
- */
-
-
-void xine_strdupa(char *dest, char *src);
-#define xine_strdupa(d, s) do { \
- (d) = NULL; \
- if((s) != NULL) { \
- (d) = (char *) alloca(strlen((s)) + 1); \
- strcpy((d), (s)); \
- } \
- } while(0)
-
-/* Shamefully copied from glibc 2.2.3 */
-#ifdef HAVE_STRPBRK
-#define xine_strpbrk strpbrk
-#else
-static inline const char *_private_strpbrk(const char *s, const char *accept) {
-
- while(*s != '\0') {
- const char *a = accept;
- while(*a != '\0')
- if(*a++ == *s)
- return s;
- ++s;
- }
-
- return NULL;
-}
-#define xine_strpbrk _private_strpbrk
-#endif
-
-#if defined HAVE_STRSEP && !defined(_MSC_VER)
-#define xine_strsep strsep
-#else
-static inline char *_private_strsep(char **stringp, const char *delim) {
- char *begin, *end;
-
- begin = *stringp;
- if(begin == NULL)
- return NULL;
-
- if(delim[0] == '\0' || delim[1] == '\0') {
- char ch = delim[0];
-
- if(ch == '\0')
- end = NULL;
- else {
- if(*begin == ch)
- end = begin;
- else if(*begin == '\0')
- end = NULL;
- else
- end = strchr(begin + 1, ch);
- }
- }
- else
- end = xine_strpbrk(begin, delim);
-
- if(end) {
- *end++ = '\0';
- *stringp = end;
- }
- else
- *stringp = NULL;
-
- return begin;
-}
-#define xine_strsep _private_strsep
-#endif
-
-
-#ifdef HAVE_SETENV
-#define xine_setenv setenv
-#else
-static inline void _private_setenv(const char *name, const char *val, int _xx) {
- int len = strlen(name) + strlen(val) + 2;
- char env[len];
-
- sprintf(env, "%s%c%s", name, '=', val);
- putenv(env);
-}
-#define xine_setenv _private_setenv
-#endif
-
-/*
- * Color Conversion Utility Functions
- * The following data structures and functions facilitate the conversion
- * of RGB images to packed YUV (YUY2) images. There are also functions to
- * convert from YUV9 -> YV12. All of the meaty details are written in
- * color.c.
- */
-
-typedef struct yuv_planes_s {
-
- unsigned char *y;
- unsigned char *u;
- unsigned char *v;
- unsigned int row_width; /* frame width */
- unsigned int row_count; /* frame height */
-
-} yuv_planes_t;
-
-void init_yuv_conversion(void);
-void init_yuv_planes(yuv_planes_t *yuv_planes, int width, int height);
-void free_yuv_planes(yuv_planes_t *yuv_planes);
-
-extern void (*yuv444_to_yuy2)
- (yuv_planes_t *yuv_planes, unsigned char *yuy2_map, int pitch);
-extern void (*yuv9_to_yv12)
- (unsigned char *y_src, int y_src_pitch, unsigned char *y_dest, int y_dest_pitch,
- unsigned char *u_src, int u_src_pitch, unsigned char *u_dest, int u_dest_pitch,
- unsigned char *v_src, int v_src_pitch, unsigned char *v_dest, int v_dest_pitch,
- int width, int height);
-extern void (*yuv411_to_yv12)
- (unsigned char *y_src, int y_src_pitch, unsigned char *y_dest, int y_dest_pitch,
- unsigned char *u_src, int u_src_pitch, unsigned char *u_dest, int u_dest_pitch,
- unsigned char *v_src, int v_src_pitch, unsigned char *v_dest, int v_dest_pitch,
- int width, int height);
-extern void (*yv12_to_yuy2)
- (unsigned char *y_src, int y_src_pitch,
- unsigned char *u_src, int u_src_pitch,
- unsigned char *v_src, int v_src_pitch,
- unsigned char *yuy2_map, int yuy2_pitch,
- int width, int height, int progressive);
-extern void (*yuy2_to_yv12)
- (unsigned char *yuy2_map, int yuy2_pitch,
- unsigned char *y_dst, int y_dst_pitch,
- unsigned char *u_dst, int u_dst_pitch,
- unsigned char *v_dst, int v_dst_pitch,
- int width, int height);
-
-#define SCALEFACTOR 65536
-#define CENTERSAMPLE 128
-
-#define COMPUTE_Y(r, g, b) \
- (unsigned char) \
- ((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR)
-#define COMPUTE_U(r, g, b) \
- (unsigned char) \
- ((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
-#define COMPUTE_V(r, g, b) \
- (unsigned char) \
- ((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE)
-
-#define UNPACK_BGR15(packed_pixel, r, g, b) \
- b = (packed_pixel & 0x7C00) >> 7; \
- g = (packed_pixel & 0x03E0) >> 2; \
- r = (packed_pixel & 0x001F) << 3;
-
-#define UNPACK_BGR16(packed_pixel, r, g, b) \
- b = (packed_pixel & 0xF800) >> 8; \
- g = (packed_pixel & 0x07E0) >> 3; \
- r = (packed_pixel & 0x001F) << 3;
-
-#define UNPACK_RGB15(packed_pixel, r, g, b) \
- r = (packed_pixel & 0x7C00) >> 7; \
- g = (packed_pixel & 0x03E0) >> 2; \
- b = (packed_pixel & 0x001F) << 3;
-
-#define UNPACK_RGB16(packed_pixel, r, g, b) \
- r = (packed_pixel & 0xF800) >> 8; \
- g = (packed_pixel & 0x07E0) >> 3; \
- b = (packed_pixel & 0x001F) << 3;
-
-extern int y_r_table[256];
-extern int y_g_table[256];
-extern int y_b_table[256];
-
-extern int u_r_table[256];
-extern int u_g_table[256];
-extern int u_b_table[256];
-
-extern int v_r_table[256];
-extern int v_g_table[256];
-extern int v_b_table[256];
-
-/* frame copying functions */
-extern void yv12_to_yv12
- (unsigned char *y_src, int y_src_pitch, unsigned char *y_dst, int y_dst_pitch,
- unsigned char *u_src, int u_src_pitch, unsigned char *u_dst, int u_dst_pitch,
- unsigned char *v_src, int v_src_pitch, unsigned char *v_dst, int v_dst_pitch,
- int width, int height);
-extern void yuy2_to_yuy2
- (unsigned char *src, int src_pitch,
- unsigned char *dst, int dst_pitch,
- int width, int height);
-
-/* print a hexdump of the given data */
-void xine_hexdump (const char *buf, int length);
-
-/*
- * Optimization macros for conditions
- * Taken from the FIASCO L4 microkernel sources
- */
-#if !defined(__GNUC__) || __GNUC__ < 3
-# define EXPECT_TRUE(x) (x)
-# define EXPECT_FALSE(x) (x)
-#else
-# define EXPECT_TRUE(x) __builtin_expect((x),1)
-# define EXPECT_FALSE(x) __builtin_expect((x),0)
-#endif
-
-#ifdef NDEBUG
-#define _x_assert(exp) \
- do { \
- if (!(exp)) \
- fprintf(stderr, "assert: %s:%d: %s: Assertion `%s' failed.\n", \
- __FILE__, __LINE__, __XINE_FUNCTION__, #exp); \
- } while(0)
-#else
-#define _x_assert(exp) \
- do { \
- if (!(exp)) { \
- fprintf(stderr, "assert: %s:%d: %s: Assertion `%s' failed.\n", \
- __FILE__, __LINE__, __XINE_FUNCTION__, #exp); \
- abort(); \
- } \
- } while(0)
-#endif
-
-#define _x_abort() \
- do { \
- fprintf(stderr, "abort: %s:%d: %s: Aborting.\n", \
- __FILE__, __LINE__, __XINE_FUNCTION__); \
- abort(); \
- } while(0)
-
-
-/****** logging with xine **********************************/
-
-#ifndef LOG_MODULE
- #define LOG_MODULE __FILE__
-#endif /* LOG_MODULE */
-
-#define LOG_MODULE_STRING printf("%s: ", LOG_MODULE );
-
-#ifdef LOG_VERBOSE
- #define LONG_LOG_MODULE_STRING \
- printf("%s: (%s:%d) ", LOG_MODULE, __XINE_FUNCTION__, __LINE__ );
-#else
- #define LONG_LOG_MODULE_STRING LOG_MODULE_STRING
-#endif /* LOG_VERBOSE */
-
-#ifdef LOG
- #ifdef __GNUC__
- #define lprintf(fmt, args...) \
- do { \
- LONG_LOG_MODULE_STRING \
- printf(fmt, ##args); \
- } while(0)
- #else /* __GNUC__ */
- #ifdef _MSC_VER
- #define lprintf(fmtargs) \
- do { \
- LONG_LOG_MODULE_STRING \
- printf("%s", fmtargs); \
- } while(0)
- #else /* _MSC_VER */
- #define lprintf(fmt, ...) \
- do { \
- LONG_LOG_MODULE_STRING \
- printf(__VA_ARGS__); \
- } while(0)
- #endif /* _MSC_VER */
- #endif /* __GNUC__ */
-#else /* LOG */
- #ifdef __GNUC__
- #define lprintf(fmt, args...) do {} while(0)
- #else
- #ifdef _MSC_VER
- #define lprintf
- #else
- #define lprintf(...) do {} while(0)
- #endif /* _MSC_VER */
- #endif /* __GNUC__ */
-#endif /* LOG */
-
-#ifdef __GNUC__
- #define llprintf(cat, fmt, args...) \
- do{ \
- if(cat){ \
- LONG_LOG_MODULE_STRING \
- printf( fmt, ##args ); \
- } \
- }while(0)
-#else
-#ifdef _MSC_VER
- #define llprintf(cat, fmtargs) \
- do{ \
- if(cat){ \
- LONG_LOG_MODULE_STRING \
- printf( "%s", fmtargs ); \
- } \
- }while(0)
-#else
- #define llprintf(cat, ...) \
- do{ \
- if(cat){ \
- LONG_LOG_MODULE_STRING \
- printf( __VA_ARGS__ ); \
- } \
- }while(0)
-#endif /* _MSC_VER */
-#endif /* __GNUC__ */
-
-#ifdef __GNUC__
- #define xprintf(xine, verbose, fmt, args...) \
- do { \
- if((xine) && (xine)->verbosity >= verbose){ \
- xine_log(xine, XINE_LOG_TRACE, fmt, ##args); \
- } \
- } while(0)
-#else
-#ifdef _MSC_VER
- #define xprintf(xine, verbose, fmtargs) \
- do { \
- if((xine) && (xine)->verbosity >= verbose){ \
- xine_log(xine, XINE_LOG_TRACE, fmtargs); \
- } \
- } while(0)
-#else
- #define xprintf(xine, verbose, ...) \
- do { \
- if((xine) && (xine)->verbosity >= verbose){ \
- xine_log(xine, XINE_LOG_TRACE, __VA_ARGS__); \
- } \
- } while(0)
-#endif /* _MSC_VER */
-#endif /* __GNUC__ */
-
-/* time measuring macros for profiling tasks */
-
-#ifdef DEBUG
-# define XINE_PROFILE(function) \
- do { \
- struct timeval current_time; \
- double dtime; \
- gettimeofday(¤t_time, NULL); \
- dtime = -(current_time.tv_sec + (current_time.tv_usec / 1000000.0)); \
- function; \
- gettimeofday(¤t_time, NULL); \
- dtime += current_time.tv_sec + (current_time.tv_usec / 1000000.0); \
- printf("%s: (%s:%d) took %lf seconds\n", \
- LOG_MODULE, __XINE_FUNCTION__, __LINE__, dtime); \
- } while(0)
-# define XINE_PROFILE_ACCUMULATE(function) \
- do { \
- struct timeval current_time; \
- static double dtime = 0; \
- gettimeofday(¤t_time, NULL); \
- dtime -= current_time.tv_sec + (current_time.tv_usec / 1000000.0); \
- function; \
- gettimeofday(¤t_time, NULL); \
- dtime += current_time.tv_sec + (current_time.tv_usec / 1000000.0); \
- printf("%s: (%s:%d) took %lf seconds\n", \
- LOG_MODULE, __XINE_FUNCTION__, __LINE__, dtime); \
- } while(0)
-#else
-# define XINE_PROFILE(function) function
-# define XINE_PROFILE_ACCUMULATE(function) function
-#endif /* LOG */
-
-
-/******** double chained lists with builtin iterator *******/
-
-typedef struct xine_node_s {
-
- struct xine_node_s *next, *prev;
-
- void *content;
-
- int priority;
-
-} xine_node_t;
-
-
-typedef struct {
-
- xine_node_t *first, *last, *cur;
-
-} xine_list_t;
-
-
-
-xine_list_t *xine_list_new (void);
-
-
-/**
- * dispose the whole list.
- * note: disposes _only_ the list structure, content must be free()d elsewhere
- */
-void xine_list_free(xine_list_t *l);
-
-
-/**
- * returns: Boolean
- */
-int xine_list_is_empty (xine_list_t *l);
-
-/**
- * return content of first entry in list.
- */
-void *xine_list_first_content (xine_list_t *l);
-
-/**
- * return next content in list.
- */
-void *xine_list_next_content (xine_list_t *l);
-
-/**
- * Return last content of list.
- */
-void *xine_list_last_content (xine_list_t *l);
-
-/**
- * Return previous content of list.
- */
-void *xine_list_prev_content (xine_list_t *l);
-
-/**
- * Append content to list, sorted by decreasing priority.
- */
-void xine_list_append_priority_content (xine_list_t *l, void *content, int priority);
-
-/**
- * Append content to list.
- */
-void xine_list_append_content (xine_list_t *l, void *content);
-
-/**
- * Insert content in list.
- */
-void xine_list_insert_content (xine_list_t *l, void *content);
-
-/**
- * Remove current content in list.
- * note: removes only the list entry; content must be free()d elsewhere.
- */
-void xine_list_delete_current (xine_list_t *l);
-
-#ifndef HAVE_BASENAME
-/*
- * get base name
- */
-char *basename (char const *name);
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-include ../../config.mak
-
-TARGET = dan charlie pango pixbuf dissolve luma
-
-CFLAGS += -I.. $(RDYNAMIC)
-
-LDFLAGS += -L../modules
-LDFLAGS += -L../framework -lmlt
-
-all: $(TARGET)
-
-hello: hello.o
- $(CC) hello.o -o $@ -L../framework -L../modules -lmlt
-
-pango: pango.o
- $(CC) pango.o -o $@ $(LDFLAGS)
-
-pixbuf: pixbuf.o
- $(CC) pixbuf.o -o $@ $(LDFLAGS)
-
-dissolve: dissolve.o
- $(CC) dissolve.o -o $@ $(LDFLAGS)
-
-luma: luma.o
- $(CC) luma.o -o $@ $(LDFLAGS)
-
-dan: dan.o
- $(CC) dan.o -o $@ $(LDFLAGS)
-
-charlie: charlie.o io.o
- $(CC) charlie.o io.o -o $@ $(LDFLAGS)
-
-clean:
- rm -f dan.o io.o charlie.o dan charlie
-
-depend: dan.c charlie.c io.c
- $(CC) -MM $(CFLAGS) $^ 1>.depend
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <framework/mlt.h>
-
-#include "io.h"
-
-mlt_producer create_producer( char *file )
-{
- mlt_producer result = NULL;
-
- // 1st Line preferences
- if ( strstr( file, ".inigo" ) )
- {
- char *args[ 2 ] = { file, NULL };
- result = mlt_factory_producer( "inigo", args );
- }
- else if ( strstr( file, ".mpg" ) )
- result = mlt_factory_producer( "mcmpeg", file );
- else if ( strstr( file, ".mpeg" ) )
- result = mlt_factory_producer( "mcmpeg", file );
- else if ( strstr( file, ".dat" ) )
- result = mlt_factory_producer( "mcmpeg", file );
- else if ( strstr( file, ".dv" ) )
- result = mlt_factory_producer( "mcdv", file );
- else if ( strstr( file, ".dif" ) )
- result = mlt_factory_producer( "mcdv", file );
- else if ( strstr( file, ".jpg" ) )
- result = mlt_factory_producer( "pixbuf", file );
- else if ( strstr( file, ".JPG" ) )
- result = mlt_factory_producer( "pixbuf", file );
- else if ( strstr( file, ".jpeg" ) )
- result = mlt_factory_producer( "pixbuf", file );
- else if ( strstr( file, ".png" ) )
- result = mlt_factory_producer( "pixbuf", file );
-
- // 2nd Line fallbacks
- if ( result == NULL && strstr( file, ".dv" ) )
- result = mlt_factory_producer( "libdv", file );
- else if ( result == NULL && strstr( file, ".dif" ) )
- result = mlt_factory_producer( "libdv", file );
-
- return result;
-}
-
-void transport_action( mlt_producer producer, char *value )
-{
- mlt_properties properties = mlt_producer_properties( producer );
-
- switch( value[ 0 ] )
- {
- case 'q':
- mlt_properties_set_int( properties, "done", 1 );
- break;
- case '0':
- mlt_producer_set_speed( producer, 1 );
- mlt_producer_seek( producer, 0 );
- break;
- case '1':
- mlt_producer_set_speed( producer, -5 );
- break;
- case '2':
- mlt_producer_set_speed( producer, -2.5 );
- break;
- case '3':
- mlt_producer_set_speed( producer, -1 );
- break;
- case '4':
- mlt_producer_set_speed( producer, -0.5 );
- break;
- case '5':
- mlt_producer_set_speed( producer, 0 );
- break;
- case '6':
- mlt_producer_set_speed( producer, 0.5 );
- break;
- case '7':
- mlt_producer_set_speed( producer, 1 );
- break;
- case '8':
- mlt_producer_set_speed( producer, 2.5 );
- break;
- case '9':
- mlt_producer_set_speed( producer, 5 );
- break;
- }
-}
-
-mlt_consumer create_consumer( char *id, mlt_producer producer )
-{
- char *arg = strchr( id, ':' );
- if ( arg != NULL )
- *arg ++ = '\0';
- mlt_consumer consumer = mlt_factory_consumer( id, arg );
- if ( consumer != NULL )
- {
- mlt_properties properties = mlt_consumer_properties( consumer );
- mlt_properties_set_data( properties, "transport_callback", transport_action, 0, NULL, NULL );
- mlt_properties_set_data( properties, "transport_producer", producer, 0, NULL, NULL );
- }
- return consumer;
-}
-
-void track_service( mlt_field field, void *service, mlt_destructor destructor )
-{
- mlt_properties properties = mlt_field_properties( field );
- int registered = mlt_properties_get_int( properties, "registered" );
- char *key = mlt_properties_get( properties, "registered" );
- mlt_properties_set_data( properties, key, service, 0, destructor, NULL );
- mlt_properties_set_int( properties, "registered", ++ registered );
-}
-
-void set_properties( mlt_service service, char *namevalue )
-{
- mlt_properties properties = mlt_service_properties( service );
- mlt_properties_parse( properties, namevalue );
-}
-
-void transport( mlt_producer producer )
-{
- mlt_properties properties = mlt_producer_properties( producer );
-
- term_init( );
- fprintf( stderr, "Press 'q' to continue\n" );
- while( mlt_properties_get_int( properties, "done" ) == 0 )
- {
- int value = term_read( );
- if ( value != -1 )
- transport_action( producer, ( char * )&value );
- }
-}
-
-int main( int argc, char **argv )
-{
- int i;
- mlt_service service = NULL;
- mlt_consumer consumer = NULL;
- mlt_producer producer = NULL;
- mlt_playlist playlist = NULL;
-
- // Construct the factory
- mlt_factory_init( getenv( "MLT_REPOSITORY" ) );
-
- // Set up containers
- playlist = mlt_playlist_init( );
-
- // Parse the arguments
- for ( i = 1; i < argc; i ++ )
- {
- if ( !strcmp( argv[ i ], "-consumer" ) )
- {
- consumer = create_consumer( argv[ ++ i ], mlt_playlist_producer( playlist ) );
- if ( consumer != NULL )
- service = mlt_consumer_service( consumer );
- }
- else if ( !strstr( argv[ i ], "=" ) )
- {
- if ( producer != NULL )
- mlt_playlist_append( playlist, producer );
- producer = create_producer( argv[ i ] );
- if ( producer != NULL )
- service = mlt_producer_service( producer );
- }
- else
- {
- set_properties( service, argv[ i ] );
- }
- }
-
- // If we have no consumer, default to sdl
- if ( consumer == NULL )
- consumer = create_consumer( "sdl", mlt_playlist_producer( playlist ) );
-
- // Connect producer to playlist
- if ( producer != NULL )
- mlt_playlist_append( playlist, producer );
-
- // Connect consumer to playlist
- mlt_consumer_connect( consumer, mlt_playlist_service( playlist ) );
-
- // Transport functionality
- transport( mlt_playlist_producer( playlist ) );
-
- // Close the services
- mlt_consumer_close( consumer );
- mlt_playlist_close( playlist );
-
- // Close the factory
- mlt_factory_close( );
-
- return 0;
-}
+++ /dev/null
-
-#include <framework/mlt.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-
-
-int main( int argc, char **argv )
-{
- mlt_properties p = mlt_properties_parse_yaml( argv[1] );
- mlt_properties q = mlt_properties_new();
- mlt_properties_set_data( q, "metadata", p, 0, ( mlt_destructor )mlt_properties_close, ( mlt_serialiser )mlt_properties_serialise_yaml );
- printf( "%s", mlt_properties_get( q, "metadata" ) );
- mlt_properties_close( q );
-
- mlt_repository repo = mlt_factory_init( NULL );
- mlt_properties metadata = mlt_repository_metadata( repo, producer_type, "avformat" );
- if ( metadata )
- {
- char *s = mlt_properties_serialise_yaml( metadata );
- printf( "%s", s );
- free( s );
- }
- mlt_factory_close();
- return 0;
-}
+++ /dev/null
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-
-int main( int argc, char **argv )
-{
- char temp[ 132 ];
- char *file1 = NULL;
- char *file2 = NULL;
-
- mlt_factory_init( "../modules" );
-
- if ( argc < 3 )
- {
- fprintf( stderr, "usage: dissolve file1.mpeg file2.mpeg\n" );
- return 1;
- }
- else
- {
- file1 = argv[ 1 ];
- file2 = argv[ 2 ];
- }
-
- // Start the consumer...
- mlt_consumer consumer = mlt_factory_consumer( "sdl", "PAL" );
-
- // Create the producer(s)
- mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 );
- mlt_producer dv2 = mlt_factory_producer( "mcmpeg", file2 );
-
- mlt_playlist playlist1 = mlt_playlist_init();
- mlt_playlist_append_io( playlist1, dv1, 0.0, 5.0 );
-
- mlt_playlist playlist2 = mlt_playlist_init();
- mlt_playlist_blank( playlist2, 2.9 );
- mlt_playlist_append( playlist2, dv2 );
-
- // Register producers(s) with a multitrack object
- mlt_multitrack multitrack = mlt_multitrack_init( );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist1 ), 0 );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist2 ), 1 );
-
- // Define a transition
- mlt_transition transition = mlt_factory_transition( "luma", NULL );
- mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 );
- mlt_transition_set_in_and_out( transition, 3.0, 5.0 );
-
- // Buy a tractor and connect it to the filter
- mlt_tractor tractor = mlt_tractor_init( );
- mlt_tractor_connect( tractor, mlt_transition_service( transition ) );
-
- // Connect the tractor to the consumer
- mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) );
-
- // Do stuff until we're told otherwise...
- fprintf( stderr, "Press return to continue\n" );
- fgets( temp, 132, stdin );
-
- // Close everything...
- mlt_consumer_close( consumer );
- mlt_tractor_close( tractor );
- mlt_transition_close( transition );
- mlt_multitrack_close( multitrack );
- mlt_playlist_close( playlist1 );
- mlt_playlist_close( playlist2 );
- mlt_producer_close( dv1 );
- mlt_producer_close( dv2 );
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <unistd.h>
-#include <framework/mlt.h>
-
-mlt_producer create_playlist( int argc, char **argv )
-{
- // We're creating a playlist here
- mlt_playlist playlist = mlt_playlist_init( );
-
- // We need the playlist properties to ensure clean up
- mlt_properties properties = mlt_playlist_properties( playlist );
-
- // Loop through each of the arguments
- int i = 0;
- for ( i = 1; i < argc; i ++ )
- {
- // Definie 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 );
- }
-
- // Return the playlist as a producer
- return mlt_playlist_producer( playlist );
-}
-
-mlt_producer create_tracks( int argc, char **argv )
-{
- // Create the field
- mlt_field field = mlt_field_init( );
-
- // Obtain the multitrack
- mlt_multitrack multitrack = mlt_field_multitrack( field );
-
- // Obtain the tractor
- mlt_tractor tractor = mlt_field_tractor( field );
-
- // Obtain a composite transition
- mlt_transition transition = mlt_factory_transition( "composite", "10%,10%:15%x15%" );
-
- // Create track 0
- mlt_producer track0 = create_playlist( argc, argv );
-
- // Get the length of track0
- mlt_position length = mlt_producer_get_playtime( track0 );
-
- // Create the watermark track
- mlt_producer track1 = mlt_factory_producer( "fezzik", "pango:" );
-
- // Get the properties of track1
- mlt_properties properties = mlt_producer_properties( track1 );
-
- // Set the properties
- mlt_properties_set( properties, "text", "Hello\nWorld" );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", length - 1 );
- mlt_properties_set_position( properties, "length", length );
-
- // Now set the properties on the transition
- properties = mlt_transition_properties( transition );
- mlt_properties_set_position( properties, "in", 0 );
- mlt_properties_set_position( properties, "out", length - 1 );
-
- // Add our tracks to the multitrack
- mlt_multitrack_connect( multitrack, track0, 0 );
- mlt_multitrack_connect( multitrack, track1, 1 );
-
- // Now plant the transition
- mlt_field_plant_transition( field, transition, 0, 1 );
-
- // Now set the properties on the transition
- properties = mlt_tractor_properties( tractor );
-
- // Ensure clean up and set properties correctly
- 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 );
- mlt_properties_set_position( properties, "length", length );
- mlt_properties_set_position( properties, "out", length - 1 );
-
- // Return the tractor
- return mlt_tractor_producer( tractor );
-}
-
-int main( int argc, char **argv )
-{
- // Initialise the factory
- if ( mlt_factory_init( NULL ) == 0 )
- {
- // Create the default consumer
- mlt_consumer hello = mlt_factory_consumer( NULL, NULL );
-
- // Create a producer using the default normalising selecter
- mlt_producer world = create_tracks( argc, argv );
-
- // Connect the producer to the consumer
- mlt_consumer_connect( hello, mlt_producer_service( world ) );
-
- // Start the consumer
- mlt_consumer_start( hello );
-
- // Wait for the consumer to terminate
- while( !mlt_consumer_is_stopped( hello ) )
- sleep( 1 );
-
- // Close the consumer
- mlt_consumer_close( hello );
-
- // Close the producer
- mlt_producer_close( world );
-
- // Close the factory
- mlt_factory_close( );
- }
- else
- {
- // Report an error during initialisation
- fprintf( stderr, "Unable to locate factory modules\n" );
- }
-
- // End of program
- return 0;
-}
-
+++ /dev/null
-/*
- * io.c -- dv1394d client demo input/output
- * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* System header files */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <termios.h>
-#include <unistd.h>
-
-/* Application header files */
-#include "io.h"
-
-char *chomp( char *input )
-{
- if ( input != NULL )
- {
- int length = strlen( input );
- if ( length && input[ length - 1 ] == '\n' )
- input[ length - 1 ] = '\0';
- if ( length > 1 && input[ length - 2 ] == '\r' )
- input[ length - 2 ] = '\0';
- }
- return input;
-}
-
-char *trim( char *input )
-{
- if ( input != NULL )
- {
- int length = strlen( input );
- int first = 0;
- while( first < length && isspace( input[ first ] ) )
- first ++;
- memmove( input, input + first, length - first + 1 );
- length = length - first;
- while ( length > 0 && isspace( input[ length - 1 ] ) )
- input[ -- length ] = '\0';
- }
- return input;
-}
-
-char *strip_quotes( char *input )
-{
- if ( input != NULL )
- {
- char *ptr = strrchr( input, '\"' );
- if ( ptr != NULL )
- *ptr = '\0';
- if ( input[ 0 ] == '\"' )
- strcpy( input, input + 1 );
- }
- return input;
-}
-
-char *get_string( char *output, int maxlength, char *use )
-{
- char *value = NULL;
- strcpy( output, use );
- if ( trim( chomp( fgets( output, maxlength, stdin ) ) ) != NULL )
- {
- if ( !strcmp( output, "" ) )
- strcpy( output, use );
- value = output;
- }
- return value;
-}
-
-int *get_int( int *output, int use )
-{
- int *value = NULL;
- char temp[ 132 ];
- *output = use;
- if ( trim( chomp( fgets( temp, 132, stdin ) ) ) != NULL )
- {
- if ( strcmp( temp, "" ) )
- *output = atoi( temp );
- value = output;
- }
- return value;
-}
-
-/** This stores the previous settings
-*/
-
-static struct termios oldtty;
-static int mode = 0;
-
-/** This is called automatically on application exit to restore the
- previous tty settings.
-*/
-
-void term_exit(void)
-{
- if ( mode == 1 )
- {
- tcsetattr( 0, TCSANOW, &oldtty );
- mode = 0;
- }
-}
-
-/** Init terminal so that we can grab keys without blocking.
-*/
-
-void term_init( )
-{
- struct termios tty;
-
- tcgetattr( 0, &tty );
- oldtty = tty;
-
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
- tty.c_cflag &= ~(CSIZE|PARENB);
- tty.c_cflag |= CS8;
- tty.c_cc[ VMIN ] = 1;
- tty.c_cc[ VTIME ] = 0;
-
- tcsetattr( 0, TCSANOW, &tty );
-
- mode = 1;
-
- atexit( term_exit );
-}
-
-/** Check for a keypress without blocking infinitely.
- Returns: ASCII value of keypress or -1 if no keypress detected.
-*/
-
-int term_read( )
-{
- int n = 1;
- unsigned char ch;
- struct timeval tv;
- fd_set rfds;
-
- FD_ZERO( &rfds );
- FD_SET( 0, &rfds );
- tv.tv_sec = 0;
- tv.tv_usec = 250;
- n = select( 1, &rfds, NULL, NULL, &tv );
- if (n > 0)
- {
- n = read( 0, &ch, 1 );
- tcflush( 0, TCIFLUSH );
- if (n == 1)
- return ch;
- return n;
- }
- return -1;
-}
-
-char get_keypress( )
-{
- char value = '\0';
- int pressed = 0;
-
- fflush( stdout );
-
- term_init( );
- while ( ( pressed = term_read( ) ) == -1 ) ;
- term_exit( );
-
- value = (char)pressed;
-
- return value;
-}
-
-void wait_for_any_key( char *message )
-{
- if ( message == NULL )
- printf( "Press any key to continue: " );
- else
- printf( "%s", message );
-
- get_keypress( );
-
- printf( "\n\n" );
-}
-
-void beep( )
-{
- printf( "%c", 7 );
- fflush( stdout );
-}
+++ /dev/null
-/*
- * io.h -- dv1394d client demo input/output
- * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
- * Author: Charles Yates <charles.yates@pandora.be>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DEMO_IO_H_
-#define _DEMO_IO_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-extern char *chomp( char * );
-extern char *trim( char * );
-extern char *strip_quotes( char * );
-extern char *get_string( char *, int, char * );
-extern int *get_int( int *, int );
-extern void term_init( );
-extern int term_read( );
-extern void term_exit( );
-extern char get_keypress( );
-extern void wait_for_any_key( char * );
-extern void beep( );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-
-int main( int argc, char **argv )
-{
- char temp[ 132 ];
- char *file1 = NULL;
- char *file2 = NULL;
- char *wipe = NULL;
-
- mlt_factory_init( "../modules" );
-
- if ( argc < 4 )
- {
- fprintf( stderr, "usage: luma file1.mpeg file2.mpeg wipe.pgm\n" );
- return 1;
- }
- else
- {
- file1 = argv[ 1 ];
- file2 = argv[ 2 ];
- wipe = argv[ 3 ];
- }
-
- // Start the consumer...
- mlt_consumer consumer = mlt_factory_consumer( "bluefish", "NTSC" );
-
- // Create the producer(s)
- mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 );
- mlt_producer dv2 = mlt_factory_producer( "mcmpeg", file2 );
-
- mlt_playlist playlist1 = mlt_playlist_init();
- mlt_playlist_append_io( playlist1, dv1, 0.0, 5.0 );
-
- mlt_playlist playlist2 = mlt_playlist_init();
- mlt_playlist_blank( playlist2, 2.9 );
- mlt_playlist_append( playlist2, dv2 );
-
- // Register producers(s) with a multitrack object
- mlt_multitrack multitrack = mlt_multitrack_init( );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist1 ), 0 );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist2 ), 1 );
-
- // Define a transition
- mlt_transition transition = mlt_factory_transition( "luma", wipe );
- mlt_properties_set( mlt_transition_properties( transition ), "filename", wipe );
- mlt_properties_set_double( mlt_transition_properties( transition ), "softness", 0.1 );
- mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 );
- mlt_transition_set_in_and_out( transition, 3.0, 5.0 );
-
- // Buy a tractor and connect it to the filter
- mlt_tractor tractor = mlt_tractor_init( );
- mlt_tractor_connect( tractor, mlt_transition_service( transition ) );
-
- // Connect the tractor to the consumer
- mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) );
-
- // Do stuff until we're told otherwise...
- fprintf( stderr, "Press return to continue\n" );
- fgets( temp, 132, stdin );
-
- // Close everything...
- mlt_consumer_close( consumer );
- mlt_tractor_close( tractor );
- mlt_transition_close( transition );
- mlt_multitrack_close( multitrack );
- mlt_playlist_close( playlist1 );
- mlt_playlist_close( playlist2 );
- mlt_producer_close( dv1 );
- mlt_producer_close( dv2 );
-
- return 0;
-}
+++ /dev/null
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-
-int main( int argc, char **argv )
-{
- char temp[ 132 ];
- char *file1 = NULL;
- char *text = NULL;
-
- mlt_factory_init( "../modules" );
-
- if ( argc < 3 )
- {
- fprintf( stderr, "usage: pango file.mpeg text_to_display\n" );
- return 1;
- }
- else
- {
- file1 = argv[ 1 ];
- text = argv[ 2 ];
- }
-
- // Start the consumer...
- mlt_consumer consumer = mlt_factory_consumer( "bluefish", "NTSC" );
-
- // Create the producer(s)
- mlt_playlist pl1 = mlt_playlist_init();
- mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 );
- mlt_playlist_append( pl1, dv1 );
-
- mlt_playlist pl2 = mlt_playlist_init();
- mlt_producer title = mlt_factory_producer( "pango", NULL ); //"<span font_desc=\"Sans Bold 36\">Mutton <span font_desc=\"Luxi Serif Bold Oblique 36\">Lettuce</span> Tomato</span>" );
- mlt_playlist_append( pl2, title );
- mlt_properties_set( mlt_producer_properties( title ), "font", "Sans Bold 36" );
- mlt_properties_set( mlt_producer_properties( title ), "text", text );
- mlt_properties_set_int( mlt_producer_properties( title ), "bgcolor", 0x0000007f );
- mlt_properties_set_int( mlt_producer_properties( title ), "pad", 8 );
- mlt_properties_set_int( mlt_producer_properties( title ), "align", 1 );
- mlt_properties_set_int( mlt_producer_properties( title ), "x", 200 );
- mlt_properties_set_int( mlt_producer_properties( title ), "y", 40 );
- mlt_properties_set_double( mlt_producer_properties( title ), "mix", 0.8 );
-
- // Register producers(s) with a multitrack object
- mlt_multitrack multitrack = mlt_multitrack_init( );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( pl1 ), 0 );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( pl2 ), 1 );
-
- // Define a transition
- mlt_transition transition = mlt_factory_transition( "composite", NULL );
- mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 );
- mlt_transition_set_in_and_out( transition, 0.0, 9999.0 );
-
- // Buy a tractor and connect it to the filter
- mlt_tractor tractor = mlt_tractor_init( );
- mlt_tractor_connect( tractor, mlt_transition_service( transition ) );
-
- // Connect the tractor to the consumer
- mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) );
-
- // Do stuff until we're told otherwise...
- fprintf( stderr, "Press return to continue\n" );
- fgets( temp, 132, stdin );
-
- // Close everything...
- mlt_consumer_close( consumer );
- mlt_tractor_close( tractor );
- mlt_transition_close( transition );
- mlt_multitrack_close( multitrack );
- mlt_playlist_close( pl1 );
- mlt_playlist_close( pl2 );
- mlt_producer_close( dv1 );
- mlt_producer_close( title );
-
- return 0;
-}
+++ /dev/null
-
-#include <framework/mlt.h>
-
-#include <stdio.h>
-
-int main( int argc, char **argv )
-{
- char temp[ 132 ];
- char *file1 = NULL;
- char *file2 = NULL;
-
- mlt_factory_init( "../modules" );
-
- if ( argc < 3 )
- {
- fprintf( stderr, "usage: pixbuf file.mpeg file.{png,jpg,etc}\n" );
- return 1;
- }
- else
- {
- file1 = argv[ 1 ];
- file2 = argv[ 2 ];
- }
-
- // Start the consumer...
- mlt_consumer consumer = mlt_factory_consumer( "sdl", "PAL" );
-
- // Create the producer(s)
- mlt_playlist pl1 = mlt_playlist_init();
- mlt_producer dv1 = mlt_factory_producer( "mcmpeg", file1 );
- mlt_playlist_append( pl1, dv1 );
-
- mlt_playlist pl2 = mlt_playlist_init();
- mlt_producer overlay = mlt_factory_producer( "pixbuf", file2 );
- mlt_playlist_append( pl2, overlay );
- mlt_properties_set_int( mlt_producer_properties( overlay ), "x", 600 );
- mlt_properties_set_int( mlt_producer_properties( overlay ), "y", 460 );
- mlt_properties_set_double( mlt_producer_properties( overlay ), "mix", 0.8 );
-
- // Register producers(s) with a multitrack object
- mlt_multitrack multitrack = mlt_multitrack_init( );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( pl1 ), 0 );
- mlt_multitrack_connect( multitrack, mlt_playlist_producer( pl2 ), 1 );
-
- // Define a transition
- mlt_transition transition = mlt_factory_transition( "composite", NULL );
- mlt_transition_connect( transition, mlt_multitrack_service( multitrack ), 0, 1 );
- mlt_transition_set_in_and_out( transition, 0.0, 9999.0 );
-
- // Buy a tractor and connect it to the filter
- mlt_tractor tractor = mlt_tractor_init( );
- mlt_tractor_connect( tractor, mlt_transition_service( transition ) );
-
- // Connect the tractor to the consumer
- mlt_consumer_connect( consumer, mlt_tractor_service( tractor ) );
-
- // Do stuff until we're told otherwise...
- fprintf( stderr, "Press return to continue\n" );
- fgets( temp, 132, stdin );
-
- // Close everything...
- mlt_consumer_close( consumer );
- mlt_tractor_close( tractor );
- mlt_transition_close( transition );
- mlt_multitrack_close( multitrack );
- mlt_playlist_close( pl1 );
- mlt_playlist_close( pl2 );
- mlt_producer_close( dv1 );
- mlt_producer_close( overlay );
-
- return 0;
-}
+++ /dev/null
-export MLT_REPOSITORY=`pwd`/../modules
-
-export LD_LIBRARY_PATH=`pwd`/../framework:\
-`pwd`/../modules/bluefish:\
-`pwd`/../../../bluefish/lib:\
-`pwd`/../../../mpeg_sdk_demo/bin:\
-`pwd`/../../../dv_sdk