]> git.sesse.net Git - mlt/commitdiff
Merge branch 'frei0r-metadata'
authorDan Dennedy <dan@dennedy.org>
Sun, 17 Mar 2013 20:15:37 +0000 (13:15 -0700)
committerDan Dennedy <dan@dennedy.org>
Sun, 17 Mar 2013 20:15:37 +0000 (13:15 -0700)
379 files changed:
.gitignore
AUTHORS
ChangeLog
Doxyfile
GPLv3 [new file with mode: 0644]
Makefile
NEWS
configure
demo/mlt_ticker
docs/melt.1
docs/mlt-xml.txt
presets/consumer/avformat/AAC [new file with mode: 0644]
presets/consumer/avformat/Flash [new file with mode: 0644]
presets/consumer/avformat/MJPEG [new file with mode: 0644]
presets/consumer/avformat/MP3 [new file with mode: 0644]
presets/consumer/avformat/MPEG-2 [new file with mode: 0644]
presets/consumer/avformat/MPEG-4 [new file with mode: 0644]
presets/consumer/avformat/MPEG-4-ASP [new file with mode: 0644]
presets/consumer/avformat/Sony-PSP
presets/consumer/avformat/Vorbis [new file with mode: 0644]
presets/consumer/avformat/WAV [new file with mode: 0644]
presets/consumer/avformat/XDCAM-HD422
presets/consumer/avformat/atsc_1080i_50/DNxHD
presets/consumer/avformat/atsc_1080i_5994/DNxHD
presets/consumer/avformat/atsc_1080p_2398/DNxHD
presets/consumer/avformat/atsc_1080p_24/DNxHD
presets/consumer/avformat/atsc_1080p_25/DNxHD
presets/consumer/avformat/atsc_1080p_2997/DNxHD
presets/consumer/avformat/atsc_1080p_30/DNxHD
presets/consumer/avformat/atsc_1080p_50/DNxHD
presets/consumer/avformat/atsc_1080p_5994/DNxHD
presets/consumer/avformat/atsc_1080p_60/DNxHD
presets/consumer/avformat/atsc_720p_2398/DNxHD
presets/consumer/avformat/atsc_720p_50/DNxHD
presets/consumer/avformat/atsc_720p_5994/DNxHD
presets/consumer/avformat/atsc_720p_60/DNxHD
presets/consumer/avformat/dv_ntsc/D10
presets/consumer/avformat/dv_ntsc/DV
presets/consumer/avformat/dv_ntsc/DVCPRO50
presets/consumer/avformat/dv_ntsc/DVD
presets/consumer/avformat/dv_ntsc_wide/D10
presets/consumer/avformat/dv_ntsc_wide/DV
presets/consumer/avformat/dv_ntsc_wide/DVCPRO50
presets/consumer/avformat/dv_ntsc_wide/DVD
presets/consumer/avformat/dv_pal/D10
presets/consumer/avformat/dv_pal/DV
presets/consumer/avformat/dv_pal/DVCPRO50
presets/consumer/avformat/dv_pal/DVD
presets/consumer/avformat/dv_pal_wide/D10
presets/consumer/avformat/dv_pal_wide/DV
presets/consumer/avformat/dv_pal_wide/DVCPRO50
presets/consumer/avformat/dv_pal_wide/DVD
presets/consumer/avformat/hdv_1080_25p/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_1080_30p/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_1080_50i/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_1080_60i/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_720_25p/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_720_30p/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_720_50p/HDV [new file with mode: 0644]
presets/consumer/avformat/hdv_720_60p/HDV [new file with mode: 0644]
presets/consumer/avformat/lossless/FFV1 [new file with mode: 0644]
presets/consumer/avformat/lossless/H.264 [new file with mode: 0644]
presets/consumer/avformat/lossless/HuffYUV [new file with mode: 0644]
presets/consumer/avformat/lossless/MJPEG [new file with mode: 0644]
presets/consumer/avformat/lossless/MPEG-2 [new file with mode: 0644]
presets/consumer/avformat/lossless/MPEG-4 [new file with mode: 0644]
presets/consumer/avformat/lossless/ProRes [new file with mode: 0644]
presets/consumer/avformat/stills/BMP [new file with mode: 0644]
presets/consumer/avformat/stills/DPX [new file with mode: 0644]
presets/consumer/avformat/stills/JPEG [new file with mode: 0644]
presets/consumer/avformat/stills/PNG [new file with mode: 0644]
presets/consumer/avformat/stills/PPM [new file with mode: 0644]
presets/consumer/avformat/stills/TGA [new file with mode: 0644]
presets/consumer/avformat/stills/TIFF [new file with mode: 0644]
presets/consumer/avformat/webm
presets/consumer/avformat/x264-medium
presets/consumer/avformat/x264-medium-baseline
presets/consumer/avformat/x264-medium-main
presets/consumer/avformat/x264-medium-pass1
profiles/Makefile
src/framework/Makefile
src/framework/configure
src/framework/mlt.vers [new file with mode: 0644]
src/framework/mlt_cache.c
src/framework/mlt_cache.h
src/framework/mlt_consumer.c
src/framework/mlt_consumer.h
src/framework/mlt_deque.c
src/framework/mlt_events.c
src/framework/mlt_factory.c
src/framework/mlt_field.c
src/framework/mlt_filter.c
src/framework/mlt_frame.c
src/framework/mlt_frame.h
src/framework/mlt_geometry.c
src/framework/mlt_multitrack.c
src/framework/mlt_playlist.c
src/framework/mlt_playlist.h
src/framework/mlt_producer.c
src/framework/mlt_producer.h
src/framework/mlt_profile.c
src/framework/mlt_properties.c
src/framework/mlt_properties.h
src/framework/mlt_property.c
src/framework/mlt_property.h
src/framework/mlt_repository.c
src/framework/mlt_service.c
src/framework/mlt_service.h
src/framework/mlt_tractor.c
src/framework/mlt_transition.c
src/framework/mlt_types.h
src/framework/mlt_version.h
src/melt/Makefile
src/melt/configure [deleted file]
src/melt/io.c
src/melt/melt.c
src/mlt++/Makefile
src/mlt++/MltDeque.cpp
src/mlt++/MltDeque.h
src/mlt++/MltFilteredConsumer.cpp
src/mlt++/MltFilteredConsumer.h
src/mlt++/MltFilteredProducer.cpp
src/mlt++/MltFilteredProducer.h
src/mlt++/MltFrame.cpp
src/mlt++/MltFrame.h
src/mlt++/MltPlaylist.cpp
src/mlt++/MltPlaylist.h
src/mlt++/MltProducer.cpp
src/mlt++/MltProducer.h
src/mlt++/MltProfile.cpp
src/mlt++/MltProfile.h
src/mlt++/MltProperties.cpp
src/mlt++/MltProperties.h
src/mlt++/MltPushConsumer.cpp
src/mlt++/MltPushConsumer.h
src/mlt++/MltService.cpp
src/mlt++/MltService.h
src/mlt++/config.h
src/mlt++/configure
src/mlt++/mlt++.vers [new file with mode: 0644]
src/modules/Makefile
src/modules/avformat/Makefile
src/modules/avformat/configure
src/modules/avformat/consumer_avformat.c
src/modules/avformat/factory.c
src/modules/avformat/filter_avcolour_space.c
src/modules/avformat/filter_avdeinterlace.c
src/modules/avformat/filter_avresample.c
src/modules/avformat/filter_swscale.c
src/modules/avformat/producer_avformat.c
src/modules/avformat/producer_avformat.yml
src/modules/avformat/vdpau.c
src/modules/avsync/Makefile [new file with mode: 0644]
src/modules/avsync/consumer_blipflash.c [new file with mode: 0644]
src/modules/avsync/consumer_blipflash.yml [new file with mode: 0644]
src/modules/avsync/factory.c [new file with mode: 0644]
src/modules/avsync/producer_blipflash.c [new file with mode: 0644]
src/modules/avsync/producer_blipflash.yml [new file with mode: 0644]
src/modules/core/Makefile
src/modules/core/composite_line_yuv_sse2_simple.c [new file with mode: 0644]
src/modules/core/consumer_multi.c
src/modules/core/factory.c
src/modules/core/filter_audiochannels.c
src/modules/core/filter_audioconvert.c
src/modules/core/filter_channelcopy.c
src/modules/core/filter_crop.c
src/modules/core/filter_data_show.c
src/modules/core/filter_fieldorder.c
src/modules/core/filter_imageconvert.c
src/modules/core/filter_mono.c
src/modules/core/filter_obscure.c
src/modules/core/filter_panner.c
src/modules/core/filter_region.c
src/modules/core/filter_rescale.c
src/modules/core/filter_resize.c
src/modules/core/filter_watermark.c
src/modules/core/loader.dict
src/modules/core/loader.ini
src/modules/core/producer_colour.c
src/modules/core/producer_consumer.c
src/modules/core/producer_loader.c
src/modules/core/producer_melt.c
src/modules/core/producer_noise.c
src/modules/core/producer_ppm.c
src/modules/core/transition_composite.c
src/modules/core/transition_composite.h
src/modules/core/transition_composite.yml
src/modules/core/transition_luma.c
src/modules/core/transition_mix.c
src/modules/core/transition_region.c
src/modules/decklink/Makefile
src/modules/decklink/common.cpp [new file with mode: 0644]
src/modules/decklink/common.h [new file with mode: 0644]
src/modules/decklink/consumer_decklink.cpp
src/modules/decklink/consumer_decklink.yml
src/modules/decklink/darwin/DeckLinkAPI.h [new file with mode: 0755]
src/modules/decklink/darwin/DeckLinkAPIDispatch.cpp [new file with mode: 0755]
src/modules/decklink/linux/DeckLinkAPI.h [moved from src/modules/decklink/DeckLinkAPI.h with 100% similarity]
src/modules/decklink/linux/DeckLinkAPIDispatch.cpp [moved from src/modules/decklink/DeckLinkAPIDispatch.cpp with 100% similarity]
src/modules/decklink/linux/LinuxCOM.h [moved from src/modules/decklink/LinuxCOM.h with 100% similarity]
src/modules/decklink/producer_decklink.cpp
src/modules/decklink/producer_decklink.yml
src/modules/decklink/win/DeckLinkAPI_h.h [moved from src/modules/decklink/DeckLinkAPI_h.h with 100% similarity]
src/modules/decklink/win/DeckLinkAPI_i.cpp [moved from src/modules/decklink/DeckLinkAPI_i.cpp with 100% similarity]
src/modules/dgraft/Makefile
src/modules/dv/Makefile
src/modules/dv/producer_libdv.c
src/modules/effectv/Makefile
src/modules/feeds/Makefile
src/modules/frei0r/Makefile
src/modules/frei0r/configure
src/modules/frei0r/factory.c
src/modules/frei0r/frei0r_helper.c
src/modules/frei0r/producer_frei0r.c
src/modules/gtk2/Makefile
src/modules/gtk2/configure
src/modules/gtk2/filter_dynamictext.c
src/modules/gtk2/filter_rescale.c
src/modules/gtk2/producer_pango.c
src/modules/gtk2/producer_pango.yml
src/modules/gtk2/producer_pixbuf.c
src/modules/gtk2/producer_pixbuf.yml
src/modules/gtk2/scale_line_22_yuv_mmx.S
src/modules/jackrack/Makefile
src/modules/jackrack/configure
src/modules/jackrack/consumer_jack.c
src/modules/jackrack/consumer_jack.yml
src/modules/jackrack/factory.c
src/modules/jackrack/filter_jackrack.c
src/modules/jackrack/jack_rack.c
src/modules/jackrack/plugin_desc.c
src/modules/jackrack/plugin_desc.h
src/modules/jackrack/plugin_mgr.c
src/modules/jackrack/process.c
src/modules/jackrack/producer_ladspa.c [new file with mode: 0644]
src/modules/jackrack/producer_ladspa.yml [new file with mode: 0644]
src/modules/kdenlive/Makefile
src/modules/kdenlive/filter_freeze.c
src/modules/kdenlive/producer_framebuffer.c
src/modules/kino/Makefile
src/modules/kino/avi.cc
src/modules/kino/filehandler.cc
src/modules/kino/producer_kino.c
src/modules/kino/riff.cc
src/modules/linsys/Makefile
src/modules/linsys/consumer_SDIstream.c
src/modules/linsys/sdi_generator.c
src/modules/lumas/Makefile
src/modules/lumas/luma.c
src/modules/motion_est/Makefile
src/modules/motion_est/filter_autotrack_rectangle.c
src/modules/motion_est/filter_motion_est.c
src/modules/motion_est/producer_slowmotion.c
src/modules/normalize/Makefile
src/modules/normalize/factory.c
src/modules/normalize/filter_audiolevel.c [new file with mode: 0644]
src/modules/normalize/filter_audiolevel.yml [new file with mode: 0644]
src/modules/normalize/filter_volume.c
src/modules/oldfilm/Makefile
src/modules/oldfilm/filter_dust.c
src/modules/oldfilm/filter_lines.c
src/modules/oldfilm/filter_lines.yml
src/modules/opengl/Makefile [new file with mode: 0644]
src/modules/opengl/configure [new file with mode: 0755]
src/modules/opengl/consumer_xgl.c [new file with mode: 0644]
src/modules/opengl/factory.c [new file with mode: 0644]
src/modules/opengl/fbo_input.cpp [new file with mode: 0644]
src/modules/opengl/fbo_input.h [new file with mode: 0644]
src/modules/opengl/filter_deconvolution_sharpen.cpp [new file with mode: 0644]
src/modules/opengl/filter_deconvolution_sharpen.yml [new file with mode: 0644]
src/modules/opengl/filter_glsl_manager.cpp [new file with mode: 0644]
src/modules/opengl/filter_lift_gamma_gain.cpp [new file with mode: 0644]
src/modules/opengl/filter_lift_gamma_gain.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_blur.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_blur.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_convert.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_crop.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_diffusion.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_diffusion.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_glow.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_glow.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_mirror.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_mirror.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_opacity.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_opacity.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_rect.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_rect.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_resample.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_resize.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_saturation.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_saturation.yml [new file with mode: 0644]
src/modules/opengl/filter_movit_vignette.cpp [new file with mode: 0644]
src/modules/opengl/filter_movit_vignette.yml [new file with mode: 0644]
src/modules/opengl/filter_white_balance.cpp [new file with mode: 0644]
src/modules/opengl/filter_white_balance.yml [new file with mode: 0644]
src/modules/opengl/glsl_manager.h [new file with mode: 0644]
src/modules/opengl/mlt_flip_effect.h [new file with mode: 0644]
src/modules/opengl/mlt_movit_input.cpp [new file with mode: 0644]
src/modules/opengl/mlt_movit_input.h [new file with mode: 0644]
src/modules/opengl/transition_movit_mix.cpp [new file with mode: 0644]
src/modules/opengl/transition_movit_mix.yml [new file with mode: 0644]
src/modules/opengl/transition_movit_overlay.cpp [new file with mode: 0644]
src/modules/opengl/transition_movit_overlay.yml [new file with mode: 0644]
src/modules/plus/Makefile
src/modules/plus/filter_affine.c
src/modules/plus/interp.h
src/modules/plus/transition_affine.c
src/modules/qimage/Makefile
src/modules/qimage/configure
src/modules/qimage/consumer_qglsl.cpp [new file with mode: 0644]
src/modules/qimage/factory.c
src/modules/qimage/kdenlivetitle_wrapper.cpp
src/modules/qimage/producer_kdenlivetitle.c
src/modules/qimage/producer_qimage.c
src/modules/qimage/producer_qimage.yml
src/modules/qimage/qimage_wrapper.cpp
src/modules/qimage/qimage_wrapper.h
src/modules/qimage/transition_vqm.cpp [new file with mode: 0644]
src/modules/qimage/transition_vqm.yml [new file with mode: 0644]
src/modules/resample/Makefile
src/modules/resample/filter_resample.c
src/modules/rotoscoping/Makefile
src/modules/rotoscoping/filter_rotoscoping.c
src/modules/rtaudio/Makefile
src/modules/rtaudio/RtAudio.cpp
src/modules/rtaudio/RtAudio.h
src/modules/rtaudio/consumer_rtaudio.cpp
src/modules/rtaudio/consumer_rtaudio.yml
src/modules/sdl/Makefile
src/modules/sdl/consumer_sdl.c
src/modules/sdl/consumer_sdl_audio.c
src/modules/sdl/consumer_sdl_audio.yml
src/modules/sdl/consumer_sdl_preview.c
src/modules/sdl/consumer_sdl_still.c
src/modules/sdl/producer_sdl_image.c
src/modules/sdl/producer_sdl_image.yml
src/modules/sox/Makefile
src/modules/sox/filter_sox.c
src/modules/swfdec/Makefile
src/modules/swfdec/configure
src/modules/swfdec/producer_swfdec.c
src/modules/videostab/Makefile
src/modules/videostab/filter_videostab.c
src/modules/videostab/filter_videostab2.c
src/modules/videostab/filter_videostab2.yml
src/modules/videostab/stab/estimate.c
src/modules/videostab/stab/klt/error.c
src/modules/videostab/stab/klt/klt.c
src/modules/videostab/stabilize.c
src/modules/videostab/stabilize.h
src/modules/videostab/transform_image.c
src/modules/vmfx/Makefile
src/modules/vmfx/filter_shape.c
src/modules/vmfx/producer_pgm.c
src/modules/vorbis/Makefile
src/modules/vorbis/producer_vorbis.c
src/modules/xine/Makefile
src/modules/xine/filter_deinterlace.c
src/modules/xine/vf_yadif_template.h
src/modules/xine/yadif.c
src/modules/xml/Makefile
src/modules/xml/consumer_xml.c
src/modules/xml/consumer_xml.yml
src/modules/xml/producer_xml.c
src/swig/Makefile
src/swig/csharp/build
src/swig/java/build
src/swig/lua/build
src/swig/mlt.i
src/swig/perl/Makefile.PL
src/swig/perl/build
src/swig/php/build
src/swig/python/build
src/swig/python/switcher.py [new file with mode: 0755]
src/swig/python/webvfx_generator.py [new file with mode: 0755]
src/swig/ruby/build
src/swig/ruby/metadata.rb
src/swig/ruby/playlist.rb [new file with mode: 0755]
src/swig/tcl/build

index 5e8692015c134bf0f8159f6ede671feeafc1ea78..0bd0fc9e455f816ad569ee59c00c6c936b0d8706 100644 (file)
@@ -6,3 +6,10 @@ config.h
 .depend
 *~
 *.cxx
+docs/html/*
+releases/*
+patches/*
+src/modules/lumas/NTSC/*.pgm
+src/modules/lumas/PAL/*.pgm
+src/swig/csharp/src_swig/*
+src/swig/perl/blib/*
diff --git a/AUTHORS b/AUTHORS
index d91b719fc5fe6bb7edf984ad7addfc31c6001b8e..a7a5b1541ef795689542a590edfd989b6dc6adb6 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -5,10 +5,10 @@ MLT framework is maintained by:
 Dan Dennedy <dan@dennedy.org>
 
 MLT module authors and maintainers:
-
 Charles Yates <charles.yates@pandora.be>
 Dan Dennedy <dan@dennedy.org>
 Stephane Fillod (effectv)
 Marco Gittler <g.marco@freenet.de> (frei0r, oldfilm, qimage/kdenlivetitle)
 Jean-Baptiste Mardelle <jb@ader.ch> (kdenlive, qimage)
 Zachary Drew (motion_est)
+Maksym Veremeyenko <verem@m1stereo.tv>
index c7b76b52b035804d32bbabde9aa3652eb0bc0898..501c8a8a21b6d8b9fb6c6f3ce695c9da2e492335 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2013-01-20  Dan Dennedy <dan@dennedy.org>
+
+  * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h,
+  src/melt/melt.c: Set version to 0.8.8.
+
+2012-12-31  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c: Fix build against FFmepg 0.5 and
+  0.6.
+
+2012-12-26  Niv Sardi <xaiki@evilgiggle.com>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/gtk2/producer_pixbuf.yml:
+  pixbuf producer: loop option to loop sequence selectively 
+
+2012-12-22  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
+  src/framework/mlt_types.h, src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c,
+  src/modules/core/filter_audiochannels.c,
+  src/modules/core/filter_audioconvert.c,
+  src/modules/core/filter_channelcopy.c, src/modules/core/filter_mono.c: Add
+  mlt_audio_u8 (sourceforce-182).  It should support planar libavutil
+  AV_SAMPLE_FMT_U8P, but it is untested due to lacking a sample.
+
+2012-12-12  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/resample/filter_resample.c: Fix possible divide by zero
+  exceptions.
+
+2012-11-27  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/factory.c, src/modules/avformat/filter_avresample.c,
+  src/modules/avformat/producer_avformat.c: Fix decoding audio with planar
+  formats.
+
+  * src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/producer_decklink.cpp: Fix mlt_profile to DeckLink
+  DisplayMode matching.
+
+2012-11-17  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c:
+  Fix crash on invalid image sequence.
+
+  * configure, src/framework/mlt_version.h: set to interim version 0.8.7
+
+  * src/modules/qimage/kdenlivetitle_wrapper.cpp,
+  src/modules/videostab/stab/klt/error.c: Remove exit()s that cause unexpected
+  app failures.  An app can register a mlt_log callback, trap errors, and do
+  something more graceful than abort as perhaps some of these are not really as
+  fatal as they claim to be (a different patch can change the levels as
+  needed).
+
+2012-11-14  Dan Dennedy <dan@dennedy.org>
+
+  * Doxyfile, NEWS, configure, docs/melt.1, src/framework/mlt_version.h: Set
+  version to 0.8.6
+
+2012-11-13  Dan Dennedy <dan@dennedy.org>
+
+  * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h,
+  src/modules/avformat/configure: Set version to 0.8.4
+
+2012-11-11  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/factory.c, src/modules/normalize/Makefile,
+  src/modules/normalize/factory.c, src/modules/normalize/filter_audiolevel.c,
+  src/modules/normalize/filter_audiolevel.yml: Add audiolevel filter.
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/avformat/producer_avformat.yml, src/modules/core/filter_resize.c:
+  More fixes for force_full_luma (kdenlive-2799).  This change lets the image
+  converter downstream of the avformat producer perform utilize the range
+  as-needed. Then, when the rescale filter sees that the force_full_range is
+  set on the frame but has not yet been applied, forces a conversion to RGB to
+  enforce it. In addition, the recently added force_full_luma property on the
+  avformat producer is removed because it is redundant with AVOption
+  color_range=2.
+
+  * presets/consumer/avformat/Sony-PSP,
+  presets/consumer/avformat/atsc_1080i_50/DNxHD,
+  presets/consumer/avformat/atsc_1080i_5994/DNxHD,
+  presets/consumer/avformat/atsc_1080p_2398/DNxHD,
+  presets/consumer/avformat/atsc_1080p_24/DNxHD,
+  presets/consumer/avformat/atsc_1080p_25/DNxHD,
+  presets/consumer/avformat/atsc_1080p_2997/DNxHD,
+  presets/consumer/avformat/atsc_1080p_30/DNxHD,
+  presets/consumer/avformat/atsc_1080p_50/DNxHD,
+  presets/consumer/avformat/atsc_1080p_5994/DNxHD,
+  presets/consumer/avformat/atsc_1080p_60/DNxHD,
+  presets/consumer/avformat/atsc_720p_2398/DNxHD,
+  presets/consumer/avformat/atsc_720p_50/DNxHD,
+  presets/consumer/avformat/atsc_720p_5994/DNxHD,
+  presets/consumer/avformat/atsc_720p_60/DNxHD,
+  presets/consumer/avformat/dv_ntsc/D10, presets/consumer/avformat/dv_ntsc/DV,
+  presets/consumer/avformat/dv_ntsc/DVCPRO50,
+  presets/consumer/avformat/dv_ntsc_wide/D10,
+  presets/consumer/avformat/dv_ntsc_wide/DV,
+  presets/consumer/avformat/dv_ntsc_wide/DVCPRO50,
+  presets/consumer/avformat/dv_pal/D10, presets/consumer/avformat/dv_pal/DV,
+  presets/consumer/avformat/dv_pal/DVCPRO50,
+  presets/consumer/avformat/dv_pal_wide/D10,
+  presets/consumer/avformat/dv_pal_wide/DV,
+  presets/consumer/avformat/dv_pal_wide/DVCPRO50,
+  presets/consumer/avformat/hdv_1080_25p/HDV,
+  presets/consumer/avformat/hdv_1080_30p/HDV,
+  presets/consumer/avformat/hdv_1080_50i/HDV,
+  presets/consumer/avformat/hdv_1080_60i/HDV,
+  presets/consumer/avformat/hdv_720_25p/HDV,
+  presets/consumer/avformat/hdv_720_30p/HDV,
+  presets/consumer/avformat/hdv_720_50p/HDV,
+  presets/consumer/avformat/hdv_720_60p/HDV,
+  presets/consumer/avformat/lossless/FFV1,
+  presets/consumer/avformat/lossless/H.264,
+  presets/consumer/avformat/lossless/MPEG-4: Add more descriptions to encoding
+  presets.
+
+2012-11-05  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/qimage/producer_qimage.c,
+  src/modules/qimage/producer_qimage.yml: qimage: let begin property be passed
+  as a query string parameter
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/gtk2/producer_pixbuf.yml:
+  pixbuf: support alt. query syntax begin:value for melt
+
+2012-11-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/gtk2/producer_pixbuf.yml:
+  pixbuf: let begin property be passed as a query string parameter
+
+2012-10-23  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/avformat/producer_avformat.yml: Fix force_full_luma
+  (kdenlive-2799).
+
+2012-10-19  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_geometry.c, src/modules/videostab/filter_videostab.c,
+  src/modules/videostab/filter_videostab2.c: Let vector property of
+  videostab(2) be read directly as mlt_geometry.
+
+2012-10-19  Jean-Baptiste Mardelle <jb@kdenlive.org>
+
+  * src/modules/qimage/Makefile, src/modules/qimage/configure,
+  src/modules/qimage/producer_qimage.c, src/modules/qimage/qimage_wrapper.cpp,
+  src/modules/qimage/qimage_wrapper.h: Fix loading of extra image formats using
+  Kdelibs (xcf, ...)
+
+2012-10-09  Dan Dennedy <dan@dennedy.org>
+
+  * src/swig/Makefile, src/swig/csharp/build, src/swig/java/build,
+  src/swig/lua/build, src/swig/perl/Makefile.PL, src/swig/perl/build,
+  src/swig/php/build, src/swig/python/build, src/swig/ruby/build,
+  src/swig/tcl/build: Build the SWIG bindings with the CXXFLAGS (3554425) 
+  Based on patch by Cristian Morales Vega
+
+  * src/modules/core/producer_colour.c, src/modules/core/producer_noise.c,
+  src/modules/frei0r/producer_frei0r.c: fix aspect ratio of generators when set
+  via consumer property
+
+2012-09-23  Dan Dennedy <dan@dennedy.org>
+
+  * presets/consumer/avformat/MJPEG, presets/consumer/avformat/lossless/FFV1,
+  presets/consumer/avformat/lossless/MJPEG: indicate in some presets codecs
+  which do not support multithread
+
+2012-09-16  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/Makefile, src/framework/configure,
+  src/framework/mlt_property.h: cleanup sys/param.h include on FreeBSD 
+  Assisted by Albert Villa who says it is safe to assume sys/param.h is
+  available, which is needed for FreeBSD version check on whether to include
+  xlocale.h in mlt_property.h.
+
+2012-09-13  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/sdl/consumer_sdl_audio.c,
+  src/modules/sdl/consumer_sdl_preview.c: sdl_audio and sdl_preview also do not
+  care about field order  Also, have sdl_preview pass top_field_first to its
+  children.
+
+  * src/framework/mlt_consumer.h, src/modules/core/filter_fieldorder.c,
+  src/modules/sdl/consumer_sdl.c: add ability to ignore field order as used by
+  sdl consumer
+
+2012-09-09  Dan Dennedy <dan@dennedy.org>
+
+  * src/mlt++/MltProfile.cpp, src/mlt++/MltProfile.h: add
+  Mlt::Profile::colorspace()
+
+2012-09-08  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/framework/configure, src/modules/avformat/configure,
+  src/modules/frei0r/configure: allow env CC to override hard-coded gcc in
+  configure scripts  patch by Alberto Villa
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c,
+  src/modules/qimage/producer_qimage.c, src/modules/qimage/qimage_wrapper.cpp,
+  src/modules/swfdec/producer_swfdec.c, src/modules/vorbis/producer_vorbis.c:
+  change producers to use mlt_frame_original_position()
+
+  * src/framework/mlt_frame.c, src/framework/mlt_frame.h: add
+  mlt_frame_original_position()
+
+2012-09-03  Dan Dennedy <dan@dennedy.org>
+
+  * src/mlt++/MltService.cpp, src/mlt++/MltService.h: add
+  Mlt::Service::set_profile()
+
+  * src/framework/mlt_service.c, src/framework/mlt_service.h: add
+  mlt_service_set_profile()
+
+  * src/mlt++/MltProfile.cpp, src/mlt++/MltProfile.h: add
+  Mlt::Profile::is_explicit()
+
+2012-08-31  Dan Dennedy <dan@dennedy.org>
+
+  * src/swig/mlt.i, src/swig/ruby/playlist.rb: extend Ruby API with
+  PlaylistNextListner and show how to use it
+
+  * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h: add
+  playlist-next event to mlt_playlist
+
+2012-08-30  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/framework/mlt_version.h: set interim version to 0.8.3
+
+2012-08-28  Dan Dennedy <dan@dennedy.org>
+
+  * ChangeLog, presets/consumer/avformat/MPEG-4 ASP,
+  presets/consumer/avformat/MPEG-4-ASP, presets/consumer/avformat/webm: add
+  acodec to webm preset and rename MPEG-4 ASP preset
+
+  * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h: set version
+  to 0.8.2
+
+2012-08-26  Dan Dennedy <dan@dennedy.org>
+
+  * presets/consumer/avformat/stills/BMP, presets/consumer/avformat/stills/DPX,
+  presets/consumer/avformat/stills/JPEG, presets/consumer/avformat/stills/PNG,
+  presets/consumer/avformat/stills/PPM, presets/consumer/avformat/stills/TGA,
+  presets/consumer/avformat/stills/TIFF: add meta.preset.extension to image
+  sequence presets
+
+  * presets/consumer/avformat/AAC, presets/consumer/avformat/Flash,
+  presets/consumer/avformat/MJPEG, presets/consumer/avformat/MP3,
+  presets/consumer/avformat/MPEG-2, presets/consumer/avformat/MPEG-4,
+  presets/consumer/avformat/MPEG-4 ASP, presets/consumer/avformat/Sony-PSP,
+  presets/consumer/avformat/Vorbis, presets/consumer/avformat/WAV,
+  presets/consumer/avformat/XDCAM-HD422,
+  presets/consumer/avformat/atsc_1080i_50/DNxHD,
+  presets/consumer/avformat/atsc_1080i_5994/DNxHD,
+  presets/consumer/avformat/atsc_1080p_2398/DNxHD,
+  presets/consumer/avformat/atsc_1080p_24/DNxHD,
+  presets/consumer/avformat/atsc_1080p_25/DNxHD,
+  presets/consumer/avformat/atsc_1080p_2997/DNxHD,
+  presets/consumer/avformat/atsc_1080p_30/DNxHD,
+  presets/consumer/avformat/atsc_1080p_50/DNxHD,
+  presets/consumer/avformat/atsc_1080p_5994/DNxHD,
+  presets/consumer/avformat/atsc_1080p_60/DNxHD,
+  presets/consumer/avformat/atsc_720p_2398/DNxHD,
+  presets/consumer/avformat/atsc_720p_50/DNxHD,
+  presets/consumer/avformat/atsc_720p_5994/DNxHD,
+  presets/consumer/avformat/atsc_720p_60/DNxHD,
+  presets/consumer/avformat/dv_ntsc/D10, presets/consumer/avformat/dv_ntsc/DVD,
+  presets/consumer/avformat/dv_ntsc_wide/D10,
+  presets/consumer/avformat/dv_ntsc_wide/DVD,
+  presets/consumer/avformat/dv_pal/D10, presets/consumer/avformat/dv_pal/DVD,
+  presets/consumer/avformat/dv_pal_wide/D10,
+  presets/consumer/avformat/dv_pal_wide/DVD,
+  presets/consumer/avformat/hdv_1080_25p/HDV,
+  presets/consumer/avformat/hdv_1080_30p/HDV,
+  presets/consumer/avformat/hdv_1080_50i/HDV,
+  presets/consumer/avformat/hdv_1080_60i/HDV,
+  presets/consumer/avformat/hdv_720_25p/HDV,
+  presets/consumer/avformat/hdv_720_30p/HDV,
+  presets/consumer/avformat/hdv_720_50p/HDV,
+  presets/consumer/avformat/hdv_720_60p/HDV,
+  presets/consumer/avformat/lossless/FFV1,
+  presets/consumer/avformat/lossless/H.264,
+  presets/consumer/avformat/lossless/HuffYUV,
+  presets/consumer/avformat/lossless/MJPEG,
+  presets/consumer/avformat/lossless/MPEG-2,
+  presets/consumer/avformat/lossless/MPEG-4,
+  presets/consumer/avformat/lossless/ProRes, presets/consumer/avformat/webm,
+  presets/consumer/avformat/x264-medium,
+  presets/consumer/avformat/x264-medium-baseline,
+  presets/consumer/avformat/x264-medium-main,
+  presets/consumer/avformat/x264-medium-pass1: add preset metadata such as
+  alternate name, filename extension, note.
+
+  * presets/consumer/avformat/Sony-PSP, presets/consumer/avformat/webm,
+  presets/consumer/avformat/x264-medium-baseline,
+  presets/consumer/avformat/x264-medium-main: change profile to vprofile in
+  presets
+
+  * presets/consumer/avformat/Vorbis,
+  presets/consumer/avformat/lossless/ProRes: add vorbis and prores encode
+  presets
+
+2012-08-25  Dan Dennedy <dan@dennedy.org>
+
+  * presets/consumer/avformat/AAC, presets/consumer/avformat/Flash,
+  presets/consumer/avformat/MJPEG, presets/consumer/avformat/MP3,
+  presets/consumer/avformat/MPEG-2, presets/consumer/avformat/MPEG-4,
+  presets/consumer/avformat/MPEG-4 ASP, presets/consumer/avformat/WAV,
+  presets/consumer/avformat/hdv_1080_25p/HDV,
+  presets/consumer/avformat/hdv_1080_30p/HDV,
+  presets/consumer/avformat/hdv_1080_50i/HDV,
+  presets/consumer/avformat/hdv_1080_60i/HDV,
+  presets/consumer/avformat/hdv_720_25p/HDV,
+  presets/consumer/avformat/hdv_720_30p/HDV,
+  presets/consumer/avformat/hdv_720_50p/HDV,
+  presets/consumer/avformat/hdv_720_60p/HDV,
+  presets/consumer/avformat/lossless/FFV1,
+  presets/consumer/avformat/lossless/H.264,
+  presets/consumer/avformat/lossless/HuffYUV,
+  presets/consumer/avformat/lossless/MJPEG,
+  presets/consumer/avformat/lossless/MPEG-2,
+  presets/consumer/avformat/lossless/MPEG-4,
+  presets/consumer/avformat/stills/BMP, presets/consumer/avformat/stills/DPX,
+  presets/consumer/avformat/stills/JPEG, presets/consumer/avformat/stills/PNG,
+  presets/consumer/avformat/stills/PPM, presets/consumer/avformat/stills/TGA,
+  presets/consumer/avformat/stills/TIFF,
+  presets/consumer/avformat/x264-medium-pass1: add a bunch of new encoding
+  presets
+
+2012-08-24  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/avformat/producer_avformat.yml: the recent A/V sync overhaul
+  needed some additional work
+
+2012-08-11  Dan Dennedy <dan@dennedy.org>
+
+  * src/melt/io.c, src/melt/melt.c: fix melt progress display on Windows
+
+2012-08-01  Mikko Rapeli <mikko.rapeli@iki.fi>
+
+  * src/modules/videostab/filter_videostab.c,
+  src/modules/videostab/filter_videostab2.c: videostab/filter_videostab*.c:
+  check return value from mlt_filter_new()  Fixes Coverity CID 709365 and
+  709366: Dereference null return value (NULL_RETURNS) Function
+  "mlt_filter_new" returns null (checked 50 out of 52 times). [show details]
+  Assigning: "parent" = null return value from "mlt_filter_new". 201           
+      mlt_filter parent = mlt_filter_new(); Dereferencing a null pointer
+  "parent". 202                parent->child = self;
+
+  * src/modules/videostab/filter_videostab.c,
+  src/modules/videostab/filter_videostab2.c: videostab/filter_videostab*.c:
+  check for null  Fixes Coverity CID 709404: Dereference before null check
+  (REVERSE_INULL) Dereferencing pointer "g". [show details] 85        if (
+  !mlt_geometry_parse( g, vectors, length, -1, -1 ) ) ... Dereferencing "g"
+  before a null check. 104        if ( g ) mlt_geometry_close( g );
+
+2012-08-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/avformat/producer_avformat.yml: add image cache size property to
+  avformat producer
+
+2012-08-03  Marco Gittler <g.marco@freenet.de>
+
+  * src/modules/oldfilm/filter_lines.c, src/modules/oldfilm/filter_lines.yml:
+  fix width output of filter in xml
+
+2012-07-25  Mikko Rapeli <mikko.rapeli@iki.fi>
+
+  * src/framework/mlt_field.c, src/framework/mlt_frame.c,
+  src/framework/mlt_multitrack.c, src/framework/mlt_playlist.c,
+  src/framework/mlt_properties.c, src/framework/mlt_repository.c,
+  src/framework/mlt_service.c, src/framework/mlt_tractor.c,
+  src/modules/core/filter_audioconvert.c, src/modules/core/filter_crop.c,
+  src/modules/core/filter_imageconvert.c, src/modules/core/filter_panner.c,
+  src/modules/core/filter_resize.c, src/modules/core/producer_ppm.c,
+  src/modules/core/transition_composite.c, src/modules/core/transition_mix.c,
+  src/modules/dv/producer_libdv.c, src/modules/gtk2/producer_pango.c,
+  src/modules/gtk2/producer_pixbuf.c, src/modules/kino/producer_kino.c,
+  src/modules/linsys/consumer_SDIstream.c,
+  src/modules/normalize/filter_volume.c,
+  src/modules/qimage/producer_kdenlivetitle.c,
+  src/modules/qimage/producer_qimage.c, src/modules/rtaudio/RtAudio.cpp,
+  src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_audio.c,
+  src/modules/sdl/consumer_sdl_preview.c, src/modules/sdl/consumer_sdl_still.c,
+  src/modules/xml/consumer_xml.c, src/modules/xml/producer_xml.c: Fix calloc()
+  parameter ordering  First parameter to calloc() is the count and second the
+  amount of bytes for each item. Likely this has no run time effect since the
+  resulting buffer size is the same.
+
+2012-07-23  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
+  fix crash when switching image formats with alpha  This happens when
+  switching from image format with distinct alpha channel (yuv422) to one with
+  embedded alpha channel (rgb24a).  Reported-by: j-b-m
+
+2012-07-22  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/videostab/stabilize.c, src/modules/videostab/stabilize.h:
+  remove unused function (coverity-709390)
+
+  * src/mlt++/MltService.cpp, src/mlt++/MltService.h: add
+  Service::get_profile() returns mlt_profile
+
+  * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h: fix memory leak
+  (coverity-709375)
+
+2012-07-20  Dan Dennedy <dan@dennedy.org>
+
+  * AUTHORS, src/modules/core/Makefile,
+  src/modules/core/composite_line_yuv_sse2_simple.c,
+  src/modules/core/transition_composite.c: improve compatibility to compile
+  composite sse2 (macports-35243)
+
+2012-07-12  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/producer_loader.c, src/modules/xml/producer_xml.c: accept
+  file:// prefix on MLT XML file
+
+2012-06-23  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h,
+  src/mlt++/MltPlaylist.cpp, src/mlt++/MltPlaylist.h,
+  src/modules/core/producer_melt.c, src/modules/xml/producer_xml.c: add support
+  for time string to playlist blanks
+
+  * src/modules/jackrack/consumer_jack.c,
+  src/modules/jackrack/consumer_jack.yml,
+  src/modules/rtaudio/consumer_rtaudio.cpp,
+  src/modules/rtaudio/consumer_rtaudio.yml,
+  src/modules/sdl/consumer_sdl_audio.c, src/modules/sdl/consumer_sdl_audio.yml:
+  add support for audio scrubbing to audio-only consumers
+
+2012-06-19  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_producer.c, src/framework/mlt_producer.h,
+  src/mlt++/MltProducer.cpp, src/mlt++/MltProducer.h: add
+  mlt_producer_seek_time and mlt_producer_frame_time
+
+  * src/mlt++/MltFilteredConsumer.cpp, src/mlt++/MltFilteredConsumer.h,
+  src/mlt++/MltFilteredProducer.cpp, src/mlt++/MltFilteredProducer.h,
+  src/mlt++/MltPushConsumer.cpp, src/mlt++/MltPushConsumer.h: add const-ness to
+  some strings in specialized service classes
+
+2012-06-18  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/rotoscoping/filter_rotoscoping.c,
+  src/modules/vmfx/filter_shape.c, src/modules/xine/vf_yadif_template.h,
+  src/modules/xine/yadif.c: fix clang errors
+
+2012-06-16  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c,
+  src/modules/avformat/producer_avformat.yml: overhaul a/v sync and seeking in
+  avformat producer  The new_seek property changed to use_pts. This
+  consolidates old seek and new seek code, improves a/v sync for more files,
+  and improves seek performance for AVCHD in general (including libav).
+
+2012-06-04  Dan Dennedy <dan@dennedy.org>
+
+  * NEWS, configure, src/framework/mlt_version.h: set interim version to 0.8.1
+
+2012-06-01  Dan Dennedy <dan@dennedy.org>
+
+  * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h,
+  src/modules/avformat/configure: set version to 0.8.0
+
+2012-05-29  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_cache.c, src/framework/mlt_cache.h: add
+  mlt_cache_put_frame and mlt_cache_get_frame
+
+  * src/modules/gtk2/Makefile, src/modules/gtk2/configure,
+  src/modules/gtk2/scale_line_22_yuv_mmx.S, src/modules/jackrack/Makefile,
+  src/modules/jackrack/configure: fix cross-compiling gtk2 and jackrack modules
+  for windows
+
+2012-05-26  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/mlt++/configure, src/modules/qimage/configure,
+  src/modules/swfdec/Makefile, src/modules/videostab/stab/estimate.c: add
+  configure options and fixes for cross-compiling
+
+2012-05-19  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/DeckLinkAPI.h,
+  src/modules/decklink/DeckLinkAPIDispatch.cpp,
+  src/modules/decklink/DeckLinkAPI_h.h, src/modules/decklink/DeckLinkAPI_i.cpp,
+  src/modules/decklink/LinuxCOM.h, src/modules/decklink/Makefile,
+  src/modules/decklink/common.cpp, src/modules/decklink/common.h,
+  src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/darwin/DeckLinkAPI.h,
+  .../decklink/darwin/DeckLinkAPIDispatch.cpp,
+  src/modules/decklink/linux/DeckLinkAPI.h,
+  src/modules/decklink/linux/DeckLinkAPIDispatch.cpp,
+  src/modules/decklink/linux/LinuxCOM.h,
+  src/modules/decklink/producer_decklink.cpp,
+  src/modules/decklink/win/DeckLinkAPI_h.h,
+  src/modules/decklink/win/DeckLinkAPI_i.cpp: fix decklink build for OS X
+
+2012-04-18  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/producer_decklink.cpp: fix decklink build on Windows
+
+2012-04-11  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/plus/filter_affine.c, src/modules/plus/interp.h,
+  src/modules/plus/transition_affine.c: fix distortion handling alpha channel
+  in affine transition  Reported-by: j-b-m
+
+2012-04-10  Dan Dennedy <dan@dennedy.org>
+
+  * demo/mlt_ticker, src/modules/plus/filter_affine.c: fix background alpha
+  channel of affine filter  broke when black producer was changed to opaque
+  like other colors
+
+2012-04-07  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/plus/transition_affine.c,
+  src/modules/qimage/qimage_wrapper.cpp: fix regressions during refactorization
+
+2012-03-31  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/xml/consumer_xml.c, src/modules/xml/consumer_xml.yml: add
+  time_format property to xml consumer  Now you can save the in, out, and
+  length properties as timecode or clock values. Default unit it still in frame
+  count.
+
+  * src/framework/mlt_producer.c, src/framework/mlt_producer.h,
+  src/mlt++/MltProducer.cpp, src/mlt++/MltProducer.h: add
+  mlt_producer_get_length_time()  More functions that return time strings will
+  be added later.
+
+  * configure, src/framework/mlt_properties.c, src/framework/mlt_properties.h,
+  src/framework/mlt_property.c, src/framework/mlt_property.h,
+  src/framework/mlt_types.h, src/mlt++/MltProperties.cpp,
+  src/mlt++/MltProperties.h: add support for timecode and clock time strings to
+  the framework
+
+2012-03-27  Dan Dennedy <dan@dennedy.org>
+
+  * GPLv3, configure, src/modules/qimage/Makefile,
+  src/modules/qimage/configure, src/modules/qimage/factory.c: require configure
+  --enable-gpl3 for GPLv3 services (currently only vqm)
+
+2012-03-25  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c:
+  fix resource leak regression in image producers
+
+2012-03-19  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/producer_decklink.cpp: enumerate DeckLink devices when
+  list_devices property is set
+
+2012-03-19  Maksym Veremeyenko <verem@m1stereo.tv>
+
+  * src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/producer_decklink.cpp: Initialize all decklink interface
+  pointers and reset them upon release.  Also, add a couple of missing
+  releases.
+
+2012-03-18  Brian Matherly <pez4brian@yahoo.com>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c: Fix incorrect precompiler
+  conditionals for libav/ffmpeg versions.  Needed to support ffmpeg 0.9 and
+  0.10 releases.
+
+2012-03-14  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/consumer_decklink.cpp,
+  src/modules/decklink/consumer_decklink.yml,
+  src/modules/decklink/producer_decklink.cpp,
+  src/modules/decklink/producer_decklink.yml: enumerate available devices in
+  decklink module
+
+2012-03-11  Brian Matherly <pez4brian@yahoo.com>
+
+  * src/modules/gtk2/producer_pixbuf.yml,
+  src/modules/qimage/producer_qimage.yml: Fix broken pixbuf and qimage producer
+  metadata.
+
+2012-03-07  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c,
+  src/modules/qimage/producer_qimage.c: indicate image producers seekable
+
+2012-03-06  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.yml,
+  src/modules/qimage/producer_qimage.yml: update service metadata for pixbuf
+  and qimage
+
+2012-03-05  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c:
+  allow %u in image sequence pattern containing begin value
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c:
+  add image sequences where scanf format contains begin value  For example, if
+  an image sequence begins with the file foo1234.png, you can use the resource
+  string "foo%1234d.png" to load it.
+
+2012-03-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/producer_decklink.cpp,
+  src/modules/qimage/qimage_wrapper.cpp: remove a couple more remnants of
+  legacy real_width and _height
+
+  * src/modules/avformat/producer_avformat.c, src/modules/dv/producer_libdv.c:
+  remove deprecated source_fps property
+
+  * src/framework/mlt_tractor.c, src/modules/avformat/producer_avformat.c,
+  src/modules/core/consumer_multi.c, src/modules/core/filter_crop.c,
+  src/modules/core/filter_rescale.c, src/modules/core/filter_resize.c,
+  src/modules/core/producer_colour.c, src/modules/core/producer_consumer.c,
+  src/modules/core/producer_loader.c, src/modules/core/transition_composite.c,
+  src/modules/dv/producer_libdv.c, src/modules/gtk2/producer_pango.c,
+  src/modules/gtk2/producer_pixbuf.c,
+  src/modules/kdenlive/producer_framebuffer.c,
+  src/modules/plus/transition_affine.c, src/modules/sdl/producer_sdl_image.c,
+  src/modules/swfdec/producer_swfdec.c,
+  src/modules/videostab/filter_videostab2.c, src/modules/vmfx/producer_pgm.c:
+  replace legacy real_width and _height with meta.media.width and .height  This
+  takes advantage of mlt_producer copying all meta properties from producer to
+  frame so we do not have to remember to do it everywhere it is needed.
+
+2012-02-29  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
+  src/framework/mlt_profile.c, src/framework/mlt_tractor.c,
+  src/framework/mlt_transition.c, src/modules/core/filter_crop.c,
+  src/modules/core/filter_watermark.c, src/modules/kdenlive/filter_freeze.c,
+  src/modules/kdenlive/producer_framebuffer.c,
+  src/modules/oldfilm/filter_dust.c, src/modules/plus/filter_affine.c,
+  src/modules/plus/transition_affine.c: remove consumer_aspect_ratio property -
+  use profile instead
+
+  * src/framework/mlt_tractor.c, src/modules/core/filter_watermark.c,
+  src/modules/core/transition_composite.c,
+  src/modules/kdenlive/filter_freeze.c: remove output_ratio property - use
+  profile instead
+
+  * src/modules/core/filter_crop.c, src/modules/core/filter_obscure.c,
+  src/modules/core/filter_rescale.c, src/modules/core/filter_resize.c,
+  src/modules/core/filter_watermark.c, src/modules/core/transition_composite.c,
+  src/modules/plus/filter_affine.c, src/modules/plus/transition_affine.c:
+  remove usage of normalised_width and _height properties from services
+
+  * src/framework/mlt_frame.c, src/framework/mlt_tractor.c: remove
+  normalised_width and _height properties from framework
+
+2012-03-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
+  fix regression with adding image conversion to image producers
+
+2012-03-02  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/qimage/producer_qimage.c,
+  src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h:
+  convert to and cache requested format in qimage
+
+2012-03-01  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/qimage/producer_qimage.c,
+  src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h:
+  split refresh_qimage() into refresh_qiamge() and refresh_image()
+
+2012-02-27  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/transition_composite.yml,
+  src/modules/gtk2/producer_pixbuf.yml: couple of small service metadata fixes
+
+2012-02-22  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/decklink/producer_decklink.cpp,
+  src/modules/decklink/producer_decklink.yml: fix regression when using
+  producer 'consumer' with decklink  This feature now requires one to set the
+  preview property on this producer to support special preview mode when the
+  speed is 0.
+
+2012-02-20  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_frame.c, src/modules/avformat/filter_avcolour_space.c,
+  src/modules/core/filter_crop.c, src/modules/core/filter_resize.c,
+  src/modules/core/transition_region.c: let mlt_frame_set_alpha clear the
+  get_alpha_mask function pointer
+
+2012-02-19  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/framework/mlt_version.h: set interim version 0.7.9
+
+2012-02-16  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/transition_composite.c,
+  src/modules/core/transition_composite.h: make composite_line_yuv() available
+  to other services
+
+2012-02-16  Maksym Veremeyenko <verem@m1stereo.tv>
+
+  * src/modules/core/composite_line_yuv_sse2_simple.c,
+  src/modules/core/transition_composite.c: use sse2 instruction for line
+  compositing
+
+2012-02-13  Dan Dennedy <dan@dennedy.org>
+
+  * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h,
+  src/melt/melt.c: set version to 0.7.8
+
+2012-02-12  Dan Dennedy <dan@dennedy.org>
+
+  * Makefile, src/modules/core/loader.dict,
+  src/modules/sdl/producer_sdl_image.yml: deprecate sdl_image
+
+  * src/mlt++/MltFrame.cpp, src/mlt++/MltFrame.h: make Frame::get_position()
+  retrun type consistent
+
+2012-02-12  Simon A. Eugster <simon.eu@gmail.com>
+
+  * src/mlt++/MltFrame.cpp, src/mlt++/MltFrame.h: Add get_position to
+  Mlt::Frame
+
+2012-02-08  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/qimage/factory.c, src/modules/qimage/transition_vqm.cpp,
+  src/modules/qimage/transition_vqm.yml: add rendering to vqm and yaml service
+  metadata
+
+2012-02-06  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/qimage/Makefile, src/modules/qimage/factory.c,
+  src/modules/qimage/transition_vqm.cpp: add vqm transition
+
+2012-02-05  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/filter_avcolour_space.c,
+  src/modules/avformat/producer_avformat.c: fix color problem with libav
+  (3483629)
+
+2012-02-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c: fix AVOption processing on ffmpeg
+  0.8
+
+2012-01-30  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c: fix AVOption processing on libav
+  0.7.3  Patch for consumer by j-b-m and extended to producer by me.
+
+2012-01-28  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/filter_avresample.c,
+  src/modules/avformat/producer_avformat.c: fix SAMPLE_FMT support for v0.6 and
+  less of libav/ffmpeg
+
+  * src/modules/avformat/filter_avresample.c,
+  src/modules/avformat/producer_avformat.c: convert all SAMPLE_FMT_16 to
+  AV_SAMPLE_FMT_16
+
+2012-01-25  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/filter_audiochannels.c,
+  src/modules/core/filter_channelcopy.c, src/modules/core/filter_mono.c: add
+  s32le and f32le format to core audio filters
+
+  * src/framework/mlt_types.h, src/modules/core/filter_audioconvert.c: add
+  support for converting between all audio sample formats
+
+2012-01-21  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
+  src/modules/avformat/producer_avformat.c: remove global avformat mutex  and
+  add a local one to the producer for open/close coherency
+
+  * src/framework/mlt_producer.h, src/framework/mlt_service.h: update doc on
+  service-change and producer-changed events
+
+2012-01-17  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/gtk2/producer_pango.yml, src/modules/gtk2/producer_pixbuf.yml:
+  document force_aspect_ratio on pango and pixbuf producers
+
+2012-01-15  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c,
+  src/modules/avformat/producer_avformat.c: enable codec- and format-specific
+  options for v0.7 releases of ffmpeg  (but not libav, which uses v53 of
+  libavformat and libavcodec in its 0.7 releases)
+
+2012-01-14  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
+  src/modules/avformat/producer_avformat.c: drop deprecated APIs of
+  libavformat/codec v53
+
+2012-01-02  gmarco <g.marco@freenet.de>
+
+  * src/modules/videostab/filter_videostab.c,
+  src/modules/videostab/stab/resample.c, src/modules/videostab/stab/resample.h,
+  src/modules/videostab/stab/utils.c, src/modules/videostab/stab/utils.h: do
+  not use lanc_kernels as global var. moved to filter struct
+
+2011-12-16  gmarco <g.marco@freenet.de>
+
+  * src/modules/videostab/filter_videostab2.c,
+  src/modules/videostab/stabilize.c, src/modules/videostab/stabilize.h,
+  src/modules/videostab/transform_image.c,
+  src/modules/videostab/transform_image.h: use calloc insteadt of malloc/memset
+  use struct for instance data small cleanup use PIX(n) dont use instable
+  yuv420 use stabilize on grayimage (converted from yuv422)
+
+2011-11-21  Marco Gittler <g.marco@freenet.de>
+
+  * src/modules/videostab/stabilize.c, src/modules/videostab/transform_image.c:
+  sse2 updates
+
+2011-12-21  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/mlt++/configure: add configure support for GNU Hurd  Patches
+  provided by Patrick Matthäi.
+
+  * src/modules/rtaudio/RtAudio.cpp, src/modules/rtaudio/configure: only build
+  rtaudio for Linux, Windows, or OS X
+
+  * src/framework/Makefile, src/framework/configure,
+  src/framework/mlt_property.h: add support for xlocale.h on FreeBSD  with
+  assistance from Gleb Smirnoff
+
+2011-12-16  gmarco <g.marco@freenet.de>
+
+  * src/modules/videostab/filter_videostab2.c,
+  src/modules/videostab/stabilize.c, src/modules/videostab/stabilize.h,
+  src/modules/videostab/transform_image.c,
+  src/modules/videostab/transform_image.h: use calloc insteadt of malloc/memset
+  use struct for instance data small cleanup use PIX(n) dont use instable
+  yuv420 use stabilize on grayimage (converted from yuv422)
+
+2011-11-21  Marco Gittler <g.marco@freenet.de>
+
+  * src/modules/videostab/stabilize.c, src/modules/videostab/transform_image.c:
+  sse2 updates
+
+2011-12-10  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/producer_colour.c, src/modules/core/producer_noise.c,
+  src/modules/dv/producer_libdv.c, src/modules/frei0r/producer_frei0r.c,
+  src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c,
+  src/modules/qimage/producer_qimage.c, src/modules/sdl/producer_sdl_image.c:
+  add mlt_image_none support to producers
+
+  * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h: add consumer
+  properties mlt_image_format and mlt_audio_format
+
+2011-12-09  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/filter_fieldorder.c,
+  src/modules/core/filter_fieldorder.yml: add meta.swap_fields to the
+  fieldorder filter
+
+2011-12-08  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/Makefile, src/modules/core/factory.c,
+  src/modules/core/filter_fieldorder.c, src/modules/core/filter_fieldorder.yml,
+  src/modules/core/filter_resize.c, src/modules/core/filter_resize.yml,
+  src/modules/core/loader.ini: refactor field order correction into new filter
+
+2011-12-05  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/rtaudio/RtAudio.cpp, src/modules/rtaudio/RtAudio.h,
+  src/modules/rtaudio/consumer_rtaudio.cpp: improve selecting rtaudio device by
+  name
+
+2011-11-28  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/rtaudio/Makefile, src/modules/rtaudio/RtAudio.cpp,
+  src/modules/rtaudio/RtAudio.h, src/modules/rtaudio/RtError.h,
+  src/modules/rtaudio/consumer_rtaudio.cpp: add rtaudio consumer
+
+2011-11-27  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/avformat/producer_avformat.c, src/modules/avformat/vdpau.c: fix
+  VDPAU state issues  Patch by Christophe Thommeret
+
+2011-11-04  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_factory.c, src/modules/frei0r/factory.c,
+  src/modules/jackrack/plugin_mgr.c: fix frei0r and ladspa loading for
+  relocatable builds
+
+2011-11-19  Dan Dennedy <dan@dennedy.org>
+
+  * src/melt/melt.c, src/modules/core/consumer_multi.c: change property
+  'consumer' to 'mlt_service' consistent with xml
+
+  * src/framework/mlt_frame.c, src/framework/mlt_frame.h,
+  src/modules/core/consumer_multi.c: enhance mlt_frame_clone with a
+  deep/shallow parameter
+
+2011-11-10  Dan Dennedy <dan@dennedy.org>
+
+  * src/framework/mlt_frame.c, src/framework/mlt_frame.h: add mlt_frame_clone()
+
+2011-11-05  Dan Dennedy <dan@dennedy.org>
+
+  * src/modules/core/Makefile, src/modules/core/consumer_multi.c,
+  src/modules/core/consumer_multi.yml, src/modules/core/factory.c: add multi
+  consumer (non-functional)
+
+2011-11-12  Dan Dennedy <dan@dennedy.org>
+
+  * profiles/sdi_486i_5994, profiles/sdi_486p_2398,
+  src/modules/linsys/consumer_SDIstream.c, src/modules/linsys/sdi_generator.c,
+  src/modules/linsys/sdi_generator.h: improve support for 486 line NTSC in
+  linsys sdi consumer
+
+2011-11-03  Dan Dennedy <dan@dennedy.org>
+
+  * configure, src/framework/mlt_version.h: set interim version 0.7.7
+
+  * src/modules/avformat/vdpau.c, src/modules/videostab/stab/estimate.c: build
+  fixes for FreeBSD  patches by Alberto Villa
+
 2011-10-31  Dan Dennedy <dan@dennedy.org>
 
   * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h: set version
   to 0.7.6
 
-  * NEWS: add release notes for v0.7.6
-
 2011-10-30  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/videostab/filter_videostab.c,
   adjust in and out properties as needed because we cannot yet use negative
   values to mean "from end."
 
-  * src/modules/jackrack/plugin_mgr.c: reduce log level of some LADSPA-related
-  exceptions
-
-2011-09-21  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/videostab/filter_videostab2.yml: updated desc
-
 2011-09-20  Marco Gittler <g.marco@freenet.de>
 
-  * src/modules/videostab/filter_videostab2.yml: added description
-
   * src/modules/videostab/filter_videostab2.c,
   src/modules/videostab/transform_image.c,
   src/modules/videostab/transform_image.h: set transform properties from mlt
 
-  * src/modules/videostab/filter_videostab2.c: read filter params correct, set
-  interpol type
-
 2011-09-19  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/videostab/filter_videostab2.c,
   src/modules/videostab/transform_image.c: use interpolation settings
 
-  * src/modules/videostab/stabilize.c: log format error on draw*
-
-  * src/modules/videostab/filter_videostab2.yml: added yml for videostab2
-
 2011-09-11  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/videostab/stabilize.c, src/modules/videostab/transform_image.c:
   src/modules/videostab/transform_image.h: avoid unreadable code  like
   (*format==mlt_image_rgb24?0:1) use mlt_types and names for it
 
-  * src/modules/videostab/filter_videostab2.c: remove log since no parent/type
-  yet
-
-  * src/modules/videostab/filter_videostab2.c: removed unsued code (point 4 )
-
-  * src/modules/videostab/filter_videostab2.c: removed printf from mlt filter
-  code (point 9)
-
-  * src/modules/videostab/filter_videostab2.c: use mlt_pool_release instead of
-  mlt_properties_close (point 8)
-
-  * src/modules/videostab/filter_videostab2.c: do not call stabilize_init()
-  anymore (point 7) thx to Dan D.
-
-  * src/modules/videostab/Makefile: fix makefile to respect global FLAGS (point
-  2)
-
-2011-09-02  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/videostab/filter_videostab2.c: framesize 3/2 * w * h seems to
-  bee too small for yuv420 (segfault in filter)
-
 2011-08-19  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/videostab/Makefile, src/modules/videostab/factory.c,
 
 2011-10-30  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/gtk2/producer_pango.yml: remove invalid metadata item for pango
-
   * src/modules/core/producer_consumer.c,
   src/modules/core/producer_consumer.yml: add autoprofile property to consumer
   producer
 
-  * src/modules/decklink/producer_decklink.cpp: log profile info when profile
-  not compatible with decklink mode
-
-  * src/modules/avformat/producer_avformat.c: fix crash cleaning packet queues
-  that were not created
-
-  * src/framework/mlt_log.c: change default log level to WARN
-
-2011-10-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Let video_delay work with
-  new_seek (AVCHD).
-
-  * src/modules/avformat/producer_avformat.c: Renove start_time from avformat
-  producer core object.
-
 2011-10-16  Brian Matherly <pez4brian@yahoo.com>
 
   * demo/mlt_voiceover, demo/pango.mlt, src/modules/core/data_fx.properties,
   src/modules/gtk2/producer_pango.yml, src/tests/pango.c: Add "family" and
   "style" properties to pango producer. Deprecate "font" property.
 
-2011-10-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Improve a/v sync and fix possible
-  inf loop w/ audio_index=all  Sometimes it would ignore the next packet that
-  falls on the current frame time - ignore was too agressive. And with
-  audio_index=all, it is faulty to predict interleaving level of streams
-  sometimes causing continual backward seeks.
-
 2011-10-11  Brian Matherly <pez4brian@yahoo.com>
 
   * src/modules/decklink/producer_decklink.yml, src/modules/sox/filter_sox.yml:
   src/modules/gtk2/producer_pango.yml: Add outline to pango and dynamic text
   services. Add pad and align to dynamic text.
 
-2011-10-08  Brian Matherly <pez4brian@yahoo.com>
-
-  * src/modules/gtk2/filter_dynamictext.c: dynamic text fixes: buffer overflows
-  an support adjacent keywords.
-
-2011-10-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Add -progress2 option to get progress with newlines. 
-  Makes easier to get progress updates in some scripts.
-
-2011-10-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix regression on audio devices.
-
-2011-10-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Improve previous fix (efebb3) to
-  prevent infinite loop.
-
-  * src/modules/avformat/producer_avformat.c: Prevent closing alreadu closed
-  AVCoddecContexts.  Patch supplied by Mikko Rapeli.
-
-2011-10-03  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix framebuffer producer in
-  property (3417991)
-
 2011-10-02  Brian Matherly <pez4brian@yahoo.com>
 
   * README, docs/TODO, docs/policies.txt, docs/services.txt: Remove docs/TODO,
   src/modules/xml/mlt-xml.dtd, src/modules/xml/producer_xml.c: Add consumer
   element to xml producer.
 
-2011-09-30  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sox/filter_sox.c: Fix segfault in sox with no effect.
-
-2011-09-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix race on stream index
-  (kdenlive-2296)
-
-  * src/modules/avformat/producer_avformat.c: Fix crash when codec not yet
-  opened (or just closed?)
-
-  * src/modules/avformat/producer_avformat.c: Fix some unprotected calls to
-  av_close_input_file.
-
-2011-09-28  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Add re-open capability to
-  decklink producer.  This causes the producer to automatically close itself
-  when it reaches the "end" as defined by an out or length property. Then, the
-  same producer can be re-opened if reused elsewhere in a playlist or another
-  instance of the decklink producer can use the same card. This requires that
-  the decklink producer be permitted to play out to its duration.
-
-2011-09-27  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix multi-threaded encoding on
-  libavcodec older than v53.
-
-2011-09-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_profile.c: Fix regression loading profile.  Also, prefer
-  mlt_environment(MLT_DATA) over $datadir to make indirection possible with
-  MLT_DATA environment variable and to be consistent with mlt_profile_list().
-
-  * src/framework/mlt_profile.c: Fix regression loading profile.  Also, prefer
-  mlt_environment(MLT_DATA) over $datadir to make indirection possible with
-  MLT_DATA environment variable and to be consistent with mlt_profile_list().
-
 2011-09-25  Brian Matherly <pez4brian@yahoo.com>
 
   * src/modules/gtk2/filter_dynamictext.yml, src/modules/gtk2/producer_pango.c,
   * src/modules/frei0r/factory.c, src/modules/jackrack/plugin_mgr.c: Load
   frei0r and ladspa plugins relative to exe on win32
 
-  * src/modules/videostab/stab/estimate.c: Fix videostab build on win32
-
   * src/framework/Makefile, src/framework/mlt_factory.c,
   src/framework/mlt_profile.c: Fix build on win32
 
-  * src/modules/avformat/consumer_avformat.c: Add parenthesis to fix warning.
-
   * src/framework/mlt_profile.c, src/framework/mlt_properties.c,
   src/framework/mlt_repository.c: Fix and cleanup profile and preset dirs.
 
   * src/framework/mlt_profile.c, src/framework/mlt_repository.c: Make profiles
   relative to MLT_DATA instead of $prefix/share/mlt
 
-2011-07-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_factory.c: Make modules and data relative to executable
-  for win32 and osx.  Requires RELOCATABLE to be defined for osx.
-
 2011-09-25  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/decklink/consumer_decklink.cpp,
   src/modules/decklink/producer_decklink.cpp: Fix building decklink on win32
 
-2011-09-24  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Fix executing stop when not
-  started (and vice versa).
-
-2011-09-23  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/linsys/consumer_SDIstream.c: Fix audio_index=all with linsys
-  SDI consumer.
-
-  * src/modules/core/filter_audiochannels.c: Fix uninitialized var in
-  audiochannels filter.
-
-2011-09-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_audio.c: Fix intermittent crash when closing
-  sdl_audio.
-
-2011-09-22  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/videostab/stab/estimate.c: fix to compile an MAC (point 1)
-
-2011-09-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_geometry.c: Serialize geometry with %g instead of my own
-  macros.
-
 2011-09-20  Dan Dennedy <dan@dennedy.org>
 
-  * presets/consumer/avformat/Sony-PSP: Add Sony PlayStation Portable encode
-  preset
-
   * presets/consumer/avformat/XDCAM-HD422,
   presets/consumer/avformat/atsc_1080i_50/DNxHD,
   presets/consumer/avformat/atsc_1080i_5994/DNxHD,
   src/modules/gtk2/filter_dynamictext.c,
   src/modules/gtk2/filter_dynamictext.yml: Add filter_dynamictext.
 
-2011-09-15  Till Theato <root@ttill.de>
-
-  * src/modules/kdenlive/filter_freeze.c: Freeze filter: Fix alpha handling.
-
-  * src/modules/kdenlive/filter_freeze.c: Freeze filter: Stop using 'this'.
-
-  * src/modules/kdenlive/producer_framebuffer.c: Framebuffer producer: Fix
-  alpha handling (Kdenlive-2311).
-
-2011-09-14  Till Theato <root@ttill.de>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Producer framebuffer: Stop
-  using 'this'.
-
-2011-09-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_factory.c: Always Load the system locales.
-
 2011-09-11  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/sox/Makefile, src/modules/sox/factory.c,
   Document normalise and analysis for sox.  This change separates the general
   sox metadata from effect instance metadata.
 
-  * src/modules/sox/filter_sox.c: Add analysis effect to sox filter.  This
-  analyzes the audio to determine a normalized gain level. The result is
-  suitable for XML serialization.
-
-2011-09-10  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sox/filter_sox.c: Only compute rms if normalise.
-
-  * src/modules/sox/filter_sox.c: Only compute rms if normalise.
-
-  * src/modules/sox/filter_sox.c: Remove some old cruft in sox.
-
-  * src/framework/mlt_property.c: Fix race conditions in mlt_property.
-
-2011-09-10  j-b-m <jb@kdenlive.org>
-
-  * src/framework/mlt_geometry.c: Skip empty keyframes when parsing geometry.
-
 2011-09-09  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/Makefile, src/modules/core/factory.c,
   presets/consumer/avformat/atsc_720p_60/DNxHD: Add a bunch of DNxHD encode
   presets.
 
-  * src/modules/core/transition_composite.c: Fix composite_copy_region on
-  locale using comma for decimal.
-
-2011-09-08  j-b-m <jb@kdenlive.org>
-
-  * src/framework/mlt_property.c: Fix locale corruption.  setlocale returns a
-  pointer that is no longer valid after the intermediate call to setlocale.
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix Kdenlive title module
-  breaking locale.
-
-2011-09-06  Dan Dennedy <dan@dennedy.org>
-
-  * presets/consumer/avformat/XDCAM-HD422: Add XDCAM HD encode preset.
-
-  * src/framework/mlt_multitrack.c: Fix many tracks with avformat producer at
-  same time (kdenlive-2286).
-
-  * presets/consumer/avformat/XDCAM-HD422: Fix many tracks with avformat
-  producer at same time (kdenlive-2286).
-
-2011-09-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Add support for writing timecode
-  from vitc metadata.
-
 2011-09-04  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/melt/producer_melt.c, src/modules/xml/producer_xml.c: Change
   * src/framework/mlt_cache.c, src/framework/mlt_cache.h: Add
   mlt_cache_get_size()
 
-  * src/modules/melt/producer_melt.c: Fix melt crash on many avformat producers
-  active.
-
-  * src/framework/mlt_cache.c: Fix setting the size of a cache up to 200.
-
 2011-09-03  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/decklink/producer_decklink.cpp,
   * src/modules/sox/factory.c, src/modules/sox/filter_sox.c: Use the sox
   version in metadata and serialization.
 
-  * src/modules/frei0r/factory.c: Serialize the frei0r version.
-
   * src/modules/xml/consumer_xml.c, src/modules/xml/mlt-xml.dtd: Add MLT
   version to serialized XML.
 
   * src/modules/frei0r/factory.c, .../motion_est/filter_autotrack_rectangle.c:
   Convert some printfs to fprintf(stderr) or mlt_log.
 
-2011-08-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix crash at end of second pass.
-
-2011-08-28  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Copy VITC to frame meta
-  property.  Can be burned in with data_show filter. Perhaps this can be stored
-  on the producer property using key frames for discontinuities. Then, it can
-  be retrieved and supplied to some new filter that would put the
-  meta.attr.vitc.markup property on frames.
-
-2011-08-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sox/factory.c: Fix bad comparison on metadata for 'sox' (not
-  sox.*)
-
-  * src/modules/frei0r/factory.c: Initialize stat buffer.
-
 2011-08-16  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/xml/consumer_xml.yml: Document serializing xml to property.
-
   * src/modules/xml/consumer_xml.c, src/modules/xml/consumer_xml.yml: Add
   no_meta property to xml consumer.  Applications that use the consumer for its
   project file might want to reduce xml bloat by setting this.
 
-  * src/modules/xml/consumer_xml.yml: Document some xml consumer properties.
-
   * src/modules/jackrack/consumer_jack.c,
   src/modules/jackrack/filter_jackrack.c, src/modules/jackrack/process.c: Fix
   segfault on concurrent calls to jack_activate().
 
 2011-08-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/framework/mlt_geometry.c: Serialize geometry with integer or float
-  representation.
-
-  * src/modules/avformat/filter_avcolour_space.c: Check swscale context before
-  using it.  Old patch suggested by j-b-m on Feb 9, 2011.
-
-  * src/modules/videostab/filter_videostab.c: More cleanup.
-
-  * src/modules/videostab/Makefile: Fix make install.
-
   * src/framework/mlt_filter.c, src/framework/mlt_filter.h,
   src/mlt++/MltFilter.cpp, src/mlt++/MltFilter.h: Add mlt_filter_get_length2.
 
-2011-08-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/videostab/filter_videostab.c: Some cleanup - reformating,
-  consolidation
-
-  * src/modules/videostab/filter_videostab.c: Stop using 'this'
-
-  * src/modules/videostab/filter_videostab.c: Remove global variables.
-
-  * src/modules/videostab/stab/estimate.c: Fix compile error on MAXFLOAT.
-
-  * src/modules/videostab/filter_videostab.c: Fix for GPL license.
-
 2011-08-12  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/videostab/factory.c,
   src/modules/videostab/filter_videostab.yml: added yml metadata
 
-  * src/modules/videostab/filter_videostab.c: removed comments
-
-  * src/modules/videostab/filter_videostab.c: some cleanup, loading from
-  deshake file works now (if correct) for my sample (45 frames) the filter will
-  do 2 runs, first with 37 , second with 45 frames. so the resut will look like
-  not working.  correct length deshake file will work.
-
 2011-08-11  Marco Gittler <g.marco@freenet.de>
 
-  * src/modules/videostab/filter_videostab.c: some vars are now local instead
-  of global. storing pos_h now works, but loading pos_h from file does not
-  produce the same result.
-
   * src/modules/videostab/factory.c, src/modules/videostab/filter_videostab.c:
   compile fix
 
   src/modules/videostab/stab/vector.h: first version of video stabilization
   from http://vstab.sourceforge.net/
 
-2011-08-09  Till Theato <root@ttill.de>
-
-  * src/modules/jackrack/factory.c: Fix regression with ladspa metadata.
-
-2011-08-06  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/jackrack/consumer_jack.c: Use JACK to lookup default ports.
-
 2011-08-03  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/jackrack/Makefile, src/modules/jackrack/configure,
   * src/modules/jackrack/Makefile, src/modules/jackrack/consumer_jack.yml: Add
   service metadata for jack consumer.
 
-  * src/modules/jackrack/consumer_jack.c: Add volume property to jack consumer.
-
-  * src/modules/jackrack/filter_jackrack.c: Fail gracefully when unable to
-  connect to JACK.
-
   * src/modules/jackrack/Makefile, src/modules/jackrack/consumer_jack.c,
   src/modules/jackrack/factory.c: Add audio-only JACK consumer.  Fires
   consumer-frame-show for video frames.
 
-2011-08-01  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix regression in multiple audio
-  tracks.  Regresssion introduced with audiochannels normalization filter.
-
-2011-07-28  Maksym Veremeyenko <verem@m1stereo.tv>
-
-  * src/modules/decklink/consumer_decklink.cpp: Make scheduling priority of
-  decklink lib thread adjustable.  Uses existing mlt_consumer priority
-  property, but also responds to special "max" and "min" values.
-
-2011-07-26  Brian Matherly <pez4brian@yahoo.com>
-
-  * src/modules/core/transition_composite.yml: Mark composite transition
-  metadata properties that are deprecated as such.
-
-  * src/melt/melt.c: Filter service metadata from being displayed if it is
-  tagged as "Hidden".
-
 2011-07-24  Brian Matherly <pez4brian@yahoo.com>
 
   * Makefile, src/modules/avformat/consumer_avformat.yml,
   loader producer. Add yml validation rule to Makefile. All yml files pass
   validation against metaschema.yaml.
 
-2011-07-24  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.yml: Document the redirect property.
-
-  * src/modules/avformat/consumer_avformat.c: Remove mlt protocol, use
-  ByteIOContext if <v53 libavformat.
-
-2011-07-11  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Add support for custom
-  AVIOContext.  New versions of ffmpeg drop ability to register a protocol.
-
 2011-07-22  Dan Dennedy <dan@dennedy.org>
 
-  * src/swig/Makefile: Add empty uninstall target to swig Makefile.
-
   * src/modules/core/filter_mirror.yml, src/modules/core/filter_mono.yml,
   src/modules/core/filter_obscure.yml, src/modules/core/filter_region.yml,
   src/modules/core/transition_luma.yml, src/modules/core/transition_mix.yml,
   src/modules/xml/consumer_xml.yml: Cleanup Brian's service metadata
   contribution.
 
-  * src/modules/decklink/consumer_decklink.cpp: Touchup spacing in decklink
-  consumer.
-
-2011-07-22  Maksym Veremeyenko <verem@m1stereo.tv>
-
-  * src/modules/decklink/consumer_decklink.cpp: Log when decklink audio buffer
-  level changes.  Very useful to understand when unexpected behavior happens.
-
-  * src/modules/decklink/consumer_decklink.cpp: Prevent decklink audio buffer
-  overflow.  Flush audio buffer if it more then preroll configured length.
-
-  * src/modules/decklink/consumer_decklink.cpp: Notify dropped frame in
-  decklink.  i.e. status *bmdOutputFrameDropped*
-
-  * src/modules/decklink/consumer_decklink.cpp: Avoid float rounding error when
-  calculating audio timestamp.
-
-2011-07-22  Dan Dennedy <dan@dennedy.org>
-
   * src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.c: Make ffmpeg v53-specific code more
   readable and searchable.
 
-  * src/modules/avformat/consumer_avformat.c: Fix codec-specific defaults for
-  libavcodec v53 (3370720).
-
-  * src/modules/avformat/consumer_avformat.c: Refactor to pass AVCodec into
-  add_audio/video_stream.
-
   * configure, src/framework/mlt_version.h: set interim version 0.7.5
 
   * src/framework/mlt_property.c, src/framework/mlt_property.h: Fix build on
   Debian kfreebsd.
 
-2011-07-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.h: Document the priority property.
-
-2011-07-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/consumer_decklink.cpp: Touchup spacing in decklink
-  consumer.
-
-2011-07-22  Maksym Veremeyenko <verem@m1stereo.tv>
-
-  * src/modules/decklink/consumer_decklink.cpp: Log when decklink audio buffer
-  level changes.  Very useful to understand when unexpected behavior happens.
-
-  * src/modules/decklink/consumer_decklink.cpp: Prevent decklink audio buffer
-  overflow.  Flush audio buffer if it more then preroll configured length.
-
-  * src/modules/decklink/consumer_decklink.cpp: Notify dropped frame in
-  decklink.  i.e. status *bmdOutputFrameDropped*
-
-  * src/modules/decklink/consumer_decklink.cpp: Avoid float rounding error when
-  calculating audio timestamp.
-
-2011-07-22  Dan Dennedy <dan@dennedy.org>
-
   * src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.c: Make ffmpeg v53-specific code more
   readable and searchable.
 
-  * src/modules/avformat/consumer_avformat.c: Fix codec-specific defaults for
-  libavcodec v53 (3370720).
-
-  * src/modules/avformat/consumer_avformat.c: Refactor to pass AVCodec into
-  add_audio/video_stream.
-
   * configure, src/framework/mlt_version.h: set interim version 0.7.5
 
   * src/framework/mlt_property.c, src/framework/mlt_property.h: Fix build on
   Debian kfreebsd.
 
-2011-07-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.h: Document the priority property.
-
 2011-07-19  Brian Matherly <pez4brian@yahoo.com>
 
   * src/modules/core/filter_mirror.yml, src/modules/core/filter_mono.yml,
 
 2011-07-16  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.7.4
-
   * Doxyfile, configure, docs/melt.1, docs/melt.txt,
   src/framework/mlt_version.h: Set version to 0.7.4
 
-  * NEWS: Add release notes for v0.7.4
-
   * src/modules/jackrack/factory.c, src/modules/jackrack/plugin_desc.c,
   src/modules/jackrack/plugin_desc.h: Properly represent LADSPA plugin author.
 
-2011-07-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Cleanup fprintf left in last
-  commmit
-
-  * src/modules/avformat/producer_avformat.c: Fix audio glitch on seek
-  (3362840).
-
-2011-07-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/xml/producer_xml.c: Load XML with LC_NUMERIC without changing
-  global locale.  Uses mlt_properties_set_lcnumeric() instead of setlocale().
-  This is only known to work on Linux.
-
-  * src/framework/mlt_properties.c: Use correct constant for
-  mlt_properties_set_lcnumeric().
-
-2011-07-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix regression seeking to in
-  point on seekable.
-
 2011-07-11  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_properties.c, src/framework/mlt_property.c,
   * presets/consumer/avformat/webm, presets/consumer/avformat/webm-pass1,
   presets/consumer/avformat/webm-pass2: Fix webm preset.
 
-  * src/framework/mlt_properties.c: Ensure serialized yaml is LC_NUMERIC=C. 
-  This is needed to ensure consistency. The metadata is read as string data and
-  converted to numbers on demand. This is why loading defaults to C locale -
-  since they were authored with that in mind. However, some plugins dynamically
-  generate metadata and may set values with int or double. Therefore, we need
-  to make it all output consistently, and for now that means C.
-
-  * src/framework/mlt_property.c: Protect locale hack with a mutex to ensure
-  consistency.
-
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   src/modules/sdl/consumer_sdl_preview.c: Make maximum consecutive-dropped
   frames configurable.  Defaults to old value of 5 that seems more preferable
   for video editing.
 
-  * src/framework/mlt_playlist.c: Fix playlist corruption with long blanks
-  (kdenlive-2219).
-
-  * src/modules/gtk2/producer_pango.c: Add a workaround in pango for old
-  kdenlive countdowns.
-
 2011-07-09  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/feeds/NTSC/data_fx.properties,
   mlt_property_get_string_l.  Locale-specific variants of key properties
   functions.
 
-  * src/modules/core/filter_obscure.c: Let obscure accept / as a coordinate
-  delimiter.
-
-  * src/modules/frei0r/factory.c: Make frei0r version metadata support locale. 
-  Patch by j-b-m
-
 2011-07-07  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/filter_data_show.yml, src/modules/core/filter_gamma.yml,
 
 2011-07-04  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/configure: Cleanup display of recommended versions.
-
-  * presets/consumer/avformat/x264-medium-pass1: Skip audio output with first
-  pass.
-
-  * presets/consumer/avformat/x264-medium-pass1: Add new FFmpeg fastfirstpass
-  option.
-
-  * src/modules/avformat/consumer_avformat.c: Suppress confusing message when
-  vpre does not exist.
-
   * presets/consumer/avformat/x264-medium-baseline,
   presets/consumer/avformat/x264-medium-main: Fix profile-based x264 presets
   for FFmpeg v0.8+.
 
-  * src/modules/avformat/consumer_avformat.c: Fix crash in consumer on FFmpeg
-  v0.8 and later.
-
-  * src/modules/avformat/configure: Revert removal of --avformat-ldextra.
-
-  * src/modules/avformat/factory.c: Fix metadata for avformat
-  demuxer/device-specific options.
-
   * presets/consumer/avformat/x264-medium,
   presets/consumer/avformat/x264-medium-baseline,
   presets/consumer/avformat/x264-medium-main,
   src/modules/avformat/producer_avformat.yml, src/modules/melt/producer_melt.c:
   Support standard query syntax on avformat URL.
 
-  * reconfigure: Add convenient reconfigure script.
-
-2011-07-03  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Change some verbose messages with
-  new_seek to debug.
-
-  * src/modules/avformat/producer_avformat.c: Fix file descriptor leak in
-  reopen_video().
-
-  * src/modules/avformat/producer_avformat.c: Fix race condition by adding
-  take_lock to producer_open().
-
-  * src/framework/mlt_consumer.c: Add check for null frame.
-
-  * src/modules/dv/producer_libdv.c: Make libdv sample aspect ratio consistent
-  with profiles.  Patch by: Maksym Veremeyenko
-
 2011-07-02  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/decklink/DeckLinkAPI_h.h,
   src/modules/decklink/configure, src/modules/decklink/consumer_decklink.cpp,
   src/modules/decklink/producer_decklink.cpp: Add Windows support for DeckLink.
 
-2011-06-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl.c: Make it easier to embed sdl in Windows
-  applications.
-
-2011-06-25  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Add handling for heavy frame-dropping with
-  real_time>1.
-
-  * src/framework/mlt_consumer.c: Improve reliability of real_time=1
-  frame-dropping.
-
-  * src/framework/mlt_consumer.c: Simplify and comment real_time=1
-  frame-dropping.
-
-2011-06-24  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Use int64_t for req_position and
-  int_position.
-
 2011-06-22  Dan Dennedy <dan@dennedy.org>
 
   * presets/consumer/avformat/dv_ntsc/DV,
   presets/consumer/avformat/dv_pal_wide/DVCPRO50: Add DV and DVCPRO50 encode
   presets.
 
-2011-06-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Make sure avformat consumer
-  closes all mlt_frames.
-
-  * src/modules/avformat/producer_avformat.c: Fix regression on avdevice.  When
-  using non-integer profile frame rate, supplying frame_rate on URL, and not
-  supplying frame_rate_base on URL.
-
-  * src/modules/core/producer_consumer.c: Fix xml producer overwriting explicit
-  profile.
-
 2011-06-17  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/Makefile, src/framework/mlt_types.h, src/melt/Makefile,
   src/modules/avformat/Makefile, src/modules/gtk2/Makefile,
   src/modules/sdl/Makefile, src/win32/fnmatch.c: Cleanup Win32 build.
 
-  * src/framework/mlt_repository.c: Win32 compile fix.
-
 2011-06-15  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_transition.c, src/modules/core/transition_composite.c:
   Fix regression in field rendering luma transition.  Due to refactoring
   composite and luma into mlt_transition_get_progress_delta().
 
-  * src/modules/avformat/producer_avformat.c: Fix int64_t to int overflow
-  problem.
-
-2011-06-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Support decklink video input
-  format detection.  This makes it work with auto-producer. After calling
-  mlt_profile_from_producer(), you must close the decklink producer and re-open
-  it with the updated profile. Also, this adds support for top_field_first and
-  colorspace indication.
-
 2011-06-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/decklink/producer_decklink.cpp: Fix waiting for frame in
-  decklink producer.
-
-  * profiles/sdi_486i_5994: Fix aspect ratio of sdi_486i_5994.
-
   * src/modules/avformat/producer_avformat.c,
   src/modules/avformat/producer_avformat.yml: Add video_delay to avformat
   producer.
 
 2011-06-11  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Provide A/V sync for non-seekable
-  sources.
-
-  * src/melt/melt.c: Fix melt -silent with pipe input.
-
   * src/modules/decklink/producer_decklink.cpp,
   src/modules/decklink/producer_decklink.yml: Add prefill property to decklink
   producer.
 
-  * src/modules/avformat/producer_avformat.c: Fix bug in avformat URL parsing. 
-  Especially reproducible on file: URLs.
-
-  * src/modules/avformat/producer_avformat.c: Fix sync of multiple audio
-  streams with audio_index=all.
-
-2011-06-10  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix infinite loop with
-  audio_index=all on sample provided by BCE.
-
-  * src/modules/decklink/consumer_decklink.cpp: Rework decklink consumer to use
-  timestamped audio packet.  Patches supplied by Maksym Veremeyenko.
-
-2011-06-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Disable new_seek on h264/ts from
-  non-seekable source (udp, pipe).
-
-2011-06-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/gtk2/producer_pango.c: Fix pango producer from loading with
-  empty string arg.
-
 2011-06-06  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Temporary fix for new crash when
-  closing codec.
-
-  * src/modules/avformat/consumer_avformat.c: Fix setting codec-specific
-  options for avcodec v53.
-
-  * src/modules/avformat/factory.c: Fix crash generating avformat metadata.
-
   * src/framework/mlt_consumer.c, src/modules/avformat/consumer_avformat.yml:
   Change consumer 'profile' property to 'mlt_profile'  libavcodec uses the
   profile property for aac and libx264.
 
 2011-06-05  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Drop usage of av_demuxer_open()
-  in avformat v53.  It is causing problems and need more stability after the
-  raft of changes.
-
-  * src/modules/avformat/producer_avformat.c: Fix regressions on libavformat
-  v53 and failing on invalid file.
-
   * src/modules/avformat/consumer_avformat.yml,
-  src/modules/avformat/producer_avformat.yml: Change URI to URL in avformat
-  yaml.
-
-  * src/modules/avformat/producer_avformat.c: Fix compilation error on
-  libavformat v53.
-
-  * src/melt/melt.c, src/modules/avformat/consumer_avformat.c: Send melt -query
-  and -help to stdout.  Nice for use with pager or grep, awk, etc.
-
-  * src/melt/melt.c: Do not open terminal on stdin if not a tty.
-
-  * src/melt/melt.c: Have melt detect 'pipe:' and disable reading stdin on
-  terminal.
-
-  * src/modules/avformat/producer_avformat.c: Fix setting default streams on
-  non-seekable streams.
-
-  * src/modules/avformat/producer_avformat.c: Fix setting demuxer private
-  options libavformat for v53+.
-
-  * src/modules/avformat/producer_avformat.c: Tidy code dealing with
-  AVFormatParameters.
-
-  * src/modules/avformat/producer_avformat.c: Refactor common code around
-  producer_open into producer_open.
-
-  * src/modules/avformat/producer_avformat.c: minor cleanup in return handling
-  in parse_url
-
-2011-06-04  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Use a single AVFormatContext for
-  non-seekable sources.  This provides better support for reading from network
-  streams such as rtsp, rtmp, udp, and hopefully pipe.
-
-  * src/modules/avformat/producer_avformat.c: Refactor avformat get_image()
-  into new seek_video().
-
-  * src/modules/avformat/producer_avformat.c: refactor avformat producer_open
-
-  * src/modules/avformat/producer_avformat.c: cleanup producer_avformat_init
-
-  * src/modules/decklink/consumer_decklink.cpp: Default decklink consumer to
-  onefield deinterlace method.
+  src/modules/avformat/producer_avformat.yml: Change URI to URL in avformat
+  yaml.
 
-  * src/modules/decklink/consumer_decklink.cpp: Fix decklink keyer playout
-  speed (3311056).
+  * src/melt/melt.c, src/modules/avformat/consumer_avformat.c: Send melt -query
+  and -help to stdout.  Nice for use with pager or grep, awk, etc.
 
 2011-06-03  Dan Dennedy <dan@dennedy.org>
 
   src/modules/decklink/consumer_decklink.yml: Enable external keyer on decklink
   consumer.  Patch supplied by Maksym Veremeyenko.
 
-2011-06-02  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Fix deadlock on no signal in
-  decklink producer.
-
-  * src/modules/decklink/consumer_decklink.cpp: Fix crash in decklink with
-  keyer and interlaced clips (3310104).
-
-  * src/modules/decklink/Makefile: Install consumer_decklink.yml.
-
-2011-05-31  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/producer_decklink.cpp: Let decklink run forever.  Also
-  fix setting resource property.
-
 2011-05-30  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/decklink/consumer_decklink.cpp: Fix decklink choppy playback
-  (3308341).  This would occur after several pause and play cycles.
-
-  * src/modules/rotoscoping/filter_rotoscoping.yml: Make rotoscoping filter
-  metadata valid yaml.
-
   * src/modules/linsys/Makefile, src/modules/linsys/consumer_sdi.yml,
   src/modules/linsys/factory.c: Add service metadata to linsys module (WIP).
 
   src/modules/dv/factory.c, src/modules/dv/producer_libdv.yml: Add service
   metdata for dv module (WIP).
 
-  * src/swig/ruby/metadata.rb: Add ruby script to generate wiki text files.
-
   * src/modules/core/Makefile, src/modules/core/factory.c,
   src/modules/core/filter_audiowave.yml,
   src/modules/core/filter_brightness.yml,
 
 2011-05-28  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/decklink/producer_decklink.cpp: Report dropped frames.
-
-  * src/modules/decklink/producer_decklink.cpp: Fix memory leak in decklink
-  producer.
-
   * src/swig/python/getimage.py, src/swig/python/waveforms.py: Convert Python
   examples to new frame method.
 
-  * src/swig/python/build: Fix python binding for OS X
-
-  * src/swig/mlt.i: Add mlt.Frame.get_image for Python.
-
-  * src/melt/melt.c: Refactor melt to mlt_profile_from_producer.
-
   * src/framework/mlt_profile.c, src/framework/mlt_profile.h,
   src/mlt++/MltProfile.cpp, src/mlt++/MltProfile.h: Add
   mlt_profile_from_producer().  This new function contains the auto-profile
   feature. Plus setters for Mlt::Profile.
 
-2011-05-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_cache.c: Do not immediately destroy all cache items on
-  purge.  This is behaving badly with the addition of mlt_service_cache_purge
-  in the avformat producer because there were frames in consumer buffers
-  holding references to cache items calling mlt_cache_item_close on
-  destruction.
-
-2011-05-25  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Prevent multiple starts on mlt_consumer.
-
 2011-05-22  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Fix full closure of avformat on
-  explicit close.  JBM wrote: Creating a video4linux producer like (simplified
-  code):  producer = new Mlt::Producer(*profile, "video4linux2:/dev/video0");
-  consumer->connect(*producer); consumer->start();  It works fine. But when I
-  want to stop the capture, there is no way to stop the video4linux producer.
-  Deleting the producer and the consumer still leaves the video4linux device
-  open.  After a few hours of struggling, I figured out that some stuff was
-  kept in the cache. Adding :  mlt_service_cache_purge(
-  MLT_PRODUCER_SERVICE(parent) );  to producer_close (as already done for the
-  qimage producer for example) fixes the issue.
-
-  * src/modules/avformat/producer_avformat.c: Fix regression in
-  protocol/avdevice handling.
-
   * src/modules/jackrack/Makefile, src/modules/jackrack/blacklist.txt,
   src/modules/jackrack/plugin_mgr.c, src/modules/jackrack/plugin_mgr.h: Add
   blacklist for ladspa filters.  Initially includes dssi-vst since that is
   unstable on AV Linux 5.
 
-  * configure: Fix segfault in yadif with gcc 4.6 -O1 or -O2.
-
 2011-05-17  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/jackrack/jack_rack.c: Do not destroy shared plugin_mgr when
-  closing instance.
-
   * src/modules/jackrack/factory.c, src/modules/jackrack/jack_rack.c: Let all
   instances of ladspa share single plugin_mgr.
 
-2011-05-16  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_resize.c: Fix regression getting consumer
-  aspect_ratio.
-
-  * src/modules/feeds/PAL/data_fx.properties: Fix background color on default
-  PAL data_show.
-
-  * src/modules/core/transition_composite.c: Fix manual deinterlace on B in
-  composite.
-
 2011-05-15  Dan Dennedy <dan@dennedy.org>
 
   * docs/melt.1, src/melt/melt.c: Document -jack option.
 
-  * docs/melt.1: Add -query preset to man page.
-
-  * src/modules/jackrack/filter_jackrack.c: Change a log item to debug.
-
   * src/melt/melt.c, src/modules/jackrack/filter_jackrack.c,
   src/modules/jackrack/process.c: Add first draft of JACK transport sync.
 
-  * src/framework/mlt_consumer.c: Improve frame-dropping for real_time=1.  Uses
-  thresholds relative to fps and buffer levels. Properly drops more frames to
-  keep audio continuous. Does not drop first several frames to prevent chopping
-  playback.
-
-  * src/modules/sdl/consumer_sdl_preview.c: Add audio_off and frequency to
-  properties passed to sdl consumer.
-
-  * src/framework/mlt_producer.c: Fix dox error.
-
 2011-05-14  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/jackrack/factory.c: Fix big slowdown enumerating all metadata
-  for ladspa plugins.
-
   * configure, src/mlt++/configure: Fix build on Debian GNU/kFreeBSD.
 
 2011-05-12  Dan Dennedy <dan@dennedy.org>
   future support for property animation (automation), which JACK Rack lacks.
   However, it does still support loading and processing JACK Rack files.
 
-  * src/modules/sox/factory.c: Simplify sox metadata generator.
-
-2011-05-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/configure: Allow decklink to build on OS X.
-
-  * src/modules/sdl/consumer_sdl_preview.c: sdl_preview should default to
-  real_time=1
-
-  * src/framework/mlt_consumer.c: Revert change to max consecutive dropped
-  frames.  At least until a better heuristic is determined.
-
 2011-05-08  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sox/factory.c: Add version check for SOX_EFF_INTERNAL.
-
   * src/modules/sox/Makefile, src/modules/sox/factory.c,
   src/modules/sox/filter_sox.c, src/modules/sox/filter_sox.yml: Add support for
   sox.effect variants.  The legacy forms of 'sox:"effect options"' and 'sox
   metadata for both the generic 'sox' filter and all of the new 'sox.effect'
   ones including their usage help!
 
-  * src/modules/avformat/Makefile: Install consumer_avformat.yml
-
   * src/modules/avformat/filter_avresample.c, src/modules/core/loader.ini: Fix
   inadvertent reording of resample filters.  And add debug log to avresample.
 
 2011-05-06  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Pad the last audio frame with
-  silence.  Instead of returning fewer samples than requested.
-
-  * src/framework/mlt_frame.h: Document the frame audio and image properties.
-
   * src/framework/mlt_tractor.c, src/modules/avformat/producer_avformat.c,
   src/modules/dv/producer_libdv.c, src/modules/vorbis/producer_vorbis.c: Make
   the frame audio properties consistent.
 
-  * src/modules/avformat/producer_avformat.c: Fix avformat producer to use new
-  mlt audio formats.
-
-  * src/modules/core/filter_audioconvert.c: Add conversion routines for new
-  audio formats.  These only doing conversion _from_ the new types
-  mlt_audio_s32le and mlt_audio_f32le. There are no plans at the moment for
-  conversion into them, but it is certainly not out of the question.
-
   * src/framework/mlt_frame.c, src/framework/mlt_types.h: Add mlt_audio_s32le
   and mlt_audio_f32le audio formats.
 
   a new filter to be more manageable. Eventually, we can add options on what to
   do when adding/removing channels.
 
-2011-05-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix channel count for resizing
-  decoded audio buffer when not resampling.
-
-  * src/modules/avformat/producer_avformat.c: Fix regressions in audio
-  decoding.
-
-  * src/modules/avformat/producer_avformat.c: Cleanup compile warnings.
-
-  * src/modules/avformat/producer_avformat.c: Simplify audio pointer and sample
-  size code.
-
-2011-05-01  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: WIP to get >16-bit multi-channel
-  audio working.  Seems close, but something is wrong.
-
-2011-05-04  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Copy cached image if writable
-  copy requested.
-
 2011-05-03  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/framework/mlt_transition.c: Ensure transition B frames get
 
 2011-05-01  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.7.2
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h: Set version
   to 0.7.2
 
-  * NEWS: Add release notes for v0.7.2.
-
   * src/modules/avformat/filter_avresample.c,
   src/modules/resample/filter_resample.c: Finish work to normalize channel
   count.  Also, refactor the audio resamplers to use mlt_audio_format_size()
   src/modules/core/producer_noise.c, src/modules/core/producer_ppm.c: Refactor
   to mlt_frame_set_audio().
 
-  * src/melt/melt.c: Let 'Q' stop melt as well.
-
   * src/modules/feeds/NTSC/data_fx.properties,
   src/modules/feeds/PAL/data_fx.properties: Fix alpha on color of some
   data-feed properties.
 
-  * src/modules/avformat/factory.c: Free temp string.
-
   * src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.c: Add support for new codec- and
   muxer-specific AVOptions.
 
-2011-04-30  Dan Dennedy <dan@dennedy.org>
-
-  * setenv: DYLD_LIBRARY_PATH not needed for me on OS X.
-
-  * src/modules/avformat/producer_avformat.c: Fix sample rate and channel count
-  from avformat producer.  If unable to resample or the decoder does not give
-  the requested channel count, then we should return the actual values so
-  downstream components can do the correct thing if they can. A good example of
-  this is 6 channel AAC when the consumer requests 2 channels. Unlike the AC-3
-  decoder, the AAC decoder can not downmix. So, we were returning audio pcm
-  containing 6 channels but with a channel count of 2.
-
-2011-04-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Try to duplicate last image if
-  decoding fails.
-
 2011-04-22  Dan Dennedy <dan@dennedy.org>
 
-  * src/framework/mlt_consumer.c: Fix intermitent crash in mlt_consumer
-  consumer_read_ahead_thread.
-
-  * src/modules/avformat/producer_avformat.c: Use new
-  av_get_bits_per_sample_fmt() in avformat producer.
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c: Use new avio functions in avformat
   module.
 
 2011-04-21  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sdl/consumer_sdl_audio.c: Fix deadlock in sdl_audio appearing
-  in kdenlive.
-
-  * src/modules/core/producer_ppm.c: Fix compile warns in producer_ppm.c.
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/producer_avformat.c: Fix regression initializing
   coefficients.
 
-  * src/modules/avformat/producer_avformat.c: Use newer
-  av_get_sample_fmt_name() if available.
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_swscale.c,
   src/modules/avformat/producer_avformat.c: Fix avformat build with libavcodec
   v53.
 
-  * src/modules/avformat/configure: Fix detect swscale on libavcodec major
-  version bump.
-
-2011-04-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/producer_colour.c: Fix corruption in color producer
-  (3288984)
-
-2011-04-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/consumer_decklink.cpp: Fix decklink consumer on
-  devices without keyer.
-
 2011-04-09  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_profile.c, src/mlt++/MltProfile.cpp,
   src/mlt++/MltProfile.h, src/swig/mlt.i: Add Mlt::Profile.list().
 
-  * src/framework/mlt_profile.c: Fix mlt_profile_list when MLT_PROFILES_PATH
-  not set.
-
-2011-04-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/kdenlive/filter_freeze.c: Fix deadlock in freeze filter. 
-  Reported by Andrew Wason.
-
 2011-04-07  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/consumer_avformat.yml, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.yml: Add avformat consumer metadata. 
   Improve avformat producer metadata. Significantly extend each with AVOptions.
 
-2011-04-06  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/transition_region.c: Better fix to the region regression
-  (3277867).  This one works with bug report test case, timecode overlay in
-  Kdenlive Render, and Region transition in Kdenlive.
-
-  * src/modules/core/transition_composite.c: Fix regression on region
-  transition (3277867).
-
 2011-04-04  Dan Dennedy <dan@dennedy.org>
 
   * demo/README, demo/demo.ini, demo/mlt_pango_keyframes,
   demo/pango_keyframes.mpl: Add mlt_pango_keyframes demo.
 
-  * src/modules/gtk2/producer_pango.c: Make pango file on invalid file
-  (3272537).
-
 2011-04-03  Dan Dennedy <dan@dennedy.org>
 
   * docs/melt.1, docs/melt.txt, src/melt/melt.c: Add -query formats and codecs
   * src/framework/mlt_profile.c, src/framework/mlt_profile.h: Add
   mlt_profile_list().
 
-  * src/modules/decklink/consumer_decklink.yml: Add parameter descriptions.
-
-2011-04-02  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/consumer_decklink.cpp: Add keyer support to decklink
-  consumer.
-
 2011-03-31  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/decklink/consumer_decklink.yml,
 
 2011-03-27  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Fail gracefully on unsupported
-  codec (3251438).
-
   * configure, src/modules/core/transition_composite.c: Fix regression in
   region filter (3251260).
 
-  * ChangeLog: Update ChangeLog for v0.7.0.
-
   * Doxyfile, configure, src/framework/mlt_version.h: Set version to 0.7.0
 
-  * NEWS: Add release notes for v0.7.0.
-
-  * src/modules/melt/producer_melt.c: Fix segfault on missing melt argument
-  (3249982).
-
-  * src/modules/avformat/producer_avformat.c: Fix a segfault in avformat with
-  parallel consumer.
-
-  * src/modules/core/transition_composite.c: Fix composite using wrong B frame
-  scaling.  This could happen when the caller of mlt_frame_get_image supplied 0
-  for width and height. For example, Kdenlive's GL output with the sdl_audio
-  consumer with real_time > 1 and paused.
-
-  * docs/melt.1: Fix segfaul on missing melt argument (3249982).
-
-  * src/modules/sdl/consumer_sdl_audio.c: Fix some crashing in sdl_audio.
-
-  * src/modules/sdl/consumer_sdl_audio.c: Also increase audio_buffer default in
-  sdl_audio.
-
-  * src/modules/avformat/configure: Disable VDPAU by default.  Require new
-  --avformat-vdpau to enable it.
-
   * src/modules/avformat/consumer_avformat.c, src/modules/sox/filter_sox.c,
   src/modules/xml/producer_xml.c: Use mlt_properties_get_value where possible.
 
   src/modules/linsys/configure: Enable linsys by default on Linux.  Disable
   linsys and decklink by default on OS X and Windows.
 
-  * src/modules/configure: Display all configure options with --help. 
-  Regardless of --enable-gpl setting.
-
-  * src/modules/avformat/producer_avformat.c: Redo locking in avformat
-  producer.  This significantly improves concurrency. The service locks added
-  during parallel consumer development also introduced a concurrency
-  performance regression even for the single-threaded consumer. The result was
-  much audio discontinuity due to audio output buffer underruns. As a result,
-  the recent bug fix to re-open the video demuxer upon seeking to the first
-  frame had to be rewritten.
-
 2011-03-23  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/vdpau.c: Fix vdpau crashes when failed to init.
-
-  * src/modules/avformat/vdpau.c: Fix unchecked vdpau pointer.
-
-  * src/modules/sdl/consumer_sdl_preview.c: Default sdl_preview prefill to 1. 
-  Since buffer and prefill were recently passed from sdl_preview onto sdl,
-  sdl's default buffer level changed to the base service default of 25. That
-  change increases the latency of transport controls. Changing the prefill to 1
-  resolves that while still allowing the rendering thread a chance to do some
-  anticipatory work.
-
-  * src/modules/decklink/consumer_decklink.cpp: Fix a comment in decklink
-  consumer.
-
   * src/framework/mlt_consumer.c, src/modules/decklink/consumer_decklink.cpp:
   Fix a couple null pointer bugs.
 
-2011-03-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/consumer_decklink.cpp: Improve frame-dropping in
-  decklink.
-
 2011-03-20  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/jackrack/filter_jackrack.c, src/modules/jackrack/plugin.h,
   * profiles/atsc_1080p_50, profiles/atsc_1080p_5994, profiles/atsc_1080p_60:
   Add high frame rate 1080p profiles.
 
-2011-03-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix regression on seeking to
-  first frame with audio_index set.
-
-2011-03-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Add force_length and
-  adjust_length properties.  The reporter on kdenlive bug 2003 reports another
-  user on IRC had the same problem with clips being too long. Change the
-  default length adjustment to be more safe and add new properties to affect
-  the heuristic for other applications that might want a different behavior.
-  adjust_length applies a plus/minus operand to the detected length.
-  force_length provides a brute force length override.
-
-  * src/modules/avformat/producer_avformat.c: Fix some incorrect frame rates in
-  avformat (kdenlive-1616).
-
-  * src/modules/frei0r/factory.c: Support frei0r transitions that use
-  f0r_update2().
-
-  * configure: Fix amd64 detection on FreeBSD.  Patch from Alberto Villa.
-
-2011-03-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Add boolean use_profile property to crop
-  filter.  This lets one express crop amounts in pixels relative to profile
-  resolution instead of in terms of source resolution.
-
-  * src/modules/frei0r/blacklist.txt: We do not yet support
-  f0r_param_position_t.
-
-2011-03-12  Ertan Deniz <ertanden@gmail.com>
-
-  * src/framework/mlt_factory.c: Set global variables to NULL in
-  mlt_factory_close  to enable mlt_factory to be initialized and closed
-  multiple times.
-
-2011-03-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Prefer opening codec by name
-  instead of by ID.  This fixes a bug with actually using libxvid instead of
-  mpeg4 because both share the same CODEC_ID_MPEG4. This is similar to the
-  recent problem with ac3 selection in new versions of ffmpeg that have 2 ac3
-  encoders.
-
 2011-03-09  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/frei0r/filter_frei0r.c, src/modules/frei0r/frei0r_helper.c,
   mlt_transition_get_position. frei0r's time parameter is seconds, but we were
   passing frame count.
 
-  * src/modules/core/transition_region.c: Fix region transition with more than
-  2 tracks.
-
   * src/modules/core/transition_region.c, src/modules/plus/transition_affine.c:
   Refactor to mlt_transition_get_position()
 
   src/mlt++/MltTransition.cpp, src/mlt++/MltTransition.h: Add
   mlt_transition_get_position()
 
-  * src/modules/core/transition_luma.c: Remove obsolete unique position on
-  frame.
-
-  * src/framework/mlt_transition.c: Use the producer when always active.
-
   * src/modules/core/filter_luma.c, src/modules/core/filter_watermark.c,
   src/modules/dgraft/filter_telecide.c, src/modules/kdenlive/filter_freeze.c,
   .../motion_est/filter_autotrack_rectangle.c,
 
 2011-03-08  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/filter_obscure.c: Refactor to mlt_filter_get_progress().
-
   * src/framework/mlt_filter.c, src/framework/mlt_transition.c: Use the
   producer when filter/transition always active.
 
   src/mlt++/MltFilter.cpp, src/mlt++/MltFilter.h: Add
   mlt_filter_get_progress().
 
-  * src/modules/plus/transition_affine.c: Refactor to
-  mlt_transition_get_length().
-
 2011-03-10  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Fix regression on AC-3 fix.  The
-  recent AC-3 fix broke automatic codec selection based on format. So, we
-  choose codec by name only for ac3 now.
-
-  * src/modules/swfdec/configure: Fix typo in swfdec configure script.
-
   * src/modules/swfdec/Makefile, src/modules/swfdec/configure: Add build
   support for swfdec 0.7.  And prioritize newer versions over older ones.
 
-  * src/modules/resample/filter_resample.c: Increase resample buffer size.  For
-  example, trying to resample 6 channels of 48 KHz would fail.
-
-  * src/modules/resample/filter_resample.c: Remove unnecessary audio conversion
-  to float.
-
-  * src/modules/avformat/producer_avformat.c: Fix audio resample with
-  audio_index=all.  This still only works with channels <= 2. Streams with
-  channels > 2 are resampled downstream with the resample filter. However, that
-  only works when said stream has the highest sample rate.
-
-2011-03-07  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: use new API
-  functions to prevent some possible issues.
-
-2011-03-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_audioconvert.c: Fix regression in audioconvert.
-
 2011-03-06  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/transition_composite.c,
   src/mlt++/MltTransition.cpp, src/mlt++/MltTransition.h: Add
   mlt_transition_get_length().
 
-  * src/modules/frei0r/filter_frei0r.c: Refactor to use mlt_frame_get_length().
-
-  * src/modules/normalize/filter_volume.c: Remove unused variable.
-
   * src/framework/mlt_filter.c, src/framework/mlt_filter.h,
   src/mlt++/MltFilter.cpp, src/mlt++/MltFilter.h: Add mlt_filter_get_length().
 
-  * src/framework/mlt_playlist.c: Refactor to use mlt_producer_get_playtime().
-
   * src/modules/core/filter_audioconvert.c, src/modules/core/filter_mono.c,
   src/modules/core/producer_consumer.c: Refactor to mlt_audio_format_size().
 
   * src/modules/core/producer_noise.c, src/modules/normalize/filter_volume.c:
   Remove unused variables.
 
-  * src/modules/avformat/filter_avcolour_space.c: Define out this unused code.
-
   * src/modules/avformat/filter_swscale.c,
   src/modules/avformat/producer_avformat.c, src/modules/core/filter_crop.c,
   src/modules/core/filter_resize.c, src/modules/core/producer_colour.c,
   src/mlt++/MltFrame.cpp, src/mlt++/MltFrame.h: Add mlt_frame_set_image and
   mlt_frame_set_alpha.
 
-  * src/framework/mlt_properties.c: Fix spelling error in doxygen.
-
-  * src/framework/mlt_consumer.c: Fix thread cleanup on parallel consumer stop.
-   This was appearing often as a segfault at the end of melt with the avformat
-  consumer.
-
   * src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c:
   Alias bicubic for hyper in pango and pixbuf.
 
   * : Add gpl flag file to rotoscoping filter.
 
-  * src/modules/avformat/consumer_avformat.c: Fix AC-3 encoding
-  (kdenlive-2010).  FFmpeg now has separate encoders that take float versus
-  fixed samples.
-
-2011-03-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/gtk2/filter_rescale.c: Make 'bicubic' an alias for highest
-  quality in gtk scaler.
-
-  * src/modules/qimage/qimage_wrapper.cpp: Fix handling monochrome in qimage.
-
-2011-03-03  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/transition_luma.c: Fix string comparison and requested
-  luma size.
-
-  * src/modules/core/filter_resize.c: Prevent attempt to pad to a smaller size.
-
-  * src/modules/core/transition_luma.c: Fix luma semantics when both reverse
-  and invert.  Previously, when not using a wipe (dissolve), invert would make
-  the transition have no effect. Now, it works and does the same thing as
-  reverse. Also, when using a wipe, reverse had no effect when invert was set,
-  and the desired effect could not be achieved. Now, it works as expected.
-
-  * demo/demo: Set a profile for the demo script.
-
-  * demo/consumers.ini: Drop MainConcept and BlueFish444 from the demo
-  consumers.
-
-  * src/framework/mlt_properties.c: Improve mlt_properties_close() in debugger.
-
 2011-03-02  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/kdenlive/filter_wave.c: Rewrite wave filter to be
-  parallel-safe.  It does this by using mlt_frame_unique_properties(). Also, it
-  fixes a problem not properly processing a source image.
-
-  * src/modules/normalize/filter_volume.c: Refactor volume to use
-  mlt_frame_unique_properties().
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h: Add
   mlt_frame_unique_properties().
 
   src/modules/avformat/producer_avformat.c, src/modules/avformat/vdpau.c:
   Rename 'this' in avformat module.
 
-  * src/modules/frei0r/not_thread_safe.txt: Mark more frei0r filters not
-  thread-safe.
-
-2011-03-01  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix deadlock regression in
-  framebuffer producer.
-
-  * src/modules/frei0r/not_thread_safe.txt: Flag some frei0r filters as not
-  thread-safe.
-
-  * src/modules/sdl/consumer_sdl.c: Fix deadlock in sdl_preview.  This would
-  occur when trying to play from a paused state at the end of the project.
-
 2011-03-01  Till Theato <root@ttill.de>
 
   * src/modules/rotoscoping/filter_rotoscoping.c,
 
 2011-02-28  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/transition_luma.c: Fix integrity of luma transition when
-  parallel.
-
-  * src/modules/avformat/producer_avformat.c: Workaround incorrect duration on
-  some clips (kdenlive-2003).
-
-  * src/modules/avformat/producer_avformat.c: Fix regression in determination
-  of seekable.
-
   * src/framework/mlt_consumer.c, src/framework/mlt_deque.c,
   src/framework/mlt_events.c, src/framework/mlt_factory.c,
   src/framework/mlt_field.c, src/framework/mlt_filter.c,
   self in the framework.  This makes doxygen output better match the headers,
   and it improves life within a code-parsing IDE like Qt Creator.
 
-  * demo/demo.ini: Fixup demo.ini
-
-  * src/framework/mlt_geometry.c: Rename self to g in mlt_geometry.
-
-  * src/modules/avformat/producer_avformat.c: Fix compiler error on older
-  version of libavutil.
-
 2011-02-27  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Fix mlt_consumer_position when
-  encoding audio only.
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c: Add support for FFmpeg AVMetadata
   API.
 
-  * src/modules/avformat/producer_avformat.c: Fix compiler warning on
-  av_get_pix_fmt().
-
-  * src/modules/avformat/producer_avformat.c: Rewrite seekable check in
-  avformat.  Now, alsa input works: melt -profile dv_pal alsa:default 
-  video4linux with alsa: melt -profile quarter_15 video4linux2:/dev/video1 \
-  -track alsa:default -transition mix  And files over HTTP can handle seeking.
-
-2011-02-27  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: Add parameters
-  feather and feather_passes. Feathering is done by bluring the map containing
-  the masked area.
-
-2011-02-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/frei0r/blacklist.txt: Remove frei0r.facedetect from black list.
-
-  * src/modules/frei0r/not_thread_safe.txt: Mark frei0r.cluster as not
-  thread-safe.
-
-  * src/modules/frei0r/factory.c: Fix small memory leak each a frei0r plugin is
-  instantiated.
-
-2011-02-25  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Add support for pix_fmt on
-  avformat resource URL.  For example,
-  libdc1394:/dev/raw1394?frame_rate:15\&pix_fmt:yuv422 makes a Firewire digital
-  camera (not DV camcorder) on Linux work.
-
-  * src/modules/avformat/producer_avformat.c: Add support for avdevice video
-  channel selection.  For example, video4linux2:/dev/video0?channel=2 sets the
-  input to S-
-
-  * setenv: fix setenv
-
-2011-02-24  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_transition.c: Support forever transitions (in and out not
-  supplied).
-
-  * src/modules/core/filter_rescale.c: Add 'factor' property to scale filters. 
-  Under certain conditions it can be desirable to manually change the
-  resolution. Caution: one can still not use this in a completely generic way
-  with this change.  For example, in a realtime playout situation, one can
-  attach swscale with factor=0.25, followed by frei0r.cluster, followed by
-  swscale again with no properties. The first swscale will downscale the image
-  for the heavy cluster filter. The last swscale will upscale it to make the
-  rest of the project components happy.
-
 2011-02-20  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/frei0r/Makefile, src/modules/frei0r/factory.c,
   src/modules/frei0r/frei0r_helper.c, src/modules/frei0r/not_thread_safe.txt:
-  Mark some frei0r plugins as not thread safe.
-
-2011-02-20  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: number of points
-  can now change from keyframe to keyframe. Result may be unexpected though.
-  Additionally some cleanup
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: rename mode
-  "matte" to "luma" Additionally prevent serialization of internal parameters
-
-2011-02-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix video4linux in avformat
-  producer.  melt video4linux2:/dev/video0
-
-  * docs/install.txt, docs/mlt-xml.txt, docs/services.txt, setenv: Remove info
-  about mainconcept and bluefish services.
-
-  * src/framework/mlt_producer.c, src/framework/mlt_producer.h,
-  src/modules/core/producer_consumer.c, src/modules/core/producer_hold.c,
-  src/modules/core/producer_noise.c, src/modules/frei0r/factory.c,
-  src/modules/motion_est/producer_slowmotion.c: Add profile parameter to
-  mlt_producer_new.
-
-  * src/framework/mlt_service.c: Check pointer passed to mlt_service_profile.
-
-  * src/modules/core/producer_colour.c: Fix aspect ratio of color producer.
-
-  * configure: Add --enable-debug option.
-
-2011-02-19  j-b-m <jb@kdenlive.org>
-
-  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
-  Store exif orientation.  Patch attached internally stores the exif
-  orientation so that it can be accessible to the framework and apps using it. 
-  Useful it in Kdenlive to correctly rotate images when creating proxy images.
-
-2011-02-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/motion_est/Makefile: Fix lib suffix on motion_est.
-
-2011-02-16  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_audio.c: Disable purging consumer on seek in
-  sdl_audio.  Due to misbehaving on parallel-consumer.
-
-2011-02-16  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: Use
-  "property-changed" event to find out when to parse the spline
-
-2011-02-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl.c: Playout remaining frames in sdl at
-  end-of-stream.
-
-  * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
-  src/modules/sdl/consumer_sdl_preview.c: Fix deadlocks in sdl_preview with
-  parallel-consumer.
-
-2011-02-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/transition_composite.c: Fix image skew bug in composite
-  (kdenlive-1923).
-
-  * src/modules/core/transition_luma.c: Fix deinterlace when luma is inverted
-  (kdenlive-1953).
-
-2011-02-07  j-b-m <jb@kdenlive.org>
-
-  * src/modules/plus/transition_affine.c: Make offset in affine transition
-  keyframable.
-
-2011-02-05  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: fix mode alpha
-  not working with image format rgb24a
-
-2011-02-03  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping: prevent possible
-  crash
-
-2011-01-31  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/producer_consumer.c: Copy the alpha channel in
-  producer_consumer.
-
-2011-01-30  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Improve efficiency of memory copy
-  in avformat consumer.  Patch from Paul Flinders <paul@flinders.org>.
-
-  * src/modules/avformat/producer_avformat.c: Be pessimistic about the duration
-  (kdenlive-1962).  Some clip formats give a slightly longer duration estimate,
-  and MLT does not handle that well especially in some non-interactive use
-  cases like transcoding and automated processing.
-
-2011-01-27  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/gtk2/Makefile: Link pango producer with libiconv on Mac OS X.
-
-2011-01-27  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/Makefile, src/modules/rotoscoping/factory.c,
-  src/modules/rotoscoping/filter_rotoscoping.c,
-  src/modules/rotoscoping/filter_rotoscoping.yml: Rotoscoping: Set default mode
-  to alpha and add YAML filter description
-
-2011-01-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Do not round up the duration
-  (kdenlive-1962).
-
-  * src/modules/avformat/producer_avformat.c: Fix pausing on vdpau with
-  noimagecache.  Also uses AVFrame we already have instead of local AVPicture.
-
-  * src/modules/avformat/producer_avformat.c: Make seeking to first frame more
-  reliable.
-
-2011-01-25  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl.c: Increase default SDL audio buffer to
-  prevent crackling.
-
-  * src/framework/mlt_consumer.c: Make worker thread handle tracking more
-  portable.
+  Mark some frei0r plugins as not thread safe.
 
-2011-01-25  Till Theato <root@ttill.de>
+2011-02-19  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: another small
-  cleanup
+  * docs/install.txt, docs/mlt-xml.txt, docs/services.txt, setenv: Remove info
+  about mainconcept and bluefish services.
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: cleanup
+  * src/framework/mlt_producer.c, src/framework/mlt_producer.h,
+  src/modules/core/producer_consumer.c, src/modules/core/producer_hold.c,
+  src/modules/core/producer_noise.c, src/modules/frei0r/factory.c,
+  src/modules/motion_est/producer_slowmotion.c: Add profile parameter to
+  mlt_producer_new.
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: Mode matte
-  should also work in yuv420p (untested since forcing a conversion from yuv422
-  does not work)
+2011-02-19  j-b-m <jb@kdenlive.org>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: only the mode
-  rgb requires a specific colorspace
+  * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
+  Store exif orientation.  Patch attached internally stores the exif
+  orientation so that it can be accessible to the framework and apps using it. 
+  Useful it in Kdenlive to correctly rotate images when creating proxy images.
 
-2011-01-24  Till Theato <root@ttill.de>
+2011-02-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: Save the the
-  json object so we do not have to parse the parameter at every processing but
-  only when it changed
+  * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
+  src/modules/sdl/consumer_sdl_preview.c: Fix deadlocks in sdl_preview with
+  parallel-consumer.
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: use mlt_pool
+2011-01-27  Till Theato <root@ttill.de>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: rename "mask"
-  mode to "matte"
+  * src/modules/rotoscoping/Makefile, src/modules/rotoscoping/factory.c,
+  src/modules/rotoscoping/filter_rotoscoping.c,
+  src/modules/rotoscoping/filter_rotoscoping.yml: Rotoscoping: Set default mode
+  to alpha and add YAML filter description
 
 2010-11-23  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/plus/filter_affine.c: Reduce service lock contention in affine
-  filter.
-
   * src/modules/frei0r/filter_frei0r.c, src/modules/frei0r/frei0r_helper.c,
   src/modules/frei0r/frei0r_helper.h, src/modules/frei0r/producer_frei0r.c,
   src/modules/frei0r/transition_frei0r.c: Reduce service lock contention in
   frei0r module.
 
-2010-11-04  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Fix race condition on frame pointer in
-  parallel consumer.
-
-2010-10-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Fix multiple workers getting the same frame.
-
 2010-10-04  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   then it may be better to not use realtime mode and permit audio
   discontinuity.
 
-  * src/framework/mlt_types.h: Add a MLT_FRAME() cast.  And white-space align
-  the casts.
-
   * src/framework/mlt_deque.c, src/framework/mlt_deque.h: Add mlt_deque_peek()
   with index.
 
-2010-06-15  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Remove audio processing from the worker
-  threads.  This has a bad interaction with the avformat producer, which
-  contains a buffer of unused decoded samples. This shifts audio processing to
-  the main consumer thread, which is often light anyways. I recommend to set
-  the threads property to 2 or more on the avformat consumer to offload video
-  encoding to separate threads from the audio processing and encoding.
-
-  * src/modules/xine/filter_deinterlace.c: Make YADIF reentrant.
-
-  * src/framework/mlt_consumer.c: Fix regression frames out-of-order.
-
-  * src/framework/mlt_consumer.c: Fix compiler warning on this enum.
-
 2010-06-14  Dan Dennedy <dan@dennedy.org>
 
-  * src/framework/mlt_consumer.c: Change this log message back to debug level.
-
   * src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
   src/framework/mlt_tractor.c, src/modules/core/filter_imageconvert.c,
   src/modules/sdl/consumer_sdl.c: Fix image format consistency and conversion.
   tractor service locking.  This completely inhibited parallelism, but removing
   it also exposes more race conditions that require resolution.
 
-  * src/framework/mlt_consumer.c: Add work queue to the parallel consumer. 
-  This removes get_frame calls from the worker threads. The get_frame call must
-  take a service lock and that creates contention between the threads.
-
-  * src/modules/xine/filter_deinterlace.c: Add service locks around yadif
-  context.
-
-2010-04-15  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_consumer.c: Change this log message to debug level.
-
 2010-03-04  Dan Dennedy <dan@dennedy.org>
 
   * .../motion_est/filter_autotrack_rectangle.c,
   src/modules/qimage/producer_qimage.c, src/modules/sox/filter_sox.c,
   src/modules/vorbis/producer_vorbis.c: Add service locks for parallelism.
 
-  * src/modules/sdl/consumer_sdl_preview.c: Pass real_time, buffer, and prefill
-  properties onto normal sdl consumer.
-
-  * src/modules/sdl/consumer_sdl.c: Log dropped frames at info log level.
-
   * src/modules/avformat/filter_avresample.c,
   src/modules/avformat/filter_swscale.c,
   src/modules/avformat/producer_avformat.c,
   RGB filters and transitions from frei0r and burningtv are still not safe
   enough.
 
-  * src/framework/mlt_tractor.c: Set the proper size of "image" where known.
-
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h: Add parallelism
   to mlt_consumer.  To use set real_time greater than 1 for frame-dropping or
   less than -1 for no frame-dropping. It works better with a liberal buffer
 
 2011-01-23  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/qimage/producer_qimage.c: Fix build outside MinGW.
-
-  * src/modules/jackrack/configure: Fix getting LADSPA include dir from
-  listplugins.
-
   * configure, src/framework/mlt_version.h: Move to an interim version number.
 
 2011-01-17  Dan Dennedy <dan@dennedy.org>
 
-  * src/examples/Makefile: Make this example use the mlt++ pkg-config.  This
-  more accurately demonstrates how to build a C++ app against mlt++.
-
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_still.c: SDL
   tweaks for Windows discovered when embedded.
 
 
 2010-12-31  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/swfdec/Makefile: Fix swfdec build on MinGW.
-
   * src/modules/xml/consumer_xml.c, src/modules/xml/producer_xml.c: Cleanup
   libxml changes for MinGW.
 
 
 2010-12-30  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sox/configure: Fix sox build on MinGW.
-
-  * src/modules/frei0r/factory.c: Fix frei0r build on MinGW.
-
   * src/modules/xml/consumer_xml.c, src/modules/xml/producer_xml.c: Fix libxml2
   build on MinGW.
 
   * src/melt/Makefile, src/melt/io.c, src/melt/melt.c,
   src/modules/sdl/consumer_sdl.c: Fix SDL and keyboard input on Win32.
 
-2010-12-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/Makefile: Fix build of mingw branch on Linux.  Fixing this
-  here prior to merging into master.
-
 2010-12-03  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/framework/Makefile, src/melt/Makefile, src/melt/io.c,
 
 2011-01-23  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.6.2.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h: Set version
   to 0.6.2.
 
-  * NEWS: Add v0.6.2 release notes.
-
-2011-01-22  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: add parameter
-  alpha_operation with possible values: clear, max, min, add, sub
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: Fix not every point
-  calculated for the spline was used
-
-2011-01-21  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: - Rename
-  parameter polygon to spline - Add parameter precision setting the maximum
-  distance between two points when calculating the spline - some cleanup
-
-2011-01-20  Till Theato <root@ttill.de>
-
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: Use cubic Bezier
-  spline instead of simple polygon to define masks
-
-2011-01-16  j-b-m <jb@kdenlive.org>
-
-  * src/modules/plus/transition_affine.c: Add always_active property to affine
-  transition.
-
 2011-01-16  Till Theato <root@ttill.de>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: Add parameter
-  invert
-
   * src/modules/rotoscoping/Makefile, src/modules/rotoscoping/cJSON.c,
   src/modules/rotoscoping/cJSON.h,
   src/modules/rotoscoping/filter_rotoscoping.c: Rotoscoping: Add support for
 
 2011-01-15  Till Theato <root@ttill.de>
 
-  * src/modules/rotoscoping/filter_rotoscoping.c: rotoscoping filter: add modes
-  - rgb (everything but polygon black, default) - alpha (polygon alpha value =
-  255, the rest = 0) - mask (polygon white, the rest black)
-
   * src/modules/rotoscoping/Makefile, src/modules/rotoscoping/factory.c,
   src/modules/rotoscoping/filter_rotoscoping.c: Add rotoscoping filter (WIP):
   It hides everything not in the polygon defined by the vertices given through
 
 2011-01-11  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/plus/transition_affine.c: fix compiler warning
-
   * configure, src/mlt++/configure, src/modules/avformat/configure,
   src/modules/kino/endian_types.h, src/modules/kino/riff.cc,
   src/modules/qimage/configure, src/modules/sox/configure: Enable build on
   * src/modules/kino/Makefile, src/modules/qimage/Makefile: Use CXX rather than
   CC for linking C++ (3090682)
 
-  * src/swig/python/build: Fix underlinking python binding (3082761).  Link the
-  python binding library to MLT and Python needed on some systems like
-  OpenSUSE.  Patch by Cristian Morales Vega
-
   * src/modules/sdl/consumer_sdl_audio.c,
   src/modules/sdl/consumer_sdl_preview.c: Fix undefined bahavior in SDL module
   (3066195).  The standard says the post-increment can have effect at any point
   the behavior of "this->refresh_count = this->refresh_count ++" is undefined. 
   Patch by Cristian Morales Vega
 
-  * src/modules/plus/filter_affine.c: Add use_normalised to affine filter.
-
-  * src/modules/plus/transition_affine.c: Fix some regressions in affine. 
-  Crashing on null rescale.interp and still some incorrect handling of sample
-  aspect ratios.
-
 2011-01-10  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/plus/interp.h, src/modules/plus/transition_affine.c: Add
 
 2011-01-10  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/linsys/20-linsys.rules: Remove NAME= from linsys udev rules.
-
   * configure, src/framework/mlt_version.h: Move to an interim version.
 
 2011-01-01  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: update ChangeLog for v0.6.0
-
-  * NEWS: Add v0.6.0 release notes.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt_version.h: set version
   to 0.6.0
 
-  * src/modules/avformat/configure: Set recommended FFmpeg version to 0.6.1.
-
-  * src/melt/melt.c: Update year in copyright notice.
-
-  * src/modules/core/transition_composite.c: Default to progressive rendering
-  in composite.  Field-based rendering is not sensitive to whether the
-  composite has motion and therefore produces ugly results for static things by
-  default. Field-based rendering can be explicitly requested on an animated
-  composite by setting the progressive property to 0.
-
-  * src/modules/feeds/NTSC/etv.properties: Scale the animation durations in
-  NTSC etv data feed.
-
   * src/modules/feeds/NTSC/etv.properties,
   src/modules/feeds/PAL/etv.properties: Make etv data feeds same and scalable
   between NTSC and PAL.
 
-  * src/melt/melt.c: Treat profile set by environment variable as explicit.
-
   * demo/mlt_attributes, src/modules/feeds/NTSC/data_fx.properties,
   src/modules/feeds/NTSC/etv.properties: Make feeds consistent between NTSC and
   PAL.  Fix mlt_attributes demo.
 
-  * src/melt/melt.c: Fix melt crashing due to many things depending on
-  consumer_aspect_ratio.
-
-  * src/modules/core/consumer_null.c: Fix segfault stopping unstarted null
-  consumer.
-
-  * src/modules/avformat/consumer_avformat.c: Increase video encoder output
-  buffer size.
-
   * demo/README, demo/mlt_slideshow, demo/mlt_slideshow_black: Convert
   "Scotland" in demos to "photos"
 
   * demo/svg.mlt, src/modules/xml/producer_xml.c: Fix parsing mixed XML
   documents and svg.mlt example.
 
-2010-12-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix an infinite loop encoding a
-  video with vorbis audio (kdenlive-1871).
-
 2010-12-27  Dan Dennedy <dan@dennedy.org>
 
   * src/mlt++/MltProducer.cpp, src/mlt++/MltProducer.h: Revert
   Producer::set_speed and add Producer::pause.  The new Producer::pause
   contains the wait for consumer-sdl-paused.
 
-2010-12-23  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/swfdec/producer_swfdec.c: Prevent concurrent access to swfdec
-  context.
-
-  * src/modules/swfdec/producer_swfdec.c: Add meta.media properties to swfdec.
-
 2010-12-22  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/plus/transition_affine.c: Fix shearing bug in affine transition
-  & filter.
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h: Add
   mlt_frame_write_ppm to visualize debugging.
 
-2010-12-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/decklink/Makefile: Fix build of decklink on some non-Linux
-  systems (BSD).
-
 2010-12-19  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_preview.c:
 
 2010-12-16  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/decklink/consumer_decklink.cpp: Fix cleaning up decklink when
-  stopped.
-
-  * src/mlt++/MltProducer.cpp: Fix regression in Producer::set_speed when
-  consumer stopped.  This was causing a deadlock in Kdenlive and any app that
-  calls set_speed when the consumer is stopped.
-
-  * src/modules/sdl/consumer_sdl_still.c: Fix race-induced intermittent crash
-  in sdl_still (kdenlive-1762).
-
   * src/framework/Makefile, src/framework/mlt.h, src/framework/mlt_version.c,
   src/framework/mlt_version.h, src/swig/mlt.i: Add mlt_version API. 
   Contributed by Jonathan Thomas.
 
 2010-12-15  Dan Dennedy <dan@dennedy.org>
 
-  * src/mlt++/MltProducer.cpp: Fix regression on return value of
-  Producer::set_speed.
-
   * src/mlt++/MltProducer.cpp, src/modules/sdl/consumer_sdl_preview.c:
   Synchronize Producer.set_speed(0) with sdl_preview.  This also helps prevent
   deadlock while waiting for consumer-sdl-paused event. Not 100% yet, but 100%
   variable to use within the handler - once it has support for event listeners
   that is.
 
-  * src/modules/sdl/consumer_sdl_preview.c: Prevent a possible deadlock when
-  pausing.
-
-2010-12-12  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/filter_freeze.c: Prevent always fetching the "frozen"
-  frame.  Instead of using cache, which causes flicker in previews.
-
-2010-12-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Fix crash when connecting the
-  sdl_preview to a new producer.  This occurs when you do not first stop the
-  consumer.
-
-2010-12-11  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Make melt handle failure to start consumer.
-
-  * src/modules/decklink/consumer_decklink.cpp: Fix tearing in decklink.  Also:
-  Adds a "preroll" property, which takes number of video frames. Prevent it
-  from deadlocking on a few dropped video frames in succession. Signal failure
-  to start when the profile is not compatible.
-
 2010-12-09  Dan Dennedy <dan@dennedy.org>
 
   * src/mlt++/MltProperties.cpp, src/mlt++/MltProperties.h: Added
   Mlt::Properties::wait_for(string).
 
-  * src/swig/mlt.i: Fix memory leak in swig on Properties::setup_wait_for.
-
-  * src/modules/linsys/consumer_SDIstream.c: Remove exit() from Linsys sdi
-  consumer.  Replace it with a consumer-fatal-error event.
-
   * src/framework/mlt_log.c, src/melt/melt.c,
   src/modules/avformat/consumer_avformat.c: Add consumer-fatal-error event to
   avformat consumer.  This addresses Kdenlive bug 1894. When the avformat
   src/framework/mlt_types.h, src/melt/melt.c, src/mlt++/MltConsumer.cpp,
   src/mlt++/MltConsumer.h: Add mlt_consumer_position (Mlt::Consumer::position).
 
-  * src/modules/sdl/consumer_sdl_preview.c: A minor refactoring.
-
-  * src/modules/sdl/consumer_sdl_preview.c: Add a consumer-sdl-paused event.
-
-  * src/modules/sdl/consumer_sdl_preview.c: Refactor end-of-stream and speed
-  change.
-
 2010-11-30  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/loader.dict: Load .xml file as MLT XML.
-
   * demo/mlt_swf_variables, demo/txtField.swf: Add example of using SWF with
   variables.
 
-  * src/modules/lumas/configure: Make --luma-compress imply --luma-8bit. 
-  Otherwise, we get unloadable 16-bit PNG.
-
-2010-11-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/swig/python/codecs.py: Add example of how to list of codecs.
-
-  * src/modules/avformat/consumer_avformat.c: Make the formats and codecs
-  available through properties.
-
-  * src/modules/avformat/producer_avformat.c: Fix reading uncompressed video
-  (bug 3121436).
-
-  * src/modules/avformat/vdpau.c: Make VDPAU decoding a tad more resilient.
-
-2010-11-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/swfdec/producer_swfdec.c: Add support for swfdec variables. 
-  The new 'variables' property takes a URL-encoded string, e.g.
-  variables="title=Hello World&subtitle=swfdec variables".
-
-2010-11-23  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Fix AVCHD detected as double frame rate.  The heuristic is
-  based upon fact that there is really no such thing as 50 or 59.94 _frames_
-  per second interlaced.
-
-2010-11-20  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/linsys/20-linsys.rules: Add suggested udev rules for Linsys
-  cards.
-
-2010-11-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/plus/transition_affine.c: Fix affine on non-square pixels
-  (kdenlive-1880).
-
-2010-11-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/swfdec/producer_swfdec.c: Refactor image conversion in swfdec.
-
-  * src/modules/frei0r/frei0r_helper.c: Add support for
-  F0R_COLOR_MODEL_BGRA8888
-
-2010-11-17  Till Theato <root@ttill.de>
-
-  * src/modules/gtk2/producer_pango.c: Fix crash in pango on very long strings.
-   Fix frame width and height get -1 when using producer pango with long
-  strings (large text files).
-
-2010-11-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl.c: Fix the size argument handling.
-
-2010-11-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Add locks around
-  avcodec_open/_close for thread protection.
-
-  * src/modules/avformat/producer_avformat.c: Fix regression on 1920x1088
-  clips.
-
 2010-11-07  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/swfdec/configure: Add configure script to detect optional
-  swfdec dependency.
-
-  * src/modules/swfdec/Makefile: Support build on swfdec 0.8 as well.
-
   * src/modules/core/loader.dict, src/modules/swfdec/Makefile,
   src/modules/swfdec/producer_swfdec.c: Add swfdec producer.  No audio or
   variables/parameters yet.
   src/modules/decklink/consumer_decklink.cpp: Add Blackmagic Design DeckLink
   consumer.
 
-2010-10-27  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/plus/transition_affine.c: Another apsect ratio fix in affine.
-
-  * src/modules/plus/transition_affine.c: Fix aspect- and size-related issues
-  in affine.
-
-2010-10-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Fix edit points when using auto-profile.
-
-  * src/modules/avformat/producer_avformat.c: Fix frame rate detection when the
-  muxer rate is 0/0.
-
 2010-10-20  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_tokeniser.c, src/modules/frei0r/frei0r_helper.c: Add
   support for frei0r string parameter.
 
-  * src/modules/avformat/filter_avcolour_space.c: Disable colorspace
-  normalization - not working yet.
-
-2010-10-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_property.c: Fkx crash converting string property with
-  null value.
-
 2010-10-17  j-b-m <jb@kdenlive.org>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
 
 2010-10-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/xml/consumer_xml.c: Do not serialize profile when consumer
-  profile is null.
-
-  * src/modules/avformat/producer_avformat.c: Fix regression using codec frame
-  rate.
-
-  * src/modules/xml/consumer_xml.c: Add null pointer checks around profile in
-  consumer xml.
-
   * src/melt/melt.c, src/modules/avformat/producer_avformat.c: Add colorspace
   to auto-profile.
 
   src/modules/avformat/producer_avformat.c: Fix version support for
   AVCodec:colorspace.
 
-  * src/modules/avformat/configure: Add --avformat-no-vdpau configure option.
-
-  * src/modules/core/filter_data_show.c: Add math header for lrint().
-
-  * src/modules/core/filter_data_show.c: Add #frame# variable substitution in
-  data_show filter.
-
-  * src/modules/core/filter_data_show.c: Fix timecode conversion with
-  non-integral framerate.
-
-2010-10-10  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/producer_consumer.c: Fix consumer producer not updating
-  frames in Kdenlive.
-
-2010-10-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Handle consumer properties that alter the profile.
-
-  * src/modules/core/producer_loader.c: Check for colorspace change on profile.
-
 2010-10-07  Dan Dennedy <dan@dennedy.org>
 
   * src/melt/melt.c, src/modules/core/producer_consumer.c,
   * src/framework/mlt_profile.c, src/framework/mlt_profile.h: Add
   mlt_profile_clone().
 
-2010-09-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/melt/melt.c: Use denominators as the litmus test for generating
-  profile.  This allows converting all producers to meta.media.width and
-  meta.media.height while not attempting to auto-profile the image producers,
-  which can potentially hold extremely large images and do not contain any
-  inherent frame rate. This also protects from potential divide by zero errors.
-
-  * src/melt/melt.c: Factor out usage help from main() processing.
-
-  * src/melt/melt.c: Factor out processing -consumer option.
-
-2010-09-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix some framerate-related issues
-  on playback.  Usage of stream->avg_frame_rate and seting aspect_ratio on
-  fallback.
-
-  * src/melt/melt.c: Fix crash on invalid and audio only clips.
-
-  * src/modules/avformat/producer_avformat.c: Improve some media attributes
-  detection.  These are for the new meta.media properties: square pixel
-  fallback, use new avg_frame_rate, converting 1088 to 1080.
-
 2010-08-28  Dan Dennedy <dan@dennedy.org>
 
   * src/melt/melt.c, src/modules/melt/producer_melt.c: Add an automatic profile
   explicitly choosing a profile different than the composition one should use
   the consumer producer. This just makes melt smarter and more automatic.
 
-  * src/modules/avformat/producer_avformat.c: Add immutable meta.media-prefixed
-  properties.  I am deprecating real_width, real_height, and source_fps in
-  favor of new properties prefixed by "meta.media." These are different than
-  the "meta.media.N.stream" and "meta.media.N.codec" properties because they
-  represent the selected tracks as well as some interpretation of the raw
-  AVFormat and AVCodec attributes in addition to reflecting "force_" overrides.
-  There is still many changes to make throughout to full remove real_width and
-  real_height. This change just adds what melt's new auto-profile feature needs
-  for most use cases.
-
-  * src/modules/core/producer_consumer.c: Do not let consumer producer alter
-  the profile when validating input.
-
   * src/modules/xml/consumer_xml.c, src/modules/xml/mlt-xml.dtd,
   src/modules/xml/producer_xml.c: Add (de)serialization of profile to XML.  In
   addition to the 'profile' element, one can also set the 'profile' attribute
   building without swscale. Fix compiling new colorspace stuff against FFmpeg
   <= v0.5. FFmpeg libs are increasing; only support contemporary header layout.
 
-2010-10-04  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix
-  TextColor+Outline+Typewriter=wrong color in titler (kdenlive-1829).
-
 2010-09-28  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_audio.c,
   Fix race conditions in SDL (kdenlive-1711).  Contributed patch by 'jem' -
   thanks!
 
-2010-09-28  j-b-m <jb@kdenlive.org>
-
-  * src/modules/sdl/consumer_sdl_still.c: Fix crash in SDL with new kdenlive
-  audio VU meter.  Below, a patch that fixes a crash in the SDL still consumer,
-  the bug was triggered by the recent audio monitor feature of Kdenlive. 
-  Basically, it just sets test_audio to 1 on the SDL still consumer frames.
-
 2010-09-26  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/filter_avcolour_space.c,
   profile) on frames.  Also, allow affirmatively setting luma to _not_ full
   range (force_full_luma=0).
 
-  * src/modules/kdenlive/producer_framebuffer.c: Fix indentation in
-  producer_framebuffer.c.
-
-  * src/framework/mlt.h: Add mlt_cache.h to set of all mlt headers.
-
-  * src/framework/mlt_frame.h: Document new colorspace and force_full_luma
-  frame properties.
-
-  * src/framework/mlt_tractor.c: Tractor needs to pass along new frame
-  properties.
-
-  * src/modules/dv/producer_libdv.c: Set libdv producer to Rec 601 colorspace.
-
   * profiles/atsc_1080i_50, profiles/atsc_1080i_5994, profiles/atsc_1080i_60,
   profiles/atsc_1080p_2398, profiles/atsc_1080p_24, profiles/atsc_1080p_25,
   profiles/atsc_1080p_2997, profiles/atsc_1080p_30, profiles/atsc_720p_2398,
   profiles/svcd_ntsc_wide, profiles/svcd_pal, profiles/svcd_pal_wide,
   profiles/vcd_ntsc, profiles/vcd_pal: Add colorspace to all profile presets.
 
-  * src/framework/mlt_profile.c: Parse colorspace profile property and add
-  hardcoded default.
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/producer_avformat.c: Rename variables and properties
   around luma range for clarity.  Frame property "force_full_luma" controls
 
 2010-09-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/filter_avcolour_space.c: Add conversion to profile
-  colorspace.
-
-  * src/modules/avformat/producer_avformat.c: Expand colorspace support to
-  explicit 601.
-
-  * src/modules/avformat/consumer_avformat.c: Set colorspace in codec context.
-
-  * src/framework/mlt_consumer.c: Map profile colorspace to consumer property.
-
-  * src/modules/avformat/producer_avformat.c: Remove hardcoded luma scaling and
-  passing skip_luma_scale to frame.  Luma scaling does not work and passing
-  skip_luma_scale can be done by setting set.skip_luma_scale on the producer.
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/producer_avformat.c: Rename yuv_std to colorspace.
 
 2010-08-24  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Require skip_luma_scale
-  explicitly <> 0.
-
   * src/framework/mlt_profile.h, src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/producer_avformat.c: Add input YUV colorspace (601 vs
   709) handling.  Still need to work on the output side including normalization
   non-scaling luma between YCbCr and RGB conversions as well as support for ITU
   Rec. 709 luma conversion for HD formats.
 
-2010-09-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Test the function pointer to be safe.
-
-  * src/modules/core/filter_crop.c: Remove an extra debug log message.
-
-  * src/modules/core/filter_crop.c: Fix crop making image black in a multitrack
-  (kdenlive-1814).
-
-2010-09-20  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_resize.c: Fix field order correction on cached
-  image.  When the avformat producer is using image caching, the field order is
-  top-field-first, and the consumer is paused then the field order correction
-  was applied to the cached image. As a result, when repeating the image due to
-  being paused, the active image would scroll down the frame. This fixes it by
-  copying to a new image instead of reusing the cached image.
-
-2010-09-19  Dan Dennedy <dan@dennedy.org>
-
-  * configure: Bump to interim version.
-
-2010-09-19  j-b-m <jb@kdenlive.org>
-
-  * src/modules/avformat/producer_avformat.c: Improve fps detection in avformat
-  producer.  I noticed MLT sometimes gives wrong fps info (I can send some demo
-  clips if required), for example it gives a 1000.0 fps on some mp4 clips.  In
-  december 2009, FFMpeg introduced avg_frame_rate that gives better results
-  than r_frame_rate which is currently used in producer_avformat.  Patch below
-  makes use of this new field when available which gives better results (my
-  mpeg4 clip now shows a 22.691 fps instead of 1000.
-
 2010-09-13  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.5.10.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.10.
 
-  * src/melt/melt.c: Update year in copyright notice.
-
-  * NEWS: Update release notes for v0.5.10
-
-  * src/modules/core/filter_crop.c: Fix bug with crop always asking for RGB
-  even when not cropping!
-
-  * src/modules/xine/yadif.c: Only build SSE2 version of YADIF on x86-64
-  (2984003).
-
 2010-09-12  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/modules/core/producer_loader.c: Enable filter avcolor_space
   on OS X.  It works now!
 
-  * src/modules/xine/deinterlace.c: Use linearblend as the C fallback to xine
-  deinterlacers.
-
-  * ChangeLog: Update ChangeLog for v0.5.8.
-
   * Doxyfile, NEWS, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.8.
 
-  * NEWS: Add v0.5.8 release notes.
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/core/filter_imageconvert.c: Enhance image conversion logging.
 
-  * src/modules/qimage/Makefile: Use linearblend as the C fallback to xine
-  deinterlacers.
-
-  * src/modules/avformat/producer_avformat.c: Validate that swscale supports
-  the resolution in avformat producer.
-
-  * src/modules/core/filter_crop.c: Fix bugs with odd width YUV processing.  By
-  preferring to crop on RGB and output an even width in case it eventually
-  needs to be converted to YUV, which is usually the case.
-
-2010-09-11  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Fix sometimes tight crop causes a green
-  line at bottom.
-
-  * src/modules/core/filter_imageconvert.c: Fix a stride and chroma-alignment
-  bug in imageconvert rgb->yuv.  Reported by Marco Gittler.
-
 2010-09-10  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/filter_crop.c, src/modules/core/filter_resize.c: Validate
   mlt_frame_get_alpha() that returns a size and mlt_frame_set_alpha()
   encapsulates handling of the alpha channel.
 
-  * src/modules/core/filter_imageconvert.c: Set the alpha channel size more
-  reliably in imageconvert.
-
-  * src/framework/mlt_frame.c: Base alpha channel on width and height.  Removes
-  scaled_width and scaled_height properties, which were typically redundant
-  with width and height, but less available. Besides, width and height better
-  reflect the image attributes to help keep the image and alpha channel in
-  sync.
-
-  * src/modules/xine/filter_deinterlace.c: Fix a segfault if one tries to use
-  deinterlace explicitly.
-
-2010-09-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix returning last bit of audio
-  samples from avformat.  Bug reported by Kevin MacPhail.
-
-2010-09-09  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: parent the svgrenderer, to
-  destruct on exit
-
-2010-09-08  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: load inline images
-
-2010-09-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/filter_swscale.c: Refix alpha channel scaling memory
-  leak (3060324).
-
 2010-09-07  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/consumer_avformat.c,
   src/modules/core/filter_imageconvert.c: Apply alpha on frame to rgba image
   (kdenlive-1786).
 
-  * src/modules/xine/filter_deinterlace.c: Fix a regression in the yadif
-  deinterlace filter.  Now that it properly checks if the previous frame
-  progressive after getting its image, when progressive, it was returning the
-  previous frame's image for the current frame!
-
-2010-09-04  Till Theato <root@ttill.de>
-
-  * src/modules/plus/filter_affine.c: Fix filter affine stopping to work at
-  frame 15000.  Additionally fix problems with in point > 0 (Kdenlive-1782).
-
-2010-09-03  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix field order on avformat
-  cached images.  Also, provide a field order override that is consistent with
-  other overrides (force_).
-
-  * src/modules/sox/filter_sox.c: Fix channel alignment in sox filter.  This
-  pointer swapping is somehow breaking the stereo imaging even though I can not
-  see why now. Anyways, it no longer support multiple effects, so it does not
-  matter.
-
-2010-09-02  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sox/filter_sox.c: Fix sox effect parameters.
-
-  * src/modules/avformat/producer_avformat.c: Automatically crop 8 bottom lines
-  of 1088 source.
-
-2010-09-01  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/normalize/filter_volume.c: Accept negative dB values for volume
-  filter.
-
-2010-08-31  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/normalize/filter_volume.c: Fix integrity of volume filter when
-  applying multiple instances.
-
-2010-08-30  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_luma.c: Fix positioning bugs in filter luma. 
-  Discovered while working on slideshow animation in Kdenlive.
-
-2010-08-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_still.c: Fix segfault in SDL observed in
-  Kdenlive.  Triggered by reloading a clip.
-
-  * src/modules/avformat/filter_swscale.c: Fix regression on scaling alpha
-  channel.  Regression introduced with usage of sws_getCachedContext not too
-  long ago.
-
-2010-08-28  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix audio decoding when AVPacket
-  has >1 frame.  This was most obvious on FLAC.
-
-  * src/modules/jackrack/filter_jackrack.c: Fix jackrack filter not working
-  without rack file.
-
-2010-08-23  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/filter_avcolour_space.c: Fix regression in
-  avcolorspace filter.
-
 2010-08-22  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/filter_swscale.c,
   src/modules/avformat/producer_avformat.c: Use caching for swscale contexts.
 
-  * src/modules/avformat/configure: Fix detecting VDPAU on dash-based systems. 
-  The script was using 'echo -e' which is not POSIX-compliant. The
-  recommendation is to use printf with string containing escape sequences.
-
 2010-08-21  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/consumer_avformat.c,
   FFmpeg builds that use runtime CPU detection. This should make things faster
   and it seems to be same quality as C routines.
 
-  * demo/mlt_slideshow2: Minor fix to mlt_slideshow2.
-
   * demo/mlt_slideshow2, src/modules/core/filter_luma.c: Enhance luma filter to
   work with animated filters.  Previously, in a slideshow the luma filter would
   apply the dissolve or wipe repeatedly over a slide. For example, with a slide
   video with the audio waveform. Currently, it only works on producers that
   also provide video.
 
-  * src/framework/mlt_frame.c: Improve audio waveform resault reliability. 
-  This scales the audio sample rate up to meet the requested image resolution,
-  16 KHz at a time.
-
-  * src/framework/mlt_frame.c: Fix potential segfault in
-  mlt_frame_get_waveform.  Also, reduce sample rate for better performance.
-
-  * src/framework/mlt_frame.c: Improve audio waveform quality.  This averages
-  over the pcm samples in each image column by adding a shade of gray. It also
-  draws a solid white base line for each channel.
-
 2010-08-18  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/mlt_frame.c, src/swig/mlt.i, src/swig/python/waveforms.py:
   stacked. Also, add a Python binding to this call to return 8-bit grayscale
   image as a Python string. Finally, add a Python example.
 
-2010-08-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_panner.c: Convert panner to use range [0, 1]. 
-  Instead of [-1, 1]. This works better with Kdenlive.
-
 2010-08-16  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/Makefile, src/modules/core/factory.c,
   front/rear fade and ganging (balance front and rear together or fade left and
   right together).
 
-  * src/modules/core/transition_mix.c: Fix ramping the mix level in mix
-  transition.  Without ramping the same mix level is applied across the samples
-  in the frame. The result is a stair-stepping effect. With ramping, the mix
-  levels are actually values _between_ frames and the mix factor gradually
-  changes from one level to the next across all of the samples in the frame.
-
 2010-08-15  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/filter_channelcopy.c: Only do channelcopy/swap if there is
-  valid work.
-
   * src/modules/core/factory.c, src/modules/core/filter_channelcopy.c: Add
   filter channelswap.  It is a permutation of channelcopy that can be used from
   channelcopy as well by setting swap=1.
 
 2010-08-14  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/filter_imageconvert.c: Make it easier to switch between
-  scaled and unscaled native colorspace converters.
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_swscale.c,
 
 2010-08-08  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sdl/consumer_sdl_still.c: Change SDL still consumer to use
-  RGBA.  Since frei0r filters are popular and use rgba, and also because
-  Kdenlive scopes request rgba, this will reduce the number of conversions.
-
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
   Make libexif include compatible with more systems/versions.
 
-  * src/modules/avformat/producer_avformat.c: Fix image cache hit updating
-  position state (kdenlive-1714).
-
-  * src/modules/xine/filter_deinterlace.c: Optimize some deinterlace filter
-  logic.  Prevents YADIF from fetching current frame image if previous frame
-  image is signalled progressive. Also, tells mlt_service to stop decorating
-  frame with previous and next frames when producer is determined to be
-  progressive or deinterlace is not requested.
-
 2010-08-07  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/core/transition_luma.c, src/modules/frei0r/transition_frei0r.c,
   src/modules/plus/transition_affine.c: Fix scaling method on B frames of some
   transitions.
 
-2010-08-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_tractor.c: Fix tractor to set conversion functions on
-  frames it generates.
-
 2010-08-04  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/consumer_avformat.c, src/modules/dv/consumer_libdv.c,
   src/modules/sdl/consumer_sdl_still.c: Move firing consumer-frame-show to
   after done with image.
 
-  * src/modules/gtk2/producer_pixbuf.c: Initialize processed var and skip if
-  NULL.
-
 2010-07-29  j-b-m <jb@kdenlive.org>
 
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
   src/modules/qimage/qimage_wrapper.cpp new file:  
   src/modules/qimage/readexif.h
 
-2010-07-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/frei0r/frei0r_helper.c: Fix memory corruption on any frei0r
-  plugin with color param.
-
-  * src/modules/frei0r/factory.c: Recognize new FREI0R_PATH env var. 
-  FREI0R_PATH was introduced in v1.2 of the frei0r specification.
-  MLT_FREI0R_PLUGIN_PATH still accepted for backwards compatibility.
-
 2010-07-20  j-b-m <jb@kdenlive.org>
 
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
   Fix exif rotation angle modified:   src/modules/gtk2/producer_pixbuf.c
   modified:   src/modules/qimage/qimage_wrapper.cpp
 
-  * src/modules/gtk2/producer_pixbuf.c: Support exif rotation with pixbuf
-  producer  modified:   src/modules/gtk2/producer_pixbuf.c
-
-  * src/modules/qimage/qimage_wrapper.cpp: Add support for auto rotation for
-  images with exif data The meta.attr.rotation property must be set to the exif
-  data to get the auto rotate effect. Only supported by qimage producer, not
-  with pixbuf currently... modified:   src/modules/qimage/qimage_wrapper.cpp
-
-2010-07-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix infinite loop on some audio
-  decode errors (kdenlive-1690).
-
 2010-07-14  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/modules/avformat/producer_avformat.c: Fix crash when
 
 2010-06-20  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.5.6.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.6.
 
-  * NEWS: Add v0.5.6 release notes.
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/avformat/factory.c: Fixup local ffmpeg build.  Set PIC compiler
   flag, make libavdevice optional, and set recommended version to 0.6 branch.
 
-2010-06-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/plus/filter_affine.c: Fix the relative position of affine
-  filter.
-
-2010-06-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/plus/interp.h: Fix affine interpolation reading outside image. 
-  This created image garbage along some edges.
-
-  * src/modules/plus/transition_affine.c: Fix max affine geometry size wrt
-  aspect.
-
-2010-06-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Revoke special handling for
-  vorbis.  It is no longer needed for Ogg and messes up WebM output.
-
 2010-06-15  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/linsys/consumer_SDIstream.c: Fix sdi sample count to be
-  recomputed on each iteration.
-
-  * src/modules/linsys/consumer_SDIstream.c: Provide sensible defaults for HD
-  SDI.  Also, now blanking may also be set to 0 or 1 to be consistent with
-  other boolean MLT properties.
-
   * src/modules/jackrack/filter_jackrack.c, src/modules/jackrack/plugin_desc.h:
   Fix a few compiler warnings in jackrack.
 
-2010-06-09  Dan Dennedy <dan@dennedy.org>
-
-  * .gitignore: Tell git to ignore swig-generated .cxx files.
-
-2010-06-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/plus/interp.h: Use rint instead of roundf to suppress compiler
-  warnings.
-
-  * src/modules/plus/transition_affine.c: Cleanup affine and fix a glitch that
-  may appear.
-
-  * src/modules/plus/transition_affine.c: Fix the repeat/mirror cycle to be
-  relative to start of transition.  Before, it was relative to start of
-  timeline, and this meant geometry animations would start at unpredictable
-  locations.
-
-  * src/modules/core/filter_obscure.c: Fix infinite loop when obscure blocking
-  <1.  Patch from Till Theato.
-
-2010-06-03  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/kdenlive/filter_boxblur.c: Make bloxblur faster and simpler. 
-  It no longer does YUV-RGB-YUV conversion; just operates in RGB.
-
-  * src/melt/melt.c: Fix superficial cpu usage with melt progress option (used
-  by Kdenlive).
-
 2010-06-02  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/plus/filter_affine.c, src/modules/plus/interp.h,
   src/modules/plus/transition_affine.c: Revise affine to use interpolation and
   sub-pixel positioning.
 
-2010-05-31  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/Makefile: Fix build on BSD with VDPAU (Alberto Villa).
-
-2010-05-30  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/configure: Fix compilation (Qt Xml linking)
-
-2010-05-28  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix compilation warning
-  undeclared av_get_pix_fmt().
-
-  * src/modules/frei0r/factory.c: Fix a memory leak registering frei0r
-  services.
-
-2010-05-20  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_osx.h: Fix build on non-OSX due to missing
-  parameter name.
-
 2010-05-18  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/sdl/consumer_sdl_osx.h, src/modules/sdl/consumer_sdl_osx.m: Fix
   src/modules/sdl/consumer_sdl_still.c: Fix leaking OS X Cocoa objects in SDL
   consumers.
 
-2010-05-16  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Enable flushing the encoder
-  buffers.  This improves reliability of encoding especially multithreaded x264
-  (remove ugly hack).
-
-  * src/modules/avformat/consumer_avformat.c: Fix deprecated function and
-  remove unused variable.
-
-  * src/modules/avformat/consumer_avformat.c: Multitrack audio encoding
-  continued.  This version changes the configuration and remapping. The number
-  of channels per output audio track is set using "channels.<N>" properties on
-  the avformat consumer, where <N> is a 0-based numeric representing the output
-  track. At this time, all tracks must share all other attributes such as
-  sample rate, codec, and bitrate.  As for the remapping, this attempts to
-  reuse the meta.map.audio... properties set on the producers as used with the
-  sdi consumer. One exception: to skip or silence channels at the beginning
-  tracks or in the middle, you must add additional map properties to the end of
-  the list to simulate these "gaps."
-
-2010-05-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Add multitrack audio encoding. 
-  This is a check point for the first working version. Changes are forthcoming.
-
 2010-05-07  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
 
 2010-05-02  Dan Dennedy <dan@dennedy.org>
 
-  * src/swig/perl/Makefile.PL: Remove hardcoded 32-bit arch in Perl binding
-  (2995474).
-
   * src/swig/csharp/build, src/swig/java/build, src/swig/lua/build,
   src/swig/perl/Makefile.PL, src/swig/perl/build, src/swig/php/build,
   src/swig/python/build, src/swig/ruby/build, src/swig/tcl/build: Fix missing
 
 2010-04-25  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Fix white artifacts in image
-  (2972137)  Also applies to Kdenlive bug 1509.
-
   * configure, src/modules/core/filter_resize.c: Fix bad stride in yuv422 due
   to non-even width requests.
 
 2010-04-19  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for v0.5.4.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.4.
 
-  * NEWS: Add v0.5.4 release notes.
-
   * src/framework/mlt_frame.c, src/modules/avformat/producer_avformat.c:
   Improve error handling on video decode failure (kdenlive-1553).
 
   version of libswcale.  Some early revisions of 0.7.1 would cause garbage on
   last column of image with non-even width.
 
-2010-04-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/producer_colour.c: Fix color producer not setting
-  real_wdith and _height.
-
-2010-04-15  Dan Dennedy <dan@dennedy.org>
-
-  * configure: --disable-mmx, --disable-sse should also disable sse2.
-
 2010-04-08  Dan Dennedy <dan@dennedy.org>
 
   * src/swig/configure, src/swig/csharp/build, src/swig/csharp/play.cs,
   number of audio channels, audio sampling rate, audio sample size. It does
   _not_ set the clock source or the number of buffers for audio and video.
 
-2010-04-06  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/producer_consumer.c: Bugfix memory leak with producer
-  consumer (2976110).  Also kdenlive bug 1197.
-
-  * src/modules/xine/filter_deinterlace.c: Better signal previous/next frames
-  not needed.
-
 2010-03-10  Dan Dennedy <dan@dennedy.org>
 
-  * NEWS: Fix version number in release notes :(
-
-  * ChangeLog: Update ChangeLog for v0.5.2.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.2.
 
-  * NEWS: Add v0.5.2 release notes.
-
   * src/modules/linsys/consumer_SDIstream.c,
   src/modules/linsys/sdi_generator.c, src/modules/linsys/sdi_generator.h:
   Improve performance of sdi consumer (patch from BCE).  consumer_SDIstream.c -
   * src/mlt++/Makefile, src/mlt++/MltFilteredProducer.cpp,
   src/mlt++/MltFilteredProducer.h: Fix MltFilteredProducer not building.
 
-2010-03-02  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Fix regressions playing all frames
-  at end (kdenlive-1207).
-
-  * src/modules/core/producer_loader.c: Fix recent regression on failure to
-  load file.
-
 2010-02-28  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/core/loader.ini: Make swscale the preferred rescale filter. 
-  Should be safe now since the default compile-time max resolution for
-  libswscale was increased to 5120 for non-ppc systems as of May, 2009. Also,
-  because I added the initialization and range tests.
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_swscale.c, src/modules/core/producer_loader.c:
   Add resolution as init arg to libswscale filters.
   * src/framework/mlt_frame.c, src/modules/effectv/filter_burn.c: Fix a couple
   of compile warnings.
 
-2010-02-27  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix crash on reading uncompressed
-  (rawvideo).
-
-  * src/modules/core/filter_rescale.c: Report scaling method in debug logging.
-
-  * src/modules/avformat/consumer_avformat.c: Fix offset to alpha component on
-  OS X.
-
 2010-02-25  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/core/producer_loader.c: Make FFmpeg the primary image converter
   if available.  Except on OS X.
 
-  * src/modules/avformat/factory.c: Fix avcolor_space alias.
-
-  * src/modules/effectv/filter_burn.c: Fix endianness of the palette in
-  burningtv.
-
-  * src/modules/sdl/consumer_sdl_preview.c: Fix playing all frames at end of
-  project (kdenlive-1207).
-
 2010-02-24  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/xine/Makefile, src/modules/xine/yadif.c: Fix build on
 
 2010-02-15  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for 0.5.0 release.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.5.0.
 
   * NEWS, src/modules/avformat/configure: Add v0.5.0 release notes.
 
-2010-02-14  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_frame.c: Fix mlt_sample_calculator returning negative
-  result.
-
-  * src/framework/mlt_cache.c: Simplify some of the cache locking and less
-  flip-flop.
-
-  * src/modules/avformat/producer_avformat.c: Add a reference to avformat
-  producer on the frame when cache miss.  Also adds some additional checks on
-  null pointers.
-
 2010-02-11  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/linsys/consumer_SDIstream.c,
   * src/modules/linsys/Makefile, src/modules/linsys/configure: Add
   --linsys-with-jpeg configure option.
 
-  * src/modules/linsys/factory.c: Change linssys_sdi consumer to just "sdi"
-
 2010-02-10  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Make avformat producer less
-  chatty in verbose mode.
-
   * profiles/atsc_1080i_50, profiles/atsc_1080i_5994, profiles/atsc_1080i_60,
   profiles/atsc_1080p_2398, profiles/atsc_1080p_24, profiles/atsc_1080p_25,
   profiles/atsc_1080p_2997, profiles/atsc_1080p_30, profiles/atsc_720p_2398,
   profiles/sdi_486i_5994, src/framework/mlt_profile.c: Revise Hz->fps in
   profiles and add more ATSC profiles.
 
-  * src/modules/avformat/vdpau.c: Look for libvdpau.so in /usr/lib64 as well.
-
-2010-02-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/xml/producer_xml.c: Add support for unspecified out points in
-  XML.
-
-  * src/framework/mlt_playlist.c: Add support for only negative out in
-  mlt_pplaylist_append_io.
-
-  * src/framework/mlt_producer.c: Add support for negative out in
-  mlt_producer_set_in_and_out.
-
-  * src/framework/mlt_playlist.c: Change -1 handling for in/out points to be
-  any negative value.
-
-  * src/modules/vorbis/producer_vorbis.c: Fix short forward seeking in vorbis
-  producer.
-
-  * src/modules/avformat/producer_avformat.c: Fix audio muxing when
-  downsampling >2 channels.  A side effect of this bug was a big memory
-  consumption. This occurs mostly commonly when using 5.1 audio sources such as
-  AVCHD or DVD and encoding to 44.1 KHz.
-
-2010-02-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_resize.c: Safer to use the image from get_image and
-  to compute the size.
-
-  * src/modules/avformat/producer_avformat.c: Fix crash in filter resize with
-  cached images (kdenlive-1330).  Also properly sets the top_field_first flag
-  on frames with cached image. Also adds the noimagecache property for
-  troubleshooting.
-
 2010-02-04  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Sometimes x264 is crashing on
-  single or first pass with multithreading.
-
-  * src/modules/core/producer_consumer.c: Fix progressive property on frames in
-  the consumer producer.  This also adds deinterlace_method and rescale
-  (method) properties to the producer so it can set those on its embedded
-  consumer.
-
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_audio.c,
   src/modules/sdl/consumer_sdl_preview.c: Default SDL to use the onefield
   deinterlace filter.  The previous default in the deinterlace filter was
   src/framework/mlt_service.h: Hide need_previous_next property from
   serialization.
 
-  * src/modules/avformat/producer_avformat.c: Fix setting resolution and format
-  in avformat image caching.
-
 2010-02-02  Dan Dennedy <dan@dennedy.org>
 
-  * configure: Add SSE2_FLAGS and --disable-sse2 to configure.  This is
-  required for YADIF assembler.
-
   * src/framework/mlt_filter.h, src/framework/mlt_frame.h,
   src/framework/mlt_service.c, src/framework/mlt_service.h: Add fetching
   previous and next frames in producers.  This is only enabled when the
   ANY filters applied to them, which is important for YADIF and telecide
   filters, which process before all other filters.
 
-  * src/framework/mlt_multitrack.c: Prefer the API over setting property.
-
-  * src/modules/avformat/producer_avformat.c: Fix force_progressive=0 on
-  avformat producer.
-
-  * src/modules/avformat/producer_avformat.c: Add image caching to avformat
-  producer.  This not only helps with very short seeking around a point
-  especially on AVCHD but also will help immensely with YADIF.
-
-2010-01-28  Dan Dennedy <dan@dennedy.org>
-
-  * Doxyfile: Sort members in doxygen docs.
-
-2010-01-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix segfault when using
-  audio_index=all on file with no audio.
-
-2010-01-23  j-b-m <jb@kdenlive.org>
-
-  * src/modules/oldfilm/filter_vignette.c: Fix vignette filter position 
-  modified:   src/modules/oldfilm/filter_vignette.c
-
-2010-01-22  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Round corners in titles for
-  rectangle borders (Patch from Till Theato) modified:  
-  src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-  * .../motion_est/filter_autotrack_rectangle.c: Fix typo in autotrack filter 
-  modified:   src/modules/motion_est/filter_autotrack_rectangle.c
-
 2010-01-21  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/producer_avformat.c, src/modules/avformat/vdpau.c: Let
 
 2010-01-19  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Make realtime (streaming)
-  avformat consumer less bursty.  Patch from PrimeTel PLC -
-  http://www.prime-tel.com
-
   * src/modules/avformat/configure, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.c: Add support for libavdevice
   (v4l/v4l2).  Thanks to hints from Volodymyr M. Lisivka. 
   src/modules/qimage/producer_qimage.c: Return and handle errors on failure to
   produce image (kdenlive-1312).
 
-  * src/modules/core/filter_resize.c: Fix incorrect comment about yuv422 only
-  in resize filter.
-
-2010-01-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix muxing when encoding with
-  x264 and B frames (2928953).
-
-  * src/modules/avformat/consumer_avformat.c: Remove deprecation warnings on
-  guess_format.
-
 2010-01-16  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Only report video encode error
-  when truly error result.
-
-  * src/modules/avformat/consumer_avformat.c: Add apre, fpre, and vpre
-  properties to avformat consumer.  These read ffmpeg preset files, which is
-  really handy for x264 encoding on the command line. They require the full
-  path to the file unlike the ffmpeg utility. apre is for audio, vpre is for
-  video, and fpre is for the format/muxer.
-
-  * src/framework/mlt_frame.c: Refactor mlt_sample_calculator to reuse
-  mlt_sample_calculator_to_now.
-
   * Doxyfile, src/framework/mlt_frame.c, src/framework/mlt_frame.h,
   src/framework/mlt_service.h: Add mlt_frame doxygen docs.
 
-2010-01-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix detection of aspect ratio of
-  DV in AVI.
-
-2010-01-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix A/V sync after seeking on
-  some files (2892086).
-
-2010-01-12  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/filter_freeze.c: Fix memleak in freeze filter -
-  Kdenlive issue 1379 modified:   src/modules/kdenlive/filter_freeze.c
-
 2010-01-10  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/producer_avformat.c,
   src/modules/xine/filter_deinterlace.c: Fix setting progressive property on
   repeated frames (kdenlive-1335).
 
-2010-01-09  gmarco <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: round outline pen
-
-2009-12-23  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: outline text possible (with
-  use of font-outline/font-outline-color)
-
 2010-01-06  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/oldfilm/filter_oldfilm.c,
   src/modules/oldfilm/filter_oldfilm.yml: user array with 100 values yml file
   updated
 
-  * src/modules/oldfilm/filter_oldfilm.c: unevendevelop effect
-
-2009-12-21  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix crash when opening a
-  kdenlive document with titles  modified:  
-  src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-2009-12-17  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/linsys/consumer_SDIstream.c: Add force_channels to sdi consumer
-  for troubleshooting.
-
-  * src/modules/avformat/producer_avformat.c: Fix crash at end of some files
-  with audio_index=all.
-
 2009-12-16  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sdl/consumer_sdl_still.c: This lock makes kdenlive start more
-  reliably in the debugger.
-
   * src/framework/mlt_service.c, src/framework/mlt_service.h,
   src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c: Add
   mlt_service_cache_purge and remove purge in mlt_service_close.  The avformat
   mlt_service_close can not purge the cache because frames may be closed after
   the producer.
 
-  * src/modules/avformat/producer_avformat.c: Redo avformat producer locking -
-  less off-and-on.
-
 2009-12-14  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/framework/mlt.h: Bump to unreleased version.
 
 2009-12-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sdl/consumer_sdl.c: Fix for when actual channels does not match
-  requested.  This typically only happens when using audio_index=all on the
-  avformat producer. This also adds a audio_offset property to the sdl consumer
-  to help with testing audio_index. It takes a numeric value in units of
-  channels over which to skip.
-
-  * src/modules/avformat/vdpau.c: Do not compile vdpau_close() until it can be
-  used.
-
   * src/modules/avformat/factory.c, src/modules/avformat/producer_avformat.c:
   Add producer variant avformat-novalidate.  The purpose of this is to increase
   the speed of loading playlists with known good files. Use with care. This
   tested thus far by modifying the output of consumer xml to change mlt_service
   from "avformat" to "avformat-novalidate".
 
-  * src/modules/avformat/producer_avformat.c: Fix audio_index=all when stream
-  not stereo.
-
-  * src/modules/avformat/vdpau.c: Fix segfault in vdpau_init when x11_display
-  not set.
-
-  * src/modules/avformat/producer_avformat.c: Some B.C.E. sample files need
-  more audio streams.
-
-  * src/modules/avformat/producer_avformat.c: Fix regression with addition of
-  mlt_cache.  This change would cause the producer to not fully initialize on
-  the first call to get_frame.
-
 2009-12-12  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/producer_avformat.c, src/modules/avformat/vdpau.c: Add
   to about 10 - 15 clips using VDPAU in the project at the moment until the
   avformat producer is changed to use mlt_cache.
 
-  * src/melt/melt.c: SDL must not close X11 while VDPAU is still using it.
-
   * src/framework/mlt_consumer.c, src/modules/sdl/consumer_sdl.c,
   src/modules/sdl/consumer_sdl_preview.c, src/modules/sdl/consumer_sdl_still.c:
   Make the SDL consumer cooperate with VDPAU.  This moves the SDL_Quit calls
   X11 Display pointer to the mlt_environment and the global SDL mutex to the
   consumer class.
 
-2009-12-10  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Add center_bias property to crop filter.
-
 2009-12-08  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for 0.4.10 release.
-
   * Doxyfile, NEWS, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.4.10 and update release notes.
 
-  * src/modules/core/filter_audioconvert.c: Fix audioconvert setting frame
-  audio on no conversion.  This was causing the existing audio to be released
-  and then telling mlt_properties to release the audio again with the old
-  pointer (double free).
-
   * configure, src/framework/mlt.h, src/modules/avformat/producer_avformat.c:
   Fix underlinking libm by removing math function.
 
 2009-12-07  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for 0.4.8 release.
-
   * Doxyfile, configure, docs/melt.1, src/framework/mlt.h: Set version to
   0.4.8.
 
-  * NEWS: Add v0.4.8 release notes.
-
   * src/modules/core/loader.ini, src/modules/core/producer_loader.c: Fix some
   cases image and audio formats not converting (kdenlive-1259).
 
-  * src/modules/core/transition_composite.c: Fix crash in
-  composite-on-composite (kdenlive-1315).
-
-2009-12-06  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix crash in x264 on second pass
-  of multi-threaded encoding.
-
-  * src/modules/avformat/consumer_avformat.c: Disable multi-threaded audio
-  encoding (not useful).
-
-  * src/modules/avformat/consumer_avformat.c: Fix encoding PCM on some recent
-  FFmpeg change (kdenlive 1282).  Also includes a little cleanup and extra
-  buffer overwrite protection.
-
-  * src/modules/avformat/consumer_avformat.c: Fix regression causing writing
-  beyond end of buffer (kdenlive 1282).  Anything with a PCM output is still
-  crashing including DV and WAV.
-
-2009-12-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/swig/ruby/build: Fix build (CFLAGS) of Ruby binding.
-
-2009-12-02  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix audio buffer overflow on
-  large resampling (2902193).
-
-  * src/modules/avformat/producer_avformat.c: Fix regression converting mono to
-  stereo.
-
-  * src/modules/core/filter_crop.c: Add center property to crop to
-  automatically fill frame.
-
-2009-12-01  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Fix distorting aspect ratio of images with
-  crop.  Unfortunately, this has the side effect of breaking the crop extents
-  of existing projects when crop was applied to an image or image sequence.
-  However, those projects were using a distorting version of crop and would
-  need to be revised anyways.
-
-  * src/modules/core/filter_crop.c: Add support for cropping RGB(A).
-
-  * src/modules/core/filter_resize.c: Only correct field order if the source is
-  interlaced.
-
-2009-11-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Re-Fix bounds checking of crop filter
-  (kdenlive-1148).
-
-  * src/modules/avformat/producer_avformat.c: Add force_fps property to
-  avformat producer.
-
-  * src/modules/frei0r/factory.c: Fix locating plugins in $HOME/.frei0r-1/lib
-  (2897195).
-
-  * src/modules/avformat/producer_avformat.c: Fix pointer of V plane for
-  yuv420p.
-
-  * src/modules/avformat/producer_avformat.c: Fix crash in avformat producer on
-  unusable file.
-
-  * src/modules/oldfilm/filter_vignette.yml: Fix validation and consistency
-  errors in vignette YAML.
-
 2009-11-29  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/oldfilm/filter_vignette.c,
   src/modules/oldfilm/filter_vignette.yml: use float for vignette effect fixed
   also bug in wrong y center
 
-2009-11-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/oldfilm/filter_vignette.yml: Fix broken vignette YAML.
-
-2009-11-29  Marco Gittler <g.marco@freenet.de>
-
   * src/modules/oldfilm/filter_vignette.c,
   src/modules/oldfilm/filter_vignette.yml: use extra paramters for vignette
   settings
 
-2009-11-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Add support for new libavcodec
-  decode functions.
-
-  * src/modules/avformat/producer_avformat.c: Fix seek on some AVCHD causing
-  infinite loop.  This detects when libavformat starts to consistently report
-  invalid PTS and then will disable Ivan's new_seek code. In the example file I
-  have this only happens when seeking backwards, which typically implies an
-  interactive use case (except when using framebuffer with speed < 0). Then, it
-  should still use the new_seek when simply apply an in point to allow for a
-  clean, accurate cut.
-
-2009-11-20  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix regression in audio only
-  output.
-
-  * src/modules/avformat/producer_avformat.c: Fix dropping samples on math
-  error (kdenlive 1219).
-
-2009-11-14  j-b-m <jb@kdenlive.org>
-
-  * src/modules/frei0r/filter_frei0r.c: Fix frei0r helper filter position (used
-  for keyframes)
-
-2009-11-13  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix typewriter start param
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Add an offset start param to
-  typewriter effect
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Get ready for typewriter
-  effect in titles
-
-2009-11-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/frei0r/factory.c: Some frei0r filters need to be initialized
-  before getting param info.
-
-  * src/modules/frei0r/factory.c: Some frei0r filters need to be initialized
-  before getting param info.
-
-2009-11-04  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix images hidden
-  (kdenlive-1247) Get ready for title effects (blur, shadow)
-
-2009-10-26  Dan Dennedy <dan@dennedy.org>
-
-  * .../motion_est/filter_autotrack_rectangle.c: Fix autotrack_rectangle with
-  negative origin (kdenlive 766).
-
-  * src/framework/mlt_frame.c: These get/set position calls are unnecessary.
-
-2009-10-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix short output when video
-  shorter than audio (kdenlive 1207).
-
-2009-10-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix audio distortion due to
-  supplying incorrect decode buffer size.
-
-  * src/modules/avformat/producer_avformat.c: Add dynamically resizing audio
-  buffer.
-
-2009-10-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix regression on video-only
-  files (kdenlive-1206).
-
-2009-10-13  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/filter_freeze.c: Fix freeze effect issues with
-  transitions (kdenlive 1192)  modified:   src/modules/kdenlive/filter_freeze.c
-
-2009-10-11  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Fix bounds checking of crop filter
-  (kdenlive-1148).
-
-  * src/modules/avformat/producer_avformat.c: Fix regression with mono audio
-  (kdenlive-1204).
-
 2009-10-10  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Add codec.frame_rate and drop the
-  profile/level meta properties.
-
-  * profiles/svcd_pal_wide: Fix the display aspect ratio of SVCD Widescreen
-  PAL.
-
   * configure, src/framework/mlt.h: Bump the version to 0.4.7.
 
-  * src/modules/linsys/consumer_SDIstream.c: Add audio channel mapping.  This
-  uses meta properties on the producer: meta.map.audio.<N>.channels=<integer>
-  meta.map.audio.<N>.start=<integer> where 8 > N >= 0. The consumer loops over
-  N, consumes meta...channels and outputs them from channel meta...start. The
-  channel index starts at 0. For example, if the first audio track of the clip
-  is stereo English and the second audio track is stereo French, then this will
-  swap them: $ melt someclip audio_index=all meta.map.audio.0.channels=2
-  meta.map.audio.0.start=2 meta.map.audio.1.channels=2 meta.map.audio.1.start=0
-  -consumer linsys_sdi.  However, the last pair of meta properties in this
-  example are actually optional. The algorithm outputs the remaining channels
-  at the start channel you specify. But since getting an unspecified property
-  yields 0, the last meta properties is unnecessary as well.
-
-  * src/modules/linsys/sdi_generator.c: Add MAX_AUDIO_STREAMS constant.
-
-  * src/modules/avformat/producer_avformat.c: Improve this log message.
-
-  * src/framework/mlt_tractor.c: Fix the tractor not passing meta properties to
-  its new frame.
-
   * src/modules/linsys/consumer_SDIstream.c,
   src/modules/linsys/sdi_generator.c: Convert some printfs to mlt_log.
 
   * src/modules/linsys/consumer_SDIstream.c,
   src/modules/linsys/sdi_generator.c: Cleanup unused parameters.
 
-  * src/modules/linsys/sdi_generator.c: Cleanup compiler warnings.
-
   * src/modules/linsys/consumer_SDIstream.c,
   src/modules/linsys/sdi_generator.c: Add support for >2 audio channels to
   Linsys SDI consumer.  This does not yet have any remapping support.
 
-2009-10-06  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Add support for audio_index=all.
-
-2009-09-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Convert audio structures to
-  arrays.  Also collect info about audio channels and streams.
-
-2009-09-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Factor out audio seeking and
-  decoding from the get_audio callback.
-
-2009-09-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Factor out video codec
-  initialization.
-
-  * src/modules/avformat/producer_avformat.c: Factor out audio codec setup from
-  audio index handling.
-
-  * src/modules/avformat/producer_avformat.c: Reduce usage of properties for
-  state.
-
 2009-10-07  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update changelog for 0.4.6 release.
-
   * AUTHORS, Doxyfile, NEWS, configure, docs/melt.1, src/framework/mlt.h: Set
   version to 0.4.6 and update release notes.
 
   configure option --avformat-svn-version.  Also update recommended version to
   Sept 15, 2009 and other cleanup.
 
-2009-10-05  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Framebuffer producer should
-  obey to the force_aspect_ratio value  modified:  
-  src/modules/kdenlive/producer_framebuffer.c
-
 2009-10-04  j-b-m <jb@kdenlive.org>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.cpp modified:  
   src/modules/qimage/producer_kdenlivetitle.c
 
-2009-09-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Improve exception handling in
-  consumer_avformat.
-
-2009-09-26  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: locale fix for decial numbers
-
-2009-09-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Improve exception handling in
-  consumer_avformat.
-
-2009-09-24  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Wait for and close AVCodec
-  threads at end.  Except when using x264 because it may crash at the end of
-  the second pass when using multiple threads. Also, cleanup another dual pass
-  log file that new versions of x264 creates.
-
-  * src/modules/avformat/consumer_avformat.c: Fix crash in logging warning
-  (2865906).
-
-2009-09-22  Dan Dennedy <dan@dennedy.org>
-
-  * src/swig/mlt.i: Fix swig building with some Python versions and possibly
-  more.
-
 2009-09-20  Dan Dennedy <dan@dennedy.org>
 
   * src/mlt++/MltField.cpp, src/mlt++/MltField.h, src/mlt++/MltProducer.cpp,
 
 2009-09-19  Dan Dennedy <dan@dennedy.org>
 
-  * src/mlt++/MltProperties.cpp, src/mlt++/MltProperties.h: Add Properties
-  constructor from opaque pointer.
-
-2009-09-15  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix crash when audio encode does
-  not yield frame (2859643).
-
-  * src/modules/avformat/consumer_avformat.c: Convert consumer_avformat message
-  to mlt_log API.
-
-2009-09-15  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix compatibility with older
-  Kdenlive titles: Kdenlive bug 1137 modified:  
-  src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-2009-09-15  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Remove the old location of the
-  first_pts calculation.
-
-  * src/modules/avformat/producer_avformat.c: Fix concurrency instability. 
-  (not related to new_seek)
-
-2009-09-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Relocate setting first_pts and
-  fix ffmpeg concurrency.
-
-2009-09-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Restore seeking to one second
-  before target.  Since Ivan Schreter's FFmpeg mpegts new-seek patches were
-  disabled, this is temporarily required for H.264 MPEG2-TS.
-
-2009-09-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Patch from Ivan Schreter to fix
-  seeking on AVCHD.  This is intended to improve seeking in general, but it not
-  ready for all formats. It can be explicitly enabled by setting the new_seek
-  property to 1. I added code to enable it by default for H.264 in MPEG-2
-  Transport Stream, but one can disable it by setting new_seek to 0. 
+  * src/mlt++/MltProperties.cpp, src/mlt++/MltProperties.h: Add Properties
+  constructor from opaque pointer.
 
 2009-09-15  Dan Dennedy <dan@dennedy.org>
 
-  * src/mlt++/MltFrame.cpp: Remove construction of unused properties object.
-
   * src/swig/Makefile, src/swig/java/build, src/swig/lua/build,
   src/swig/perl/build, src/swig/php/build, src/swig/python/build,
   src/swig/ruby/build, src/swig/tcl/build: Fix distclean make target under swig
   existing loader filter, which uses the name by which it is invoked to toggle
   the behaviour of whether to attach normalizing filters.
 
-2009-09-12  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix framebuffer producer
-  preventing image conversion and crop.
-
-  * src/modules/qimage/configure: Fix kde_libdir detection for qimage (patch
-  2151852).  Patch from Roberto Castagnola <roberto.castagnola@gmail.com>. In
-  particular, Gentoo users have needed this.
-
 2009-09-10  Dan Dennedy <dan@dennedy.org>
 
   * Makefile, src/swig/Makefile, src/swig/configure: Improve swig build with
   help from Michael Forney.
 
-2009-09-09  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/transition_composite.c: Restore performance
-  characteristics of recent composite fix.
-
-  * src/modules/core/transition_composite.c: Fix composite regression with no
-  luma.
-
-  * src/modules/core/transition_composite.c: Fix abruptness when using a luma
-  with softness in composite.
-
-  * src/modules/sdl/consumer_sdl_audio.c: Fix big memory leak when scrubbing.
-
-2009-09-10  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix memleaks modified:  
-  src/modules/kdenlive/producer_framebuffer.c
-
-2009-09-09  j-b-m <jb@kdenlive.org>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix framebuffer flicker
-  modified:   src/modules/kdenlive/producer_framebuffer.c
-
-2009-09-08  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_audio.c: Cleanup pthread mutexes and
-  conditions.
-
-  * src/modules/core/filter_rescale.c: Fix core scaler regression. 
-
-2009-09-05  Dan Dennedy <dan@dennedy.org>
-
-  * src/swig/configure: Patch from Michael Forney to fix swig configure.  If
-  configure is run with --swig-languages="lang1 lang2", it complains because it
-  is compared to "all" without any quotes. 
-
-2009-09-03  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/xml/consumer_xml.c: Fix making paths relative (kdenlive-1111). 
-
-2009-09-01  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Don't crash when running
-  kdenlivetitle module from a console, instead print error message and exit
-  modified:   src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-2009-08-31  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix flicker frame appearing
-  at 0 position, small optimisations modified:  
-  src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix flicker frame appearing
-  at 0 position, small optimisations modified:  
-  src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-2009-08-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_pool.c: The padding is no longer necessary with the gcc
-  aligned attribute. 
-
-  * src/framework/mlt_pool.c: Chris Rudorff (ppc contributor) strongly suggests
-  16 byte alignment and padding for all arch. 
-
-  * src/modules/kdenlive/producer_framebuffer.c: Apply JBM's fix to framebuffer
-  regression on big image convert refactoring. 
-
-  * src/framework/mlt_pool.c: Apply mem alignment and corruption patches from
-  Christoph Rudorff while debugging ppc. 
-
-2009-08-29  gmarco <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: removed warning
-
 2009-08-26  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/sdl/consumer_sdl_audio.c: Convert audio-only SDL consumer to
-  new audio API. 
-
-  * src/modules/sdl/consumer_sdl_audio.c: Cleanup indentation 
-
   * src/modules/sdl/Makefile, src/modules/sdl/consumer_sdl_audio.c,
   src/modules/sdl/factory.c: Add audio-only SDL consumer (for Kdenlive on OS
   X). 
 
-  * src/modules/sdl/consumer_sdl_audio.c: Convert audio-only SDL consumer to
-  new audio API. 
-
-  * src/modules/sdl/consumer_sdl_audio.c: Cleanup indentation 
-
   * src/modules/sdl/Makefile, src/modules/sdl/consumer_sdl_audio.c,
   src/modules/sdl/factory.c: Add audio-only SDL consumer (for Kdenlive on OS
   X). 
   src/modules/linsys/consumer_SDIstream.c, src/modules/linsys/factory.c,
   src/modules/linsys/sdi_generator.c: Add Linsys SDI consumer from B.C.E. 
 
-2009-08-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Fix a/v sync on files with
-  incorrect codec frame rate, but correct muxer rate. 
-
-2009-08-16  j-b-m <jb@kdenlive.org>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Titler: add support for
-  background property modified:   src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Titler: add support for
-  background property modified:   src/modules/qimage/kdenlivetitle_wrapper.cpp
-
-2009-08-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_frame.c: Fix a/v synch drift with some unhandled
-  framerates (kdenlive-1034).  Previously only special handling provided for
-  32000, 44100, and 48000 sample rates on the strange NTSC frame rate. Patch
-  provided by Mike Adkins makes it generic including 24000/1001. Thanks! 
-
 2009-08-03  Dan Dennedy <dan@dennedy.org>
 
   * src/framework/Makefile, src/framework/mlt_consumer.c,
 
 2009-08-02  j-b-m <jb@kdenlive.org>
 
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Fix start / endviewport
-  movement, do not respect aspect ratio when resizing modified:  
-  kdenlivetitle_wrapper.cpp
-
   * src/modules/qimage/configure, src/modules/qimage/kdenlivetitle_wrapper.cpp:
   Add support for svg items in titles modified:   configure modified:  
   kdenlivetitle_wrapper.cpp
 
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Dont's set Graphicscene
-  parent to avoid warning message, fix display of images modified:  
-  kdenlivetitle_wrapper.cpp
-
-  * src/modules/qimage/kdenlivetitle_wrapper.h: remove unused var modified:  
-  kdenlivetitle_wrapper.h
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: Fix errors in caching + mem
   qimage producer modified:   kdenlivetitle_wrapper.cpp modified:  
   kdenlivetitle_wrapper.h modified:   producer_kdenlivetitle.c
 
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: Cache image if there is no
-  animation modified:   kdenlivetitle_wrapper.cpp
-
 2009-07-31  j-b-m <jb@kdenlive.org>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   add myself in copyright modified:   kdenlivetitle_wrapper.cpp modified:  
   kdenlivetitle_wrapper.h modified:   producer_kdenlivetitle.c
 
-2009-07-31  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: kdenlivetitle_wrapper.cpp: qt
-  4.4 fix for scale
-
-2009-07-31  j-b-m <jb@kdenlive.org>
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h: don't use cache, just normal
   properties to store scene modified:   kdenlivetitle_wrapper.cpp modified:  
   producers in one instance of Kdenlive modified:   kdenlivetitle_wrapper.cpp
   modified:   kdenlivetitle_wrapper.h modified:   producer_kdenlivetitle.c
 
-2009-07-27  gmarco <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: kdenlivetitle_wrapper.cpp:
-  fixed merge conflict
-
 2009-07-27  j-b-m <jb@kdenlive.org>
 
-  * src/modules/qimage/producer_kdenlivetitle.c: debug -- modified:  
-  producer_kdenlivetitle.c
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: Cleanup + fix crashes when used
   src/modules/qimage/kdenlivetitle_wrapper.h: Cleanup & fix crash modified:  
   kdenlivetitle_wrapper.cpp modified:   kdenlivetitle_wrapper.h
 
-2009-07-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/framework/mlt_playlist.c: Fix handling of length parameter in
-  mlt_playlist_remove_region.  This fixes kdenlive bug 1030. The calls to
-  mlt_playlist_split() inside this function appear to have forgotten that it
-  splits _after_ the specified position. 
-
-2009-07-26  j-b-m <jb@kdenlive.org>
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h: Cleanup & fix crash modified:  
   kdenlivetitle_wrapper.cpp modified:   kdenlivetitle_wrapper.h
 
-2009-07-25  j-b-m <jb@kdenlive.org>
-
-  * src/framework/mlt_playlist.c: Fix bug preventing removal of one frame
-  region modified:   mlt_playlist.c
-
-  * src/framework/mlt_playlist.c: Fix bug preventing deletion of one frame
-  region modified:   mlt_playlist.c
-
 2009-07-24  j-b-m <jb@kdenlive.org>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.cpp modified:  
   src/modules/qimage/producer_kdenlivetitle.c
 
-  * src/modules/qimage/producer_kdenlivetitle.c: Remove debug output
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: Fix crash + position in time
   src/modules/qimage/kdenlivetitle_wrapper.h modified:  
   src/modules/qimage/producer_kdenlivetitle.c
 
-2009-07-24  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: kdenlivetitle_wrapper.cpp:
-  use changed format of title-xml
-
-  * src/modules/qimage/qimage_wrapper.cpp: qimage_wrapper: removed unused line
-
-2009-07-24  j-b-m <jb@kdenlive.org>
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: Add feature to dynamically
 
 2009-07-24  Marco Gittler <g.marco@freenet.de>
 
-  * src/modules/qimage/factory.c: qimage/factory.c: readded deleted qimage
-  producer
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: kdenlivetitle: reindent code /
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h: reindent c++
 
-  * src/modules/qimage/producer_kdenlivetitle.c: reindent code
-
   * src/modules/qimage/factory.c, src/modules/qimage/qimage_wrapper.cpp:
   readded deleted qimage producer in factory
 
-2009-07-20  Marco Gittler <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: clean image before painting
-
-2009-07-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_still.c: Fix image refresh in sdl_still
-  consmuer. 
-
-  * src/melt/melt.c: Avoid redefining _GNU_SOURCE. 
-
 2009-07-19  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/qimage/configure, src/modules/qimage/producer_kdenlivetitle.c:
   kdenlivetitle: added QtXml during configure, add rescource to producer
 
-2009-07-18  gmarco <g.marco@freenet.de>
-
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: use start/end from kdenlive
-  titlefiles
-
 2009-07-18  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
 
 2009-07-14  Dan Dennedy <dan@dennedy.org>
 
-  * src/melt/melt.c: Add missing include for basename(). 
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/core/Makefile, src/modules/dgraft/Makefile,
   src/modules/dv/Makefile, src/modules/effectv/Makefile,
 
 2009-07-14  Marco Gittler <g.marco@freenet.de>
 
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: don't block under
-  qt-application (kdenlive)
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/producer_kdenlivetitle.c: cleanup
 
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: test alpha channel
 
-2009-07-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/Makefile: Fix underlinking avformat on some systems
-  (bug 2821055). 
-
-  * src/modules/sox/filter_sox.c: Apply sox 14.3 compatibility patch from Fathi
-  Boudra. 
-
 2009-07-11  Marco Gittler <g.marco@freenet.de>
 
   * src/modules/core/loader.dict, src/modules/qimage/kdenlivetitle_wrapper.cpp,
 
 2009-07-10  Marco Gittler <g.marco@freenet.de>
 
-  * src/modules/qimage/kdenlivetitle_wrapper.cpp: kdenlivetitle_wrapper: fixed
-  typo, not seen in Mac OS (QtXml also needed
-
   * src/modules/qimage/kdenlivetitle_wrapper.cpp,
   src/modules/qimage/kdenlivetitle_wrapper.h,
   src/modules/qimage/producer_kdenlivetitle.c: kdenlivetitle_wrapper: load
   function and contains the various conversion routines. The loader producer
   automatically attaches this filter to the producer it creates. 
 
-  * src/framework/mlt_profile.c: Slightly improve auto-setting
-  MLT_NORMALISATION. 
-
 2009-06-30  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog for 0.4.4 release. 
-
   * Doxyfile, NEWS, configure, docs/melt.1, src/framework/mlt.h: Set to v0.4.4
   and update release notes. 
 
-  * src/modules/sdl/consumer_sdl.c: Log failure to open audio. 
-
-2009-06-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Fix crash with invalid video_driver
-  property. 
-
-  * src/modules/gtk2/Makefile: Link gtk2 module against libiconv on FreeBSD. 
-
-2009-06-26  Dan Dennedy <dan@dennedy.org>
-
-  * src/swig/configure: Fix conditional swig build and remove --enable-swig. 
-
 2009-06-23  Dan Dennedy <dan@dennedy.org>
 
   * src/swig/configure, src/swig/lua/build, src/swig/lua/play.lua: Add SWIG Lua
   * src/melt/Makefile, src/melt/configure, src/melt/melt.c: Add configure
   option --rename-melt. 
 
-  * src/modules/avformat/producer_avformat.c: Fix crash in avformat producer on
-  audio overrun.  Fixes Kdenlive bug 754 and possibly others due to unchecked
-  bounds writing to an audio buffer. 
-
   * src/modules/frei0r/Makefile, src/modules/frei0r/blacklist.txt,
   src/modules/frei0r/factory.c: Add blacklist to frei0r module.  This is for
   Kdenlive bugs 913 and 917. It is populated with only facedetect for now. 
 
-  * src/framework/mlt_factory.c: Initialize the environment before the module
-  repo.  This lets module factory functions get info from mlt_environment(). 
-
 2009-06-21  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/avformat/Makefile.orig, src/modules/avformat/Makefile.rej:
   src/modules/avformat/consumer_avformat.c: Fix avformat consumer crashing on
   pcm_s16le. 
 
-2009-06-19  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/gtk2/Makefile: Fix underlink libm gtk2 module (floor). 
-
-  * src/modules/avformat/producer_avformat.c: Fix regression in 8bit audio
-  handling.  Regression occurred with migration to FFmpeg
-  av_audio_resample_init(). This also drops usage of non-public audio convert;
-  instead, relying upon new resample to do the same task. audioconvert.h is
-  still used, however, to get the sample format description. 
-
-2009-06-18  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sox/Makefile: Fix underlinking libm for sdl module.  Patch from
-  Debian. 
-
-  * docs/melt.1: Fix manpage whatis entry.  Patch from Debian. 
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix framebuffer producer to be
-  thread-safe. 
-
 2009-06-16  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/consumer_avformat.c: Migrate to FFmpeg
-  avformat_alloc_context(). 
-
   * src/modules/avformat/filter_avresample.c,
   src/modules/avformat/producer_avformat.c: Migrate to FFmpeg
   av_audio_resample_init. 
   src/modules/avformat/producer_avformat.c: Fix (kdenlive-824) >2 channels not
   downmixed. 
 
-  * src/modules/jackrack/Makefile: Fix underlinking jackrack plugin. 
-
 2009-06-15  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/kdenlive/producer_framebuffer.c: Fix big memory leak in
-  framebuffer producer.  This fix is for kdenlive bug 898. This was due to
-  allocating a frame in get_frame that might not get closed by a skipped call
-  to get_image. This skipping can happen when using realtime mode (frame
-  dropping). 
-
   * configure, profiles/Makefile, src/framework/Makefile, src/melt/Makefile,
   src/modules/avformat/Makefile, src/modules/core/Makefile,
   src/modules/feeds/Makefile, src/modules/lumas/Makefile,
   src/modules/oldfilm/Makefile, src/modules/xml/Makefile: Add datadir and
   mandir options to configure. 
 
-  * src/modules/qimage/configure: Fix building qimage when QtGui does not
-  include QtCore. 
-
-  * src/modules/gtk2/pixops.c: Fix compilation of gtk2 module. 
-
   * src/modules/kino/avi.cc, src/modules/kino/filehandler.cc,
   src/modules/kino/kino_wrapper.cc: Apply patch from Debian to fix compilation
   of kino module. 
 
-  * src/modules/gtk2/have_mmx.S: Apply patch from Debian to update have_mmx. 
-
-  * Makefile: Distributors do not like us to run ldconfig. 
-
-  * configure: Link with --no-undefined flag. 
-
-2009-06-13  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/consumer_avformat.c: Fix encoding to Ogg Theora with
-  Vorbis.  This applies to Kdenlive bug 465. After fixing the huge memory leak,
-  there was an audio sync problem, and the fix for that might help other
-  formats as well (fix was to initialize the audio codec time base). This also
-  increases the size of the audio encoding buffer to fix flac encoding. 
-
 2009-06-10  Dan Dennedy <dan@dennedy.org>
 
   * docs/melt.1, docs/policies.txt, src/melt/melt.c: Add man page for melt. 
   Not yet installed. 
 
-2009-06-07  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/transition_composite.c: Add invert boolean property to
-  composite transition. 
-
-2009-05-29  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/avformat/producer_avformat.c: Workaround video streams with
-  wild timestamps (kdenlive-854) 
-
 2009-06-03  Dan Dennedy <dan@dennedy.org>
 
-  * src/modules/avformat/producer_avformat.c: Add support for RGBA formats such
-  as QT Anim. 
-
   * configure, src/framework/mlt.h: Set to interim version 0.4.3 
 
-  * src/modules/core/filter_rescale.c: Improve alpha scaling conditional logic.
-
 2009-05-30  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update Changelog for 0.4.2 release. 
-
   * Doxyfile, NEWS, configure, src/framework/mlt.h: Bump versions and update
   release notes. 
 
   src/modules/oldfilm/filter_vignette.yml: Fix YAML validation errors and
   spelling of Vignette. 
 
-2009-05-28  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_crop.c: Improve performance of crop filter. 
-
-2009-05-27  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/core/filter_rescale.c: Bugfix (kdenlive-791) crash when using
-  crop filter.  The alpha channel was not getting scaled by gtkrescale (and
-  possibly others). I moved the core alpha scaling to a fallback position for
-  scalers that do not handle alpha channel. 
-
-  * src/framework/mlt_log.c: Change default log level to panic.  Some testing
-  against FFmpeg v0.5 shows logging is still verbose with warnings enabled, but
-  panic is better? 
-
-  * src/framework/mlt_log.c: Change default log level to warning or worse. 
-
-  * src/mlt++/configure: Fix typo in mlt++ CXXFLAGS. 
-
 2009-05-26  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp,
   Change the ttl default value for image sequences.  When using printf-style
   image sequences only, the default ttl is now 1. 
 
-2009-05-21  Dan Dennedy <dan@dennedy.org>
-
-  * src/modules/sdl/consumer_sdl.c: Bugfix sdl consumer not using
-  profile.progressive 
-
 2009-05-20  Dan Dennedy <dan@dennedy.org>
 
   * configure, src/framework/mlt.h: Bump to an interim version. 
 
-  * src/modules/motion_est/Makefile: Link motionest against libm. 
-
-  * src/mlt++/config.h: Fix license in comment header. 
-
 2009-05-17  Dan Dennedy <dan@dennedy.org>
 
-  * ChangeLog: Update ChangeLog 
-
   * Makefile, NEWS: Add v0.4.0 release notes. 
 
   * Doxyfile, configure, src/framework/mlt.h: Bump version to 0.4.0 
 
 2009-05-13  Dan Dennedy <dan@dennedy.org>
 
-  * src/mlt++/configure: Bump soversion for mlt++ due to removal of classes. 
-
   * profiles/atsc_1080i_50, profiles/atsc_1080i_60, profiles/atsc_1080p_2398,
   profiles/atsc_1080p_24, profiles/atsc_1080p_25, profiles/atsc_1080p_2997,
   profiles/atsc_1080p_30, profiles/atsc_720p_30, profiles/dv_ntsc,
   profiles/square_pal_wide, profiles/svcd_ntsc_wide, profiles/svcd_pal_wide:
   Make profile descriptions more user friendly. 
 
-  * src/modules/avformat/producer_avformat.c: Improve reliability of video
-  playback.  After the v0.5 release of FFmpeg, a change was introduced that
-  prevented reliable playback of some files, namely HDV. This fixes it by
-  introducing a seek upon opening the file. Also, this change provides simple
-  fallback support for when invalid DTS is returned by libavformat. 
-
 2009-05-11  Dan Dennedy <dan@dennedy.org>
 
   * src/modules/gtk2/have_mmx.S, src/modules/gtk2/scale_line_22_yuv_mmx.S:
   Apply patch from Orcan Ogetbil that adds .note.GNU-stack section. 
 
-  * setenv: Add libmlt++ to the ld path. 
-
-  * src/mlt++/configure: Make libmlt++ PIC. 
-
 2009-05-09  Dan Dennedy <dan@dennedy.org>
 
-  * configure: Fix build on Mac OS X. 
-
   * ChangeLog, Makefile: Change dist make target to use git-archive. 
 
   * src/swig/configure, src/swig/java/Play.java, src/swig/java/build,
   src/swig/ruby/play.rb, src/swig/ruby/thumbs.rb, src/swig/tcl/build,
   src/swig/tcl/play.tcl: Fixup the swig bindings. 
 
-  * src/modules/xine/xineutils.h: Fix compilation warning in xineutils.h. 
-
   * configure, src/examples/Makefile, src/framework/Makefile,
   src/framework/mlt_geometry.c, src/framework/mlt_producer.c,
   src/mlt++/Makefile, src/mlt++/configure, src/modules/avformat/Makefile,
   src/valerie/valerie_util.c, src/valerie/valerie_util.h: Remove files that no
   longer belong.
 
-2009-05-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/configure: Update avformat configure script to deal
-  with ffmpeg changes to swscale. 
-
-  * src/modules/sdl/consumer_sdl_still.c: Prevent potential divide-by-zero
-  errors in sdl_still consumer. 
-
-  * src/modules/avformat/ffmpeg.patch: Remove ffmpeg.patch - no longer
-  necessary. 
-
-  * Makefile: Fix uninstall of pkg-config files. 
-
-2009-05-05  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: Improve seek performance with
-  dnxhd and huffyuv codecs. 
-
 2009-05-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * configure, src/albino/Makefile, src/humperdink/Makefile,
   mlt is not possible, because of the wrong linking of -lmlt while using
   LDFLAGS=-L/usr/local/lib this patch fixes the issue using pkg-config"  
 
-2009-04-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: improve
-  audio synchronization after seek (including in point) 
-
 2009-04-18  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/resample/Makefile, src/modules/vorbis/Makefile: Apply patch
 
 2009-04-16  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/jackrack/plugin_mgr.c: Add /usr/lib64 libdir to default LADSPA
-  plugin path. 
-
   * configure, src/framework/mlt.h, src/modules/kino/configure: Use pkg-config
   instead of lqt-config. 
 
 2009-04-15  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * Doxyfile: Update version in Doxygen. 
-
   * mlt++/ChangeLog, mlt++/Makefile: Add ChangeLog and remove svn log from dist
   make target. 
 
-  * ChangeLog: update changelog 
-
-  * src/modules/avformat/configure: Fix build for --avformat-svn to use FFmpeg
-  v0.5 and HEAD build to not use --enable-swscale. 
-
   * ChangeLog, Makefile: Update ChangeLog and remove svn log from the make
   install target. 
 
   * NEWS, configure, src/framework/mlt.h, src/modules/avformat/configure: bump
   to version 0.3.8  
 
-2009-04-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.ini: fezzik.ini: workaround scaling resolution
-  limitation with swscale filter by making it the lowest priority 
-
-  * src/modules/kdenlive/producer_framebuffer.c: producer_framebuffer.c:
-  interpret negative speed as reverse 
-
 2009-04-10  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/test/play.cpp, mlt++/test/server.cpp: cleanup some warnings  
   mlt++/src/MltTractor.cpp, mlt++/src/MltTransition.cpp: Fix up warnings about
   explicit base initializers in copy constructors  
 
-  * mlt++/configure: Add more warnings  
-
-  * mlt++/.gitignore: Add a .gitignore file  
-
-2009-04-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  building on some older versions. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat: bugfix
-  (kdenlive-677) to make interlaced coding automatic if profile is not
-  progressive and coding not explicit by ildct and ilme properties. 
-
 2009-04-07  Ray Lehtiniemi <rayl@mail.com>
 
-  * src/modules/kdenlive/filter_boxblur.c: Fix a 64-bit segfault in kdenlive 
-  To reproduce: - create a new project - create a color clip - add clip to
-  timeline - set an in point on the clip - add the box blur effect  The
-  segfault happens because we take the negative of an unsigned integer. This
-  works out to a signed 32 bit value on a 64 bit platform, which causes the rgb
-  array bounds to be exceeded. 
-
   * src/framework/mlt_consumer.c, src/miracle/miracle_connection.c,
   src/modules/kino/riff.cc: Fix up a few ignored return values 
 
-  * src/framework/mlt_pool.c: Fix warning: pointer of type ‘void *’ used in
-  arithmetic 
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/core/filter_watermark.c, src/modules/core/transition_composite.c,
   src/modules/core/transition_region.c, src/modules/westley/producer_westley.c:
   src/valerie/valerie_response.c, src/valerie/valerie_response.h: Constness
   changes 
 
-  * .gitignore: Add a .gitignore file 
-
-2009-04-05  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/westley/producer_westley.c: producer_westley.c: Don't prepend
-  westley document root to empty properties 
-
-2009-04-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_crop.c: filter_crop.c: bugfix chroma alignment 
-
-2009-04-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/swig/ruby/thumbs.rb: thumbs.rb: fix setting size property for
-  avformat consumer 
-
-2009-03-17  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/frei0r/factory.c: frei0r/factory.c: add /usr/lib64 to the
-  default frei0r plugin path 
-
-2009-03-15  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: transition_composite.c: allow
-  removing of luma file by passing an empty name 
-
-2009-03-14  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: transition_composite.c: make luma
-  and luma_invert properties mutable 
-
 2009-03-10  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: add
-  backwards compatibility macro for PIX_FMT_YUYV422 
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_avdeinterlace.c,
   src/modules/avformat/filter_swscale.c: avformat: fix compilation due to
   recent PIX_FMT changes in libavutil v50. 
 
-2009-03-08  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c: producer_framebuffer.c: Fix
-  producer out position 
-
-2009-03-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_log.h: mlt_log.h: add convenience macros 
-
 2009-03-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kino/riff.cc: kino/riff.cc: suppress compiler warning 
-
   * src/modules/frei0r/factory.c, src/modules/frei0r/producer_frei0r.c:
   frei0r/factory.c, producer_frei0r.c: suppress compiler warnings 
 
-  * src/framework/mlt_property.c: mlt_property.c: suppress compiler warning 
-
-2009-02-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/producer_colour.c: producer_colour.c: improve previous
-  patch 
-
-  * src/modules/core/producer_colour.c: producer_colour.c: bugfix reading color
-  value after westley has prepended the document path to the resource property 
-
 2009-02-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_preview.c,
   * src/modules/vmfx/filter_chroma.c, src/modules/vmfx/filter_chroma_hold.c:
   filter_chroma.c: update to use new property-based color value 
 
-  * src/modules/vmfx/filter_chroma_hold.c: filter_chroma_hold.c: update to use
-  new property-based color value 
-
-  * src/modules/core/producer_colour.c: producer_colour.c: update to use new
-  property-based color parsing. 
-
-  * src/framework/mlt_property.c: mlt_property.c: interpret hex int as unsigned
-
-  * src/modules/frei0r/frei0r_helper.c: frei0r_helper.c: cleanup color parser
-  to use new code in mlt_property.c 
-
-  * src/framework/mlt_property.c: mlt_property.c: added parsing for color
-  values beginning with # 
-
 2009-02-20  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/frei0r/producer_frei0r.c: modules/frei0r: added missing
-  producer_frei0r.c -This line, and those below, will be ignored--  A   
-  producer_frei0r.c  
-
   * src/modules/frei0r/Makefile, src/modules/frei0r/factory.c,
   src/modules/frei0r/frei0r_helper.c: added frei0r producers (patch from jb)
   thx to jb  
 
 2009-02-14  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/plus/filter_affine.c: filter_affine.c: remove silly default
-  rotate animation for new kdenlive pan and zoom effect (kdenlive-565) 
-
   * src/modules/core/Makefile, src/modules/core/factory.c,
   src/modules/core/filter_crop.c, src/modules/fezzik.ini: filter_crop.c: add
   cropping filter (kdenlive-509) 
 
-  * configure: configure: relax optimization level slightly to improve debugger
-  backtraces in bug reports 
-
-  * src/modules/plus/transition_affine.c: transition_affine.c: bugfix chroma
-  alignment 
-
-2009-02-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_brightness.c: filter_brightness.c: fix the
-  wonkiness by filtering chroma as well. 
-
 2009-02-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * profiles/cif_15, profiles/qcif_15, profiles/quarter_15: profiles/*_15: add
   some 15fps profiles 
 
-  * src/modules/qimage/configure: qimage/configure: let qimage first attempt to
-  use Qt4 through pkg-config (canonical) without having to specify directories
-  or QTDIR 
-
-  * src/modules/sox/configure: sox/configure: give pkg-config priority over
-  libst-config 
-
 2009-02-10  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/qimage/configure: qimage/configure: fix build on OS X 
-
-  * src/modules/avformat/filter_avdeinterlace.c: filter_avdeinterlace.c: bugfix
-  (kdenlive-672) deinterlace only works on left half of image 
-
   * src/modules/qimage/producer_qimage.c,
   src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h:
   producer_qimage.c, qimage_wrapper.{h,cpp}: enhance qimage producer to use the
   new mlt_cache (kdenlive-575) 
 
-  * src/modules/gtk2/producer_pixbuf.c: producer_pixbuf.c: enhance pixbuf
-  producer to use new mlt_cache (kdenlive-575) 
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c,
   src/modules/vorbis/producer_vorbis.c: producer_vorbis.c, producer_avformat.c,
   mlt_factory.[hc], mlt.h: add mlt_cache and related service functions
   (kdenlive-575) 
 
-  * Doxyfile: Doxyfile: set tab width to 4 spaces 
-
-  * src/framework/mlt_properties.c: mlt_properties.c: update doxygen comments
-  for some out params 
-
-  * src/framework/mlt_property.c: mlt_property.c: update a doxygen comment to
-  label param as out 
-
 2009-02-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/debian/changelog, mlt++/debian/control, mlt++/debian/copyright,
   * configure, src/framework/mlt.h, src/modules/avformat/configure: bump to
   version 0.3.6 
 
-  * NEWS: NEWS: add release notes for 0.3.6 
-
-2009-02-01  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/frei0r/factory.c: frei0r/factory.c: add more default locations
-  for locating plugins including one for MacPorts 
-
-2009-01-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/inigo/inigo.c: inigo.c: make usage fit in 80 columns 
-
-2009-01-29  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/filter_swscale.c: filter_swscale.c: Fix compilation
-  (typo introduced in rev. 1330) 
-
 2009-01-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/fezzik/producer_fezzik.c: producer_fezzik.c: do not use the
-  swscale filter on images wider than 2048 loaded by the sdl_image producer. 
-
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/producer_qimage.c,
   src/modules/sdl/producer_sdl_image.c: producer_pixbuf.c, producer_qimage.c,
   producer_sdl_image.c: bugfix (kdenlive-575) large memory consumption loading
   many pictures. 
 
-  * src/modules/avformat/filter_swscale.c: filter_swscale.c: throw assert if
-  creation of swscale context fails. 
-
-  * src/modules/avformat/factory.c: avformat/factory.c: set ffmpeg logging to
-  the same level as MLT's 
-
-2009-01-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/gtk2/producer_pixbuf.c: producer_pixbuf.c: bugfix
-  (kdenlive-575) memory leak 
-
-  * src/modules/gtk2/producer_pixbuf.c: producer_pixbuf.c: bugfix
-  (kdenlive-575) memory leak 
-
 2009-01-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/swig/configure, mlt++/swig/php/build, mlt++/swig/php/play.php:
   swig/configure, swig/php/*: add php bindings 
 
-2009-01-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: add version
-  check to use AVCodec->long_name 
-
-2009-01-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: consumer_sdl.c: bugfix segfault on
-  unchecked pointer 
-
-  * src/modules/inigo/producer_inigo.c: producer_inigo.c: bugfix segfault on
-  unchecked pointer 
-
 2009-01-21  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * docs/inigo.txt: inigo.txt: update usage info 
-
-  * docs/policies.txt: policies.txt: add instruction to update version in
-  mlt.h\! 
-
   * src/framework/mlt.h, src/framework/mlt_consumer.c,
   src/framework/mlt_consumer.h, src/framework/mlt_deque.c,
   src/framework/mlt_deque.h, src/framework/mlt_events.c,
   Update copyrights to 2009. Add cross references from files to data structures
   in doxygen. 
 
-2009-01-14  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/inigo/inigo.c: inigo/inigo.c: add -debug and -verbose options to turn
-  on additional logging. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: set consumer
-  buffer prefill to 1 by default. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  (kdenlive-450) bad timestamps in MPEG-2 Transport Stream and possibly quite a
-  few other formats. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: add support
-  for an=1, vn=1, acodec=none, and vcodec=none options (kdenlive-533) 
-
 2009-01-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * docs/policies.txt: docs/policies.txt: Add policy about not using stdout,
-  messages, and recommending the new log API. 
-
   * src/framework/Makefile, src/framework/mlt.h, src/framework/mlt_consumer.c,
   src/framework/mlt_events.c, src/framework/mlt_log.c, src/framework/mlt_log.h,
   src/framework/mlt_pool.c, src/framework/mlt_producer.c,
   mlt_producer.c, mlt_pool.c, mlt_events.c, mlt_consumer.c, mlt.h, Makefile:
   add logging system based on FFmpeg's. 
 
-  * configure: configure: separate -march (suitable on x86) and -mcpu (suitable
-  on ppc, arm, and sparc) 
-
 2009-01-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * Doxyfile: Doxyfile: strip the path to the source files 
-
-  * src/modules/core/producer_consumer.c: producer_consumer.c: bugfix setting
-  in point 
-
   * src/framework/mlt_frame.h, src/framework/mlt_multitrack.c,
   src/framework/mlt_multitrack.h, src/framework/mlt_playlist.h,
   src/framework/mlt_service.h, src/framework/mlt_tractor.c,
   support special constructor argument values to list available demuxers and
   decoders: f-list[[,]acodec-list][[,]vcodec-list] 
 
-  * src/inigo/inigo.c: inigo/inigo.c: fix the usage help within 80 characters
-  wide. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: report list
-  of muxers when f=list and codecs when acodec=list or vcodec=list. 
-
-  * src/framework/mlt_repository.c: mlt_repository.c: report reason when dlopen
-  fails. 
-
 2009-01-05  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   mlt_filter.[ch], mlt_transition.[ch], mlt_consumer.[ch]: improve doxygen for
   filter, transition, and consumer 
 
-2009-01-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/configure: avformat/configure: add -lbz2 automatically
-  for --avformat-svn 
-
 2008-12-31  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * configure, src/modules/avformat/producer_avformat.c: producer_avformat.c:
   fix build on older versions of ffmpeg; whitespace cleanup by eclipse.  
 
-2008-12-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * Doxyfile: Doxyfile: bump version 
-
 2008-12-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * NEWS, configure: NEWS, configure: set version to 0.3.4 and add release
   notes 
 
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: further
-  analysis and testing reveals the DV encoder does not need the special aspect
-  ratio overrides. It expects a generic input. Only the DV decoder produces the
-  special, proper aspect ratios for which MLT is not yet prepared. 
-
 2008-12-28  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/swig/java/build, mlt++/swig/python/build, mlt++/swig/python/play.py,
   __stack_chk_fail_local. swig/python/play.py: fix syntax error reported by
   Jonathon Thomas. 
 
-2008-12-28  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sox/filter_sox.c: filter_sox.c: fix crash when trying to create
-  a sox filter with wrong name 
-
-2008-12-28  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/configure: avformat/configure: update the recommended
-  ffmpeg revision 
-
   * src/modules/avformat/producer_avformat.c,
   src/modules/core/filter_rescale.c, src/modules/core/producer_consumer.c,
   src/modules/dv/producer_libdv.c: filter_rescale.c, producer_avformat.c,
   producer_libdv.c, producer_consumer.c: coerce a deinterlace when scaling an
-  interlaced source. 
-
-2008-12-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt-config-template: mlt-config-template: send deprecation warning to
-  stderr to prevent breaking legacy scripts and makefiles 
-
-  * mlt++/swig/configure: swig/configure: use pkg-config mlt-framework instead
-  of deprecated mlt-config. 
-
-  * src/modules/core/filter_luma.c: filter_luma.c: prevent the first
-  application of the nested luma transition from being applied to a test card
-  image. This makes slideshows start without a transition at the beginning,
-  which is nicer and more expected. 
-
-  * src/modules/core/transition_luma.c: transition_luma.c: bugfix
-  (kdenlive-496) floating point exception when a slideshow using filter luma is
-  added to a multitrack. 
+  interlaced source. 
 
 2008-12-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/producer_westley.c: producer_westley.c: silence
-  compilation warning on uninitialized variable. 
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c: producer_avformat.c,
   consumer_avformat.c: use av_set_string3 where available (gets rid of
   deprecation warning). 
 
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  rendering to widescreen PAL DV. 
-
 2008-12-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/vorbis/producer_vorbis.c: producer_vorbis.c: add meta.media.
-  properties. 
-
-  * src/modules/dv/producer_libdv.c: producer_libdv.c: add meta.media.
-  properties. 
-
-  * src/modules/avformat/Makefile: avformat/Makefile: suppress error on
-  uninstall target 
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/avformat/factory.c: avformat/configure, avformat/Makfile,
   avformat/factory.c: Add a --avformat-no-filters configure option to
   filename for a no-codecs build to libmltffmpeg.so to prevent a clash with a
   no-filters module (libmltavformat.so).  
 
-2008-12-21  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: add a bunch
-  of metadata about the media under the properties key prefix "meta.media." 
-
-2008-12-21  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/producer_sdl_image.c: producer_sdl_image.c: Fix crash when
-  attempting to play a folder without images 
-
 2008-12-20  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl.c: consumer_sdl.c: let it work without
-  filter_avcolour_space 
-
-  * src/modules/core/producer_consumer.c: producer_consumer.c: use parent
-  profile if none specified; accept real_time properties from parent producer. 
-
-  * src/modules/core/producer_consumer.c: producer_consumer.c: set our length
-  from the length of the nested producer so we can terminate at the end of
-  rendering. 
-
-  * src/framework/mlt_properties.c: mlt_properties.c: fix some documentation 
-
   * src/modules/core/Makefile, src/modules/core/factory.c,
   src/modules/core/producer_consumer.c: core/Makefile, core/factory.c,
   core/producer_consumer.c: add new producer_consumer that will consume from an
   encapsulated producer under a different profile that the parent producer
   (kdenlive-323). 
 
-  * src/modules/core/transition_region.c: transition_region.c: bugfix
-  regression with in built circle region 
-
-  * src/modules/avformat/filter_swscale.c: avformat/filter_swscale.c: add
-  support for scaling the alpha channel (needs further testing) 
-
   * src/modules/avformat/Makefile, src/modules/avformat/factory.c,
   src/modules/avformat/filter_swscale.c, src/modules/fezzik.ini:
   avformat/Makefile, avformat/factory.c, avformat/filter_swscale.c: add new
   image scaler using FFmpeg libswcale. fezzik.ini: add swscale at higher
   priority than gtk2/rescale.  
 
-2008-12-19  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: fezzik.dict: let qimage be a producer for svg 
-
 2008-12-18  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   people who want to make a version entirely without including FFmpeg's codecs,
   which present patent royalty licensing issues. 
 
-  * src/modules/avformat/configure: avformat/configure: checkout
-  (--avformat-svn) or recommend (--help) a specific FFmpeg revision if this is
-  a release version of MLT (last field of version is even). 
-
-  * configure: configure: --disable-mmx implies --disable-sse 
-
   * src/modules/avformat/Makefile, src/modules/avformat/factory.c,
   src/modules/avformat/filter_avdeinterlace.c: avformat/Makefile,
   avformat/factory.c, avformat/filter_avdeinterlace.c: Fix and enable the
   avdeinterlace filter for a non-MMX configuration. 
 
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: add support
-  for AVOptions as properties. 
-
 2008-12-16  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_events.c, src/framework/mlt_field.c,
   mlt_playlist.h, mlt_field.h, mlt_playlist.c, mlt_tractor.c, mlt_events.c: add
   doxygen docs for events, field, and playlist. 
 
-2008-12-14  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  (kdenlive-432) segfault when reusing previous AVFrame (paused or idling on
-  last frame) but the previos AVFrame was invalid (not got_picture before
-  erroring out). 
-
 2008-12-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/motion_est/filter_motion_est.c: motion_est/filter_motion_est.c:
-  the sse compilation flag logic was inverted 
-
   * src/modules/gtk2/Makefile, src/modules/gtk2/pixops.c: gtk2/pixops.c,
   gtk2/Makefile: prevent MMX on all x86_64, not just OS X 
 
-  * configure: configure: add make flag and define for ARCH_X86_64 for all OSes
-
-  * configure: configure: fix mmx/sse detection on OS X and add detection of
-  x86_64 to define ARCH_X86_64 
-
   * src/modules/xine/Makefile, src/modules/xine/configure,
   src/modules/xine/deinterlace.c, src/modules/xine/xineutils.h: xine/Makefile,
   xine/xineutils.h, xine/deinterlace.c: respect mmx compilation flag instead of
   using own detection xine/configure: remove, no longer necessary 
 
-  * src/modules/motion_est/filter_motion_est.c: filtedr_motion_est.c: respect
-  new --disable-sse configure flag and whitespace cleanup 
-
   * src/modules/gtk2/Makefile, src/modules/gtk2/configure,
   src/modules/gtk2/pixops.c: gtk2/Makefile, gtk2/configure, gtk2/pixops.c:
   disable MMX parts on OS X - does not build 
 
-  * src/modules/kino/configure: kino/configure: automatically disable on OS X -
-  does not build due to missing headers 
-
-  * configure: configure: add --disable-sse and add mmx/sse detection for OS X 
-
 2008-12-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/README: README: update instructions to use pkg-config instead of
-  mlt-config 
-
   * mlt++/swig/java/build, mlt++/swig/perl/Makefile.PL,
   mlt++/swig/python/build, mlt++/swig/ruby/build, mlt++/swig/tcl/build,
   mlt++/test/Makefile: test/Makefile, swig/*/build: replace more mlt-config
   with pkg-config 
 
-  * profiles/atsc_1080i_50: profiles/atsc_1080i_50: added new profile for
-  square pixel 1080i at a PAL-like rate 
-
-  * Doxyfile: Doxyfile: add doxygen config file 
-
-  * src/valerie/valerie_status.h: valerie_status.h: take stdio.h header from
-  system include path 
-
-  * docs/install.txt: docs/install.txt: fix license info on humperdink and
-  valerie 
-
-  * configure: configure: bump the version 
-
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   src/framework/mlt_deque.c, src/framework/mlt_deque.h,
   src/framework/mlt_events.c, src/framework/mlt_events.h,
   producer_sdl_image.c: bugfix (kdenlive-422) not validating input file for
   image producers. 
 
-  * src/modules/inigo/producer_inigo.c: producer_inigo.c: display a warning
-  when failed to load a file. 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: clean up the
-  dual pass log at the end of the second pass. 
-
 2008-11-25  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix r1242
-  segfault due to improper audio decoder memory allocation. Also fix logical
-  bug with resampling on channels > 2 
-
   * src/modules/avformat/audioconvert.h,
   src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
   (kdenlive-297) audio distortion with audio formats other than signed 16-bit. 
 
-2008-11-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: fezzik.dict: added support for .tif equivalent to
-  .tiff 
-
-2008-11-17  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/albino/albino.c: albino.c: fix playout with SDL on Mac OS X 
-
-  * src/modules/sox/filter_sox.c: filter_sox.c: bugfix (2263114) build on sox
-  14.2.0. 
-
-2008-11-13  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/filter_freeze.c: filter_freeze.c: fix detection of
-  current frame position in a playlist 
-
-2008-11-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  (kdenlive-347) segfault when resolution is not known until after first frame
-  is decoded. Also, bugfix segfault when video_index or audio_index are -1
-  (invalid). 
-
-2008-11-13  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/filter_freeze.c: filter_freeze.c: update frozen frame
-  if freeze position is changed on the fly 
-
 2008-11-13  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/oldfilm/filter_vignette.c,
   * NEWS, configure: configure, NEWS: bump to version 0.3.2 and update release
   notes 
 
-2008-11-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/plus/filter_affine.c: filter_affine.c: bugfix (kdenlive-235)
-  rendering when used inside a multitrack. 
-
 2008-11-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * profiles/hdv_720_50p: profiles/hdv_720_50p: fix frame rate in description 
-
   * profiles/atsc_1080p_2398, profiles/atsc_1080p_24, profiles/atsc_1080p_25,
   profiles/atsc_1080p_2997, profiles/atsc_1080p_30, profiles/hdv_1080_25p,
   profiles/hdv_1080_30p, profiles/hdv_720_50p, profiles/hdv_720_60p:
   profiles/hdv_*, profiles/atsc_*: added more HD progressive mode profiles 
 
-  * src/modules/oldfilm/filter_dust.yml: filter_dust.yml: apply description fix
-  patch from Mads Dydensborg. 
-
-  * src/modules/kdenlive/producer_framebuffer.c: producer_framebuffer.c: bugfix
-  segfault in construction with null argument. 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  detection of aspect ratio for DV AVI (applies to raw and quicktime files as
-  well). 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: rework the
-  aspect ratio detection to try to fetch it from the codec and/or the stream in
-  newer versions of ffmpeg. This fixes aspect handling for raw DV but still not
-  yet for DV AVIs without the vprp chunk. 
-
-2008-11-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/frei0r/factory.c: frei0r/factory.c: fix build on BSD 
-
-  * src/modules/core/transition_mix.c: transition_mix.c: prevent serializing
-  previous_mix and reset previous_mix on seeking. 
-
-  * src/modules/normalize/filter_volume.c: filter_volume.c: prevent serializing
-  previous_gain and reset previous_gain on seeking. 
-
-2008-11-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * docs/services.txt: services.txt: minor corrections to documentation for
-  producer_avformat 
-
-  * mlt++/src/Makefile: src/Makefile: suppress warning on ldconfig failure 
-
 2008-11-05  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/kdenlive/Makefile, src/modules/kdenlive/factory.c,
   src/modules/oldfilm/filter_vignette.yml: oldfilm/filter_vignette*: filter is
   now usable with keyframes  
 
-  * src/modules/frei0r/factory.c: frei0r/factory.c: set min/max values in
-  metadata to defined min/max from frei0r.h  
-
-  * src/modules/frei0r/frei0r_helper.c: frei0r/frei0r_helper.c: frei0r double
-  and bool params are now useable with keyframes (mlt_geometry)  
-
-  * src/modules/frei0r/factory.c: frei0r/factory.c: yml files can be used now
-  for critical plugins  
-
-2008-10-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * profiles/Makefile: profiles/Makefile: fix removal of turd (*~) files on
-  install. 
-
-  * docs/TODO: docs/TODO: refer to wiki page 
-
-  * Makefile: Makefile: suppress warning on ldconfig failure. 
-
 2008-10-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/albino/albino.c, src/inigo/inigo.c: albino.c, inigo.c: disable realtime
   scheduling (kdenlive-180).  
 
-2008-10-27  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: Fix crash /
-  corruption when changing audio or video index 
-
-2008-10-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: optimize
-  slightly the stream index bugfix and update the video informational
-  properties on the producer when the video index changes. 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  regression with audio_index and video_index in last release when I added the
-  feature to close file on init with re-open on first use. Also, added some
-  exception handling around index values. 
-
-  * src/modules/vmfx/filter_mono.c: filter_mono.c: cleanup code to made it more
-  consistent between cases (use_alpha). 
-
-  * src/modules/vmfx/filter_mono.c: filter_mono.c: bugfix (kdenlive-234)
-  threshold filter inverting image and add invert property to revert to old
-  behavior. 
-
 2008-10-25  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/configure: configure: apply patch from Alberto Villa to fix build on
-  FreeBSD 
-
   * configure, src/modules/kino/endian_types.h, src/modules/kino/riff.cc,
   src/modules/sox/configure: configure, kino/enadian_types.h, kino/riff.c,
   sox/configure: apply patch from Alberto Villa to fix build on FreeBSD and to
   fix a sh expression bug in sox/configure. 
 
-2008-10-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c: producer_framebuffer.c:
-  improve delimiter parsing to allow '?' in filename argument 
-
-  * mlt-config-template: mlt-config-template: add deprecation warning 
-
-  * src/modules/sox/filter_sox.c: filter_sox.c: bugfix recent build regression
-  on older versions of sox 
-
 2008-10-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/inigo/inigo.c: inigo.c: improve the usage help and add -silent and
-  -progress options 
-
-  * src/modules/inigo/producer_inigo.c: producer_inigo.c: bugfix (2164436)
-  processing unknown command line options causes infinite loop 
-
   * src/inigo/Makefile, src/inigo/inigo.c: inigo.c: added -version option 
 
-  * src/modules/sox/filter_sox.c: filter_sox.c: bugfix (2040035) segfault with
-  libsox 14.1.0 
-
-  * configure: configure: -O3 is the maximum optimization level, not -O4 
-
-2008-10-21  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: fix
-  deprecated warning on av_set_string 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: fix build on
-  older libavformat versions 
-
-2008-10-20  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix Ogg
-  Vorbis files and possibly others that report invalid pts on some packets 
-
-  * mlt++/configure: configure: convert to use pkg-config; mlt-config is
-  deprecated 
-
-  * src/modules/xine/configure: xine/configure: disable module on ppc64 
-
-  * src/modules/xine/configure: xine/configure: disable module on ppc64 
-
-2008-10-08  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: Fix crash
-  introduced by FFmpeg revision 15367 (check that muxer and encoder have same
-  aspect ratio) 
-
-2008-10-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  reading file over http.  
-
 2008-09-22  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/gtk2/producer_pixbuf.c, src/modules/qimage/qimage_wrapper.cpp:
   producer_pixbuf.c, qimage_wrapper.c: Add "force_reload" option to force image
   reloading in the image producers 
 
-2008-09-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  (2106941) compilation against recent ffmpeg changes 
-
-2008-09-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kino/filehandler.cc: modules/kino/filehandler.cc: compilation
-  fix  
-
 2008-08-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sox/configure, src/modules/sox/filter_sox.c: sox/configure,
 
 2008-08-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/AUTHORS: update mlt++ AUTHORS 
-
-  * mlt++/Makefile: fix make dist target 
-
-  * configure: bump versions for 0.3.0 release 
-
-  * mlt++/configure: bump versions for 0.3.0 release 
-
-  * Makefile: improve make dist target 
-
-  * mlt++/Makefile: improve make dist target 
-
-  * AUTHORS: add AUTHORS file 
-
-  * NEWS: Add release notes file 
-
   * mlt++/swig/java/Play.java, mlt++/swig/java/Play.sh, mlt++/swig/java/build:
   swig/java: fixup the java bindings build script and example (bug 1523941) 
 
-  * demo/mlt_news: demo/mlt_news: small typo 
-
-2008-08-05  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c:
-  kdenlive/producer_framebuffer.c: keep resource file in producer and use '?'
-  instead of ':' to separate filename from speed, because it caused some
-  problems with other MLT functions 
-
-2008-08-03  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_playlist.c: framework/mlt_playlist.c: check length before
-  inserting blank, which fixes one frame blanks that were sometimes inserted
-  where not needed. 
-
-2008-07-31  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/frei0r/factory.c: frei0r/factory.c: use float values for
-  "double vars" in frei0r   
-
-2008-07-28  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/frei0r/configure: frei0r/configure: removed unneeded newlines  
-
-2008-07-27  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c: producer_framebuffer.c: Fix
-  aspect ratio with slowmotion producer 
-
-2008-07-24  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/qimage/configure: qimage/configure: Fix Qt3 detection and
-  compilation 
-
 2008-07-22  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/qimage/producer_qimage.c,
   qimage module: add mutex, fix caching and use alpha only if necessary (mostly
   borrowed from producer_pixbuf) 
 
-2008-07-14  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/qimage/configure: qimage/configure: Fix Qt4 detection 
-
-2008-07-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  recent regression with setting aspect ratio. Now it takes it from the profile
-  by default using the quotient properties for best accuracy. Now, one can also
-  override the aspect ratio using the same property name as the ffmpeg command
-  line utility ("aspect") for even greater symmetry. 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  segfault when fail to open or read file in init. 
-
 2008-07-10  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/qimage/configure, src/modules/qimage/producer_qimage.c,
   qimage module: add support for Qt4 (you can force compile against Qt3 with
   --force-qt3) 
 
-2008-07-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/vorbis/producer_vorbis.c: producer_vorbis.c: bugfix regression
-  with introduction of mlt_profile causing length of vorbis producer to always
-  yield zero. 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  regression playing audio-only files. 
-
 2008-07-01  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/oldfilm/filter_vignette.c,
   service closure truly thread-safe. As it was, reference count increment and
   decrement operations were not atomic and not protected comprehensively. 
 
-  * src/framework/mlt_consumer.c: mlt_consumer.c: added ability to set priority
-  of the read-ahead thread through a new "priority" property. This only works
-  if you have permission; fails to execute properly otherwise - not sure how to
-  make it fail over gracefully. Do not set this property if you do not have
-  permission. 
-
 2008-06-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h, mlt++/swig/mltpp.i:
   MltProducer.{h,cpp}, mltpp.i: remove Producer::get_frame that is unncessary
   and introduced a memory leak. 
 
-2008-06-25  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_field.c: mlt_field.c: correctly reconnect transitions
-  after a service disconnect 
-
-  * src/framework/mlt_service.c: mlt_service.c: fix bad identification for some
-  services (eg. transitions) 
-
-2008-06-25  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  segfault up the call stack when no image could be decoded for a frame by
-  producing the "test card" image. 
-
-2008-06-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/src/MltPlaylist.cpp: MltPlaylist.cpp: return null on clip_info method
-  if mlt_playlist_get_clip_info fails. 
-
-  * src/framework/mlt_playlist.c: mlt_playlist.c: return error on
-  mlt_playlist_get_clip_info if producer is null. 
-
-2008-06-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik/producer_fezzik.c: producer_fezzik.c: let other services
-  prevent Fezzik from attaching filters by passing the "fezzik_normalised"
-  property. 
-
-  * src/framework/mlt_repository.c: mlt_repository.c: bugfix memory leak on
-  getting directory list of MLT_REPOSITORY. 
-
-2008-06-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_consumer.c: mlt_consumer.c: make the realtime
-  frame-dropping heuristic based on actual frame rate instead of 25fps 
-
-2008-06-17  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  segfault in unprotected libavcodec call that is clearly marked not thread
-  safe! 
-
-2008-06-15  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: transition_composite.c: slightly
-  more accurate positioning when using crop panning and horizontal position is
-  adjusted to align chroma channels. 
-
-2008-06-10  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: close the
-  file at the end of object creation, then re-open the file on-demand. This
-  presented a file descriptor limit issue when loading very large playlists. 
-
-2008-06-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/src/MltPlaylist.cpp: MltPlaylist.cpp: prevent strdup from crashing on
-  a null pointer. 
-
-  * src/framework/mlt_playlist.c: mlt_playlist.c: remove some unncessary and
-  inefficient accounting code. 
-
-2008-06-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: transition_composite.c: add repeat
-  processing to crop property. 
-
-  * src/modules/core/transition_composite.c: transition_composite.c: add
-  animatable geometry "pan" property. This suppresses implicit scaling of the
-  b-frame and makes the compositing rectangle crop. Then, it uses the x and y
-  geometry information to pan the b-frame within the composite rectangle. For
-  example, a negative x pans the image to the left and that portion of the b
-  frame left of the composite rectangle is cropped. w and h of the pan geometry
-  is not implemented at this time, but the plan is to implement scaling of the
-  b-frame. In the end, this can provide a Ken Burns effect for still images - a
-  much requested feature. 
-
-2008-06-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: remove
-  multi-threaded audio decoding option. It does not provide any advantage at
-  this time and just wastes resources. 
-
-  * src/framework/mlt_playlist.c: mlt_playlist.c: added an "autoclose" property
-  for sequential processing of very large playlists. If set, it automatically
-  closes previous producers to reduce resources (file handles and threads if
-  using producer_avformat with threads). 
-
 2008-06-01  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/producer_pango.c: producer_pango.c: make the size property
-  an absolute height in pixels for greater compositing and quality control. 
-
   * src/modules/core/filter_resize.c, src/modules/core/transition_composite.c:
   filter_resize,c, filter_composite.c: bugfix redundant rounding. 
 
-  * src/modules/core/filter_watermark.c: filter_watermark.c: bugfix propogation
-  of output_ratio as a double - was causing incorrect calculations in
-  transition_composite.c with non-square-pixel watermark sources. 
-
-  * src/framework/mlt_properties.c: mlt_properties.c: make arithmetic processor
-  use floating point instead of integer so that '/' is meaningful. I am not
-  totally certain of the consequences of this change because I am not aware of
-  where the feature is used. However, I am using it to specify the aspect ratio
-  of certain things like bitmap graphics that were not designed for square
-  pixels. And being able to specify a fraction allows for accurate detection of
-  equivalent aspect ratios between different sources, particularly compositing.
-
-  * src/framework/mlt_profile.c: mlt_profile.c: make fallback default sample
-  aspect ratio the same as the revised profile's sample aspect ratio 
-
-2008-05-25  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/gtk2/producer_pixbuf.c: producer_pixbuf.c: apply the in point
-  to the position in the image sequence 
-
 2008-05-15  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/avformat/configure: avformat/configure: fix compilation against
-  shared ffmpeg for a headers configuration that has appeared. 
-
   * profiles/dv_ntsc, profiles/dv_ntsc_wide, profiles/dv_pal,
   profiles/dv_pal_wide, src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c: profiles/dv_*, consumer_avformat.c,
   other ITU-R 601-based video sources such as MPEG-2 for DVD Video and
   broadcast. 
 
-2008-05-12  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_luma.c: Correctly update the luma file if the
-  resource was modified 
-
 2008-05-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/configure, src/modules/avformat/consumer_avformat.c:
 
 2008-05-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/filter_resize.c: filter_resize.c: fix field order
-  correction 
-
-  * src/modules/xine/configure: xine/configure: relax restrictions to let
-  OSX/Intel use xine deinterlace 
-
   * src/framework/mlt_field.c, src/framework/mlt_field.h: mlt_field.[hc]: added
   mlt_field_disconnect_service 
 
   src/modules/dgraft/filter_telecide.c: modules/dgraft: added module for ports
   of Donald Graft's GPL filters. 
 
-  * src/modules/sox/configure: sox/configure: make inclusion of libsfx dynamic 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  reporting of top_field_first on frame. 
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure:
   avformat/Makefile, configure: fix --avformat-swscale and the removal of the
   ffmpeg 'lib' make target.  
 
-  * src/modules/core/filter_data_show.c: filter_data_show.c: bugfix
-  interpreting timecode, due to invalid fps on mlt_profiles API changes 
-
 2008-04-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h, mlt++/swig/mltpp.i:
 
 2008-04-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/test/server.cpp: test/server.cpp: bugfix (1940389) compilation on gcc
-  4.3 
-
-  * src/modules/lumas/create_lumas: lumas/create_lumas: bugfix (1940387)
-  bash-ism in script 
-
   * configure, src/modules/motion_est/configure: configure,
   motion_est/configure: remove module-specific crud from top-level configure
   script, and enable motion_est now by default.  
   src/modules/kino/kino_wrapper.cc: kino/kino_wrapper.cc, kino/filehandler.cc,
   kino/avi.cc: bugfix (1936991) compilation with gcc 4.3.  
 
-2008-04-11  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/gtk2/producer_pixbuf.c: producer_pixbuf.c: bugfix image
-  sequences 
-
 2008-03-22  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/frei0r/frei0r_helper.c, src/modules/frei0r/transition_frei0r.c:
   frei0r/{frei0r_helper,transition_frei0r}.c: fixed wrong scaling and memory
   leak  
 
-2008-03-18  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/configure: avformat/configure: improve chances of
-  successful linking with -svn and -static options 
-
 2008-03-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kino/riff.cc: kino/riff.c: fix failure to dlopen due to symbol
-  signature mismatch on make_fourcc 
-
   * src/modules/frei0r/configure, src/modules/frei0r/factory.c:
   frei0r/configure: use CFLAGS so I can tell the test where to find frei0r.h
   frei0r/factory.c: add metadata_schema value to metadata 
 
-  * src/framework/mlt_repository.c: mlt_repository.c: clear up warning due to
-  const return from getenv_locale() 
-
 2008-03-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_repository.c: mlt_repository.c: fix to previous string
-  const fix in mlt_repository_languages 
-
-  * src/framework/mlt_repository.c: mlt_repository.[hc]: fix modifying const
-  string in mlt_repository_languages 
-
   * src/framework/mlt_repository.c, src/framework/mlt_repository.h:
   mlt_repository.[hc]: add mlt_repository_languages helper function for
   localizing metadata 
 
-2008-03-05  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/valerie/Makefile: src/valerie/Makefile: fix overwriting libmlt.0.dylib
-  on libvalerie install on OS X 
-
-  * src/modules/sox/configure: sox/configure: add OS X and Debian (future?)
-  pkg-config support to sox configuration 
-
 2008-03-04  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/frei0r/factory.c: src/modules/frei0r/factory.c: load metadata
-  on request (thx for patch from Dan Dennedy) added "tags" metadata with type
-  "Video" for frei0r plugins  
-
-  * src/modules/frei0r/factory.c: modules/frei0r/factory.c: also register
-  transitions, added "tags" to metadata  
-
-  * src/modules/oldfilm/filter_vignette.c: oldfilm/filter_vignette.c: speedup  
-
   * src/modules/oldfilm/fdust.svg, src/modules/oldfilm/filter_dust.yml,
   src/modules/oldfilm/filter_grain.yml, src/modules/oldfilm/filter_lines.yml,
   src/modules/oldfilm/filter_oldfilm.yml,
   metaschema.yaml, producer_avformat.yml: reset schema_version to 0.1 since we
   have not release anything yet with schema let alone metadata 
 
-  * src/modules/frei0r/factory.c: frei0r/factory.c: apply destructors and
-  serialiser to metadata mlt_properties 
-
-  * src/inigo/inigo.c: inigo.c: fix querying on specific filter or transition 
-
-2008-03-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_resize.c: filter_rescale.c: if input width or
-  height are zero, infer them from the profile 
-
 2008-02-28  blendamedt <blendamedt@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/frei0r/configure: test not only if header frei0r.h exists, also
-  use an item  
-
   * src/modules/frei0r/Makefile, src/modules/frei0r/configure,
   src/modules/frei0r/factory.c, src/modules/frei0r/filter_frei0r.c,
   src/modules/frei0r/frei0r_helper.c, src/modules/frei0r/frei0r_helper.h,
   MltRepository.{h,cpp}: update to latest mlt_repository.h change -
   finalization of callback declarations and metadata handling 
 
-  * src/modules/avformat/configure: avformat/Makefile: compilation fix for
-  latest FFmpeg update 
-
 2008-02-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/inigo/inigo.c: inigo.c: add -query option to inigo for service and
-  metadata lookup. 
-
   * src/modules/avformat/Makefile, src/modules/avformat/factory.c,
   src/modules/avformat/producer_avformat.yml: avformat/factory.c,
   producer_avformat.yml, avformat/Makefile: add metadata for producer:avformat.
 
 2008-02-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sox/Makefile: sox/Makefile: helpful note for Ubuntu (and
-  Debian?)  
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure:
   avformat/configure, avformat/Makefile: add libavdevice for newer versions of
   ffmpeg when using --avformat-svn or --avformat-static   
 
-  * src/framework/mlt_repository.c: mlt_repository.c: throw warning on failure
-  to load module  
-
 2008-02-16  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/swig/python/build: swig/python/build: add -fPIC 
-
   * mlt++/src/MltRepository.cpp, mlt++/src/MltRepository.h, mlt++/swig/mltpp.i:
   MltRepository.{h,cpp}, swig/mltpp.i: added consumers, filters, producers,
   transitions, register_metadata, and metadata methods to Repository class 
   mlt_repository_filters, mlt_repository_producers, mlt_repository_transitions,
   mlt_repository_register_metadata, and mlt_repository_metadata  
 
-2008-02-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/configure: avformat/configure: use pkg-config with
-  --avformat-shared 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: - Convert to
-  ffmpeg and AVOptions exclusively. This makes ALL AVOptions as seen from
-  \'ffmpeg -h\' available to MLT. Instead of ffmpeg\'s \'-option value\' use
-  inigo\'s property syntax \'option=value\" - Add dual pass encoding. - Use
-  multi-threading even with non-threaded codecs by separating producer and
-  consumer threads. - Whitespace cleanup. 
-
-  * src/framework/mlt_consumer.c: mlt_consumer.c: let consumers use read-ahead
-  processing thread without frame dropping with real_time=-1 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: cleanup
-  whitespace 
-
-2008-02-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/Makefile: do not make tests automatically 
-
 2008-02-11  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/consumer_avformat.c,
   producer_avformat.c: add FFmpeg multi-thread support via "threads" property
   or MLT_AVFORMAT_THREADS environment variable   
 
-2008-02-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/dv/producer_libdv.c: producer_libdv.c: fix test for framerate
-  matching profile 
-
 2008-02-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/configure, mlt++/src/Makefile: configure: add soversion variable
   interface version (soversion) mlt.h: add version info to header so apps can
   have build time adaptations 
 
-  * mlt++/swig/ruby/thumbs.rb: thumbs.rb: fix error on Playlist.append due to
-  args not int 
-
   * mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltFactory.cpp,
   mlt++/src/MltFactory.h, mlt++/src/MltRepository.cpp,
   mlt++/src/MltRepository.h, mlt++/swig/mltpp.i: Mlt.h, MltFactory.{h,cpp},
 
 2008-02-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/COPYING: add COPYING to disclose license 
-
-  * src/framework/config.h: remove config.h 
-
   * Makefile, setenv, src/framework/Makefile, src/framework/mlt_consumer.c,
   src/framework/mlt_factory.c, src/framework/mlt_filter.c,
   src/framework/mlt_frame.c, src/framework/mlt_multitrack.c,
   Since nearly every file was touched, remove superfluous headers and prepare
   for coming mlt_repository change. 
 
-2008-01-20  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  (kdenlive-28) a/v sync on non-whole frame rate. 
-
-2008-01-11  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: do not free
-  AVPacket if av_read_frame fails. 
-
 2008-01-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/oldfilm/Makefile, src/modules/oldfilm/configure,
   src/modules/oldfilm/filter_oldfilm.h: src/modules/oldfilm/*: add oldfilm
   module contributed by Marco Gittler 
 
-  * docs/services.txt: minor typo fix 
-
-  * src/framework/mlt_playlist.c: mlt_playlist.c: fix some blank-handling bugs
-  in mlt_playlist_insert_at() 
-
-2007-12-18  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: fezzik.dict: prioritize avformat over vorbis
-  module for .ogg, at least until better track type detection is in place. 
-
-2007-12-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: make
-  compilation fix on url_fclose version sensitive to support older ffmpeg 
-
-2007-12-08  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * .../motion_est/filter_autotrack_rectangle.c: Autotrack rectangle can now be
-  defined using geometry="x,y:wxh" instead of having to pass it in the filter
-  name 
-
 2007-12-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/configure, src/modules/sox/configure: sox/configure:
   producer_westley.c: remove statefulness of frame rate through framework and
   modules, and allow consumer properties to override profile settings. 
 
-  * src/modules/sdl/producer_sdl_image.c: producer_sdl_image.c: fix compilation
-  warning with respect to const pointer 
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: fix pointer
-  passed to url_fclose() 
-
-  * src/modules/kino/riff.h: kino/riff.h: fix compiler warnings on missing
-  const for char* 
-
 2007-11-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sox/Makefile, src/modules/sox/configure,
   gtk2/producer_pango.c, gtk2/pixops.c, miracle_server.c, miracle_unit.c:
   cleanup a whole bunch of compiler warnings 
 
-  * src/modules/jackrack/configure: jackrack/configure: add detection for
-  ladspa and disable if not detected 
-
-  * src/modules/core/filter_luma.c: filter_luma.c: bugfix testing b_frame's
-  dimensions 
-
-  * src/modules/core/filter_resize.c: filter_resize.c: bugfix overriding
-  top_field_first property 
-
   * src/modules/motion_est/filter_motion_est.c,
   src/modules/motion_est/filter_vismv.c: filter_vismv.c: bugfix pointer to
   array of motion vectors 
 
-  * src/modules/avformat/configure: avformat/configure: fix detect shared
-  install of libavformat due to link to versioned .so. 
-
 2007-10-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_factory.c, src/framework/mlt_profile.c: mlt_profile.c,
   * setenv, src/framework/mlt_profile.c: mlt_profle.c: add support for
   MLT_PROFILES_DIR environment variable  
 
-  * src/modules/sdl/consumer_sdl.c: consumer_sdl.c: fix specifying window size
-  on constructor arg 
-
   * src/modules/effectv/utils.c, src/modules/effectv/utils.h: effectv/utils.*:
   fix compilation on OS X 
 
-2007-08-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl_still.c: consumer_sdl_still.c: bugfix segfault
-
-2007-08-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl_still.c: consumer_sdl_still.c: bugfix
-  initialisation of window dimensions due to recent profiles addition 
-
 2007-07-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * configure, docs/policies.txt: configure: fix broken variables in pkg-config
   files policies.txt: add bug reporting procedure  
 
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: align some
-  defaults with ffmpeg for more reliable output 
-
 2007-07-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_profile.c: mlt_profile.c:
 
 2007-07-20  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * profiles/Makefile: profiles/Makefile: cleanup profiles dir on (un)install 
-
   * profiles/atsc_1080i_60, profiles/atsc_720p_30, profiles/atsc_wide_1080i,
   profiles/atsc_wide_720p: profiles/atsc_*: rename and change descriptions 
 
   * profiles/hdv_720_50p, profiles/hdv_720_60i, profiles/hdv_720_ntsc,
   profiles/hdv_720_pal: 
 
-  * src/framework/mlt_profile.c: mlt_profile.c: revise substrings for legacy
-  setting of MLT_NORMALISATION 
-
   * profiles/atsc_wide_1080i, profiles/atsc_wide_720p, profiles/cif_ntsc,
   profiles/cif_pal, profiles/cvd_ntsc, profiles/cvd_pal, profiles/dv_ntsc,
   profiles/dv_ntsc_wide, profiles/dv_pal, profiles/dv_pal_wide,
   src/modules/avformat/producer_avformat.c: consumer_avformat.c: save disabled,
   experimental flushing code 
 
-2007-07-07  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/qimage/configure: Fix build based on patch from Ryan Hodge 
-
-2007-07-01  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict, src/modules/qimage/Makefile,
-  src/modules/qimage/configure, src/modules/qimage/producer_qimage.c,
-  src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h:
-  Add support for psd, xcf and exr images (KDE libraries needed for these
-  formats). Make pcx and tiff images load correctly 
-
-  * src/modules/gtk2/producer_pixbuf.c: Fix for rgba images (based on the code
-  from qimage_producer) 
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix get image for formats
-  different from yuv422 
-
-2007-07-01  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: improve
-  frame accuracy 
-
-2007-06-30  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Better fix for aspect_ratio
-  problem in framebuffer producer 
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix aspect ratio for
-  slowmotion / freeze effect 
+2007-07-01  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kdenlive/configure: Fix typo which prevented wave filter to be
-  available 
+  * src/modules/fezzik.dict, src/modules/qimage/Makefile,
+  src/modules/qimage/configure, src/modules/qimage/producer_qimage.c,
+  src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h:
+  Add support for psd, xcf and exr images (KDE libraries needed for these
+  formats). Make pcx and tiff images load correctly 
 
 2007-06-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * demo/circle.png: demo/circle.png: fix broken image 
-
-  * demo/watermark1.png: watermark1.png: fix broken image 
-
   * demo/mlt_title_over_gfx, demo/mlt_titleshadow_watermark,
   demo/mlt_voiceover: demo/mlt_title_over_gfx, demo/mlt_titleshadow_watermark,
   demo/mlt_voiceover: fix broken demos due to recent hidden track handling
   change in mlt_transition.c 
 
-2007-06-28  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: consumer_avformat.c: bugfix
-  initial buffer size to prevent high quantization at beginning 
-
-2007-06-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix audio
-  sync with some codecs and revert unnecessary precautions that introduce
-  inefficiency 
-
 2007-06-12  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/Makefile: added dist make targets 
-
-  * Makefile: added dist make targets 
-
   * mlt++/Makefile, mlt++/src/Makefile, mlt++/test/Makefile: added uninstall
   make targets 
 
   src/modules/effectv/utils.c, src/modules/effectv/utils.h: added effectv
   module with BurningTV filter provided by Stephane Fillod 
 
-  * src/framework/mlt_frame.c: mlt_frame.c: let image conversions accept NULL
-  for the alpha parameter 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: bugfix
-  segfault when paused after seeking but no picture available to duplicate 
-
   * docs/westley.txt, src/modules/fezzik.dict: fezzik.dict: prioritize avformat
   higher than libdv for better quality 
 
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: make better
-  test for existence for avcodec_decode_audio2 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: fix setting
-  int property as double 
-
-  * src/modules/avformat/producer_avformat.c: producer_avformat.c: - remove
-  seeking immediately after opening file improves compatibility (in particular,
-  ogg theora) - use non-deprecated avcodec_decode_audio2 if available - changes
-  to adhere to warnings on ffmpeg decode api docs ought to improve stability
-  and compatibility  
-
-  * src/modules/avformat/consumer_avformat.c: added support for ilme=1 and
-  ildct=1 properties to consumer_avformat 
-
 2007-06-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/avformat/configure: --avformat-swscale with --avformat-svn is
-  only permitted with --enable-gpl 
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure: change
   --avformat-svn configure option to do a static build of ffmpeg libs only and
   statically link to mlt module. Also, make --avformat-svn aware of
   --avformat-swscale and --enable-gpl 
 
-2007-06-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_rescale.c: bugfix core/filter_rescale segfault on
-  scaling alpha that was already to correct scale (e.g. mlt_bouncy_ball) 
-
-2007-06-01  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_rescale.c: bugfix segfault in core/filter_rescale
-  scaling alpha already scaled in gtk2/filter_rescale 
-
-  * src/framework/mlt_tractor.c: bugfix tractor not propogating resize_alpha
-  frame property 
-
-  * src/framework/mlt_transition.c: bugfix transition processing hidden track 
-
-2007-05-31  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kdenlive/producer_framebuffer.c: Fix framebuffer crash & clip
-  duration error 
-
 2007-05-25  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/dv/consumer_libdv.c: per jb's suggestion, enable
-  terminate_on_pause by default 
-
   * demo/README, demo/mlt_attributes, demo/mlt_intro, demo/mlt_jcut,
   demo/mlt_lcut, docs/inigo.txt: fix some demos broken by old changes 
 
-2007-05-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_data_show.c: fix dynamic attribute value parsing
-  and memory management in data_show 
-
 2007-05-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_factory.c, src/framework/mlt_producer.c,
   src/modules/fezzik.ini: the framework may not depend upon specific
   modules--data_feed/show in this case 
 
-  * src/modules/core/filter_rescale.c: Only scale the alpha when also scaling
-  the image.  
-
 2007-04-10  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kdenlive/filter_wave.c: compilation fix  
-
-  * src/modules/avformat/configure: fix compilation without swscale  
-
   * ChangeLog, docs/policies.txt, src/modules/core/Makefile,
   src/modules/core/configure, src/modules/core/factory.c,
   src/modules/core/filter_boxblur.c, src/modules/core/filter_boxblur.h,
   Cleanup copyrights and attributions, and move Jean-Baptiste's services to a
   new kdenlive module.  
 
-2007-03-31  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/producer_framebuffer.c: Fixed crash in slowmotion producer
-   
-
 2007-03-31  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * ChangeLog, src/modules/sox/filter_sox.c: add sox 13.0.0 support  
 
-2007-03-31  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/producer_framebuffer.c: Fix slowmotion producer (no more
-  variable speed, but at least it works now).  
-
 2007-03-30  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * ChangeLog, src/modules/core/filter_boxblur.c,
 
   * demo/README, demo/consumers.ini: change default dv1394 device file  
 
-  * configure: remove bashisms  
-
-2007-03-02  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Allow user to choose video driver
-  and output display  
-
 2007-02-19  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/core/filter_boxblur.c, src/modules/core/filter_boxblur.h,
   src/modules/core/filter_boxblur.h, src/modules/core/filter_wave.c,
   src/modules/core/filter_wave.h: Add blur and wave filters from Leny Grisel  
 
-2007-02-01  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Allow user to set alsa device  
-
-2007-01-23  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_data_show.c: Allow display of metadata and timecode
-   
-
-2007-01-22  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: Write metadata if there is any  
-
-2007-01-19  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_frame.c: Fix my terribly broken YUV to RGB conversion  
-
-2007-01-13  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl_preview.c: Allow changing volume in
-  sdl_preview consumer  
-
-2007-01-02  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: Change default value for
-  libavformat's qscale, preventing some crashes  
-
 2006-12-31  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/producer_avformat.c,
   producers, using basic structure like:
   meta.attr.metadata_name.markup=metadata_value  
 
-  * src/modules/vorbis/producer_vorbis.c: Vorbis should set correct values in
-  frame for audio channels and frequency.  
-
 2006-12-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * ChangeLog, configure, src/framework/mlt_consumer.h,
   configure run with bash since it uses bash-specific features. Also, patches
   headers to comments for pedantic compilation.  
 
-2006-11-20  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/producer_framebuffer.c: remove debug msg  
-
 2006-11-18  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/core/producer_framebuffer.c,
   src/modules/core/producer_framebuffer.h: New framebuffer producer. Provides
   slowmotion, reverse playing and stroboscope effect  
 
-2006-11-05  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: Kdenlive project files are now westley compatible 
-
-  * src/modules/core/transition_luma.c: Luma get_image produces yuv only, so
-  announce it. Fix problem when requesting rgb image of a luma transition.  
-
-2006-10-26  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_rescale.c: Fix rescaling of rgb images when not
-  using gtk2  
-
-2006-10-16  j-b-m <j-b-m@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_obscure.c: Position for the effect was not
-  calculated right if the clip was in the middle of a playlist  
-
-2006-10-06  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: + General improved media support 
-
-2006-10-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: + Correction to previous patch -
-  fixes pause behaviour with rawvideo  
-
-  * src/modules/avformat/producer_avformat.c: + Corrections for uncompressed
-  video sources  
-
 2006-09-28  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * ChangeLog: Following Dan's example.  Applied an amd64 compilation patch to
-  motion_est module and patch to correctly initialize audio frequency and
-  channels.  
-
   * src/modules/avformat/producer_avformat.c, src/modules/dv/producer_libdv.c:
   Patch supplied by Jean-Baptiste. 
   
 
 2006-08-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/vmfx/filter_mono.h: + Header file for mono filter  
-
   * src/modules/vmfx/Makefile, src/modules/vmfx/configure,
   src/modules/vmfx/factory.c, src/modules/vmfx/filter_mono.c: + A mono filter
   for mask generation (not v. useful)  
   * src/modules/vmfx/filter_chroma.c, src/modules/vmfx/filter_chroma_hold.c: +
   Correction to uneven chroma samples  
 
-  * src/modules/qimage/qimage_wrapper.cpp: + Image caching for the qimage
-  producer  
-
-  * src/modules/gtk2/producer_pixbuf.c: + Image caching for the gtk2 pixbuf
-  producer  
-
-2006-08-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * ChangeLog: *** empty log message ***  
-
-  * src/modules/westley/producer_westley.c: enhance producer_westley to parse
-  Kino 0.9.1 SMIL (clock) time values.  
-
-  * ChangeLog: *** empty log message ***  
-
-  * src/modules/avformat/configure: convert --avformat-cvs to svn and rename
-  option as --avformat-svn (--avformat-cvs is an undocumented alias).  
-
-2006-05-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * configure: bump version  
-
-2006-05-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/qimage/producer_qimage.c: apply patch from Jean-Baptiste
-  <jb@ader.ch> to add rgb24a support to producer_qimage  
-
 2006-05-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/transition_composite.c: apply patch from Jean Baptiste
-  <jb@ader.ch> to fix fill-type rescaling when aspect ratio is equal to
-  normalised ratio  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h,
   src/modules/gtk2/producer_pixbuf.c: apply patch from Jean Baptiste to add
   rgb24a support to producer_pixbuf  
 
-2006-05-20  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/qimage/configure: let QTDIR also define location of qt include
-  dir  
-
-  * src/modules/kino/filehandler.cc: fix compilation on latest version of
-  libquicktime (0.9.8)  
-
-2006-05-04  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/filter_avcolour_space.c: + Big endian patch courtesy
-  of Goncalo Carvalho (glslang at gmail dot com) - specifically, corrects
-  colour space conversions on the Intel Mac  
-
-2006-04-20  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_resize.c: + Field order control reworked
-  (meta.top_field_first has priority over source)  
-
-2006-04-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_resize.c: + Top field first correction (original
-  approach would not have worked [mea culpa], and this is only a partial
-  solution since the consumers have no say in field order)  
-
-  * src/modules/qimage/qimage_wrapper.cpp: + Fix for byte order as spotted by
-  Goncalo Carvhalo (many thanks :-))  
-
-  * src/modules/core/filter_resize.c: + Meta override for field order
-  misreporting/errors in encoders  
-
 2006-03-29  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/qimage/Makefile, src/modules/qimage/configure,
   src/modules/qimage/qimage_wrapper.cpp, src/modules/qimage/qimage_wrapper.h: +
   QImage module added - default is still GTK2 when available  
 
-  * src/modules/gtk2/producer_pixbuf.c: + Bug Fix: Removes a memory leak on
-  last alpha channel  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h: + Preparation for a
   QT image loader (to allow optional and functionally equivalent qt or gtk2
   usage for image loading)  
 
 2006-03-28  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/producer_pixbuf.c: + Usage of mlt_properties_dir_list  
-
   * src/framework/mlt_properties.c, src/framework/mlt_properties.h: + Adds a
   utility function for listing files in a directory (aids with cross platform
   support)  
 
-2006-03-20  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/src/MltFactory.h: + Fix for swig parsing  
-
 2006-03-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/framework/mlt_manager.h, src/modules/core/Makefile,
   src/modules/core/filter_mono.c, src/modules/core/filter_mono.h: added mono
   audio filter  
 
-  * src/modules/kino/Makefile: libquicktime prefers pkg-config now and latest
-  lqt-config is broken with respect to --cflags  
-
-  * configure: log configuration history to config.log  
-
 2006-02-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/src/Makefile: + Install of config.h for linux and os/x usage  
-
-  * mlt++/src/config.h: + Added the config.h for win32  
-
   * mlt++/mlt++.sln, mlt++/mlt++.vcproj, mlt++/src/Mlt.h,
   mlt++/src/MltConsumer.h, mlt++/src/MltDeque.h, mlt++/src/MltEvent.h,
   mlt++/src/MltFactory.cpp, mlt++/src/MltFactory.h, mlt++/src/MltField.h,
   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  
 
-  * src/modules/vmfx/filter_shape.c: + Activates the mixdown in the combine to
-  allow audio sync'd with wipe (smooth ramping not implemented yet)  
-
-  * src/modules/core/transition_mix.c: + Alternative mixing mechanism
-  introduced (specify a property of combine=1 on the mix transition to
-  activate)  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h: + Alternative between
   track mixing mechanism (using a low pass filter)  
 
 
   * docs/dvcp.txt, docs/inigo.txt: minor fixes  
 
-  * src/miracle/miracle_commands.c: add proper response to uadd command  
-
 2006-01-08  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/Makefile: fix compilation error  
-
-  * src/modules/dv/producer_libdv.c: Make libdv producer return some image even
-  if unable to handle specific image type request.  
-
-  * Makefile: dist-clean target is more familiar - alias it  
-
   * src/modules/feeds/NTSC/data_fx.properties,
   src/modules/feeds/NTSC/obscure.properties: fix comment/docu typo  
 
 
   * mlt++/Makefile, mlt++/configure: + Correction to a typo  
 
-  * src/modules/avformat/Makefile: + Uses libdir in private build of ffmpeg too
-   
-
-  * src/modules/avformat/configure: + 64 bit fix for ffmpeg built externally
-  (should switch to pkg-config here)  
-
-  * mlt++/swig/perl/Makefile.PL: + Perl compilation patch submitted by Torsten
-  Spindler  
-
   * mlt++/configure, mlt++/src/Makefile: + Added a --libdir switch to the
   configure and build and fixed test case compilation  
 
-  * configure: - Removed a diagnostic  
-
   * Makefile, configure, src/framework/Makefile, src/miracle/Makefile,
   src/valerie/Makefile: + Added a --libdir switch to the configure and build  
 
-2005-11-22  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/configure: + Allow LDFLAGS to be inherited from the environment  
-
-2005-11-21  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/src/Makefile: + Creates the lib directory on an install  
-
-2005-11-17  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: + Correction to alpha mask
-  generation  
-
 2005-11-10  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/Makefile, mlt++/src/Makefile: + DESTDIR patch from Anthony Green
   src/modules/avformat/producer_avformat.c: Allows aac output, corrects ntsc
   sample collection, and picks up known info streams  
 
-2005-10-28  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/motion_est/filter_crop_detect.c: Correct bug introduced by
-  revision 1.3  
-
-  * src/modules/motion_est/filter_motion_est.c: x86 doesn't play well with ppc 
-
-  * src/modules/motion_est/Makefile: Fix shared lib flags in Makefile for
-  Darwin  
-
 2005-10-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/motion_est/configure: + Enabled Zach's new slowmotion producer 
-
   * src/modules/core/consumer_null.c,
   .../motion_est/filter_autotrack_rectangle.c, src/modules/sdl/consumer_sdl.c:
   src/modules/core/consumer_null.c src/modules/sdl/consumer_sdl.c + Terminate
 
 2005-10-24  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/motion_est/README: Added a producer slowmotion example.  
-
   * src/modules/motion_est/Makefile, src/modules/motion_est/factory.c,
   src/modules/motion_est/filter_motion_est.c,
   src/modules/motion_est/filter_motion_est.h,
   slow motion producer. It provides basic slow motion through frame repeats and
   a more advanced interpolation.  
 
-2005-10-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/vmfx/filter_shape.c: + Correction for non-zero in point on the
-  associated cut  
-
-2005-10-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/gtk2/producer_pango.c: + Moved ~ to LF hack to pango processing
-   
-
-  * src/modules/sdl/consumer_sdl_still.c: + Rounding errors corrected for last
-  gasp scaling  
-
-2005-10-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: + Deadlock resolution  
-
 2005-10-10  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/framework/mlt_tractor.c,
   src/modules/core/transition_luma.c: + Added an option to override alignment
   and transparent borders for compositing  
 
-2005-10-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/vmfx/filter_shape.c: + Corrections, optimisations and a hack
-  for loading lumas from the mlt luma collection  
-
 2005-10-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sdl/configure, src/modules/sdl/factory.c: + Correction for
   uninstalled sdl image lib  
 
-  * configure: + OS/X Tiger patch  
-
   * mlt++/src/MltProperties.cpp, mlt++/src/MltProperties.h: OS/X gcc/g++ 4.x
   fix  
 
   mlt++/src/MltProperties.h, mlt++/test/Makefile: + Whoops - had forgotten
   these OS/X patches...  
 
-  * src/modules/sdl/producer_sdl_image.c: + Surface conversion  
-
-  * src/modules/sdl/producer_sdl_image.h: + Added producer_sdl_image as an
-  alternative image and image sequence producer  
-
   * src/modules/fezzik.dict, src/modules/sdl/Makefile,
   src/modules/sdl/configure, src/modules/sdl/factory.c,
   src/modules/sdl/producer_sdl_image.c: + Added producer_sdl_image as an
   alternative image and image sequence producer  
 
-2005-10-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: + Clean ups and corrections  
-
-2005-09-29  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * mlt++/src/MltPushConsumer.cpp: + Oops - fix for memory leak  
-
-  * src/modules/avformat/filter_avcolour_space.c: + Extracts alpha from rgb24a
-  images  
-
 2005-09-28  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltPushConsumer.cpp,
   src/modules/feeds/PAL/etv.properties + Temporary work around to keep
   composites correct  
 
-2005-09-27  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: + Correction and a minor
-  optimisation  
-
-  * src/modules/gtk2/producer_pixbuf.c: + Changed incorrect global variable to
-  static  
-
-  * src/modules/avformat/consumer_avformat.c:
-  src/modules/avformat/consumer_avformat.c + User specified pixel format
-  property (pix_fmt) + Corrections to aspect ratio + Alpha channel added to
-  RGBA32 conversions - Removed an historical/erroneous attempt to hack aspect
-  ratio  
-
 2005-09-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/producer_westley.c: + Indicator for missing media
-  replacement in case pango doesn't exist  
-
-  * src/modules/plus/filter_charcoal.c: + Bounds checking on chroma samples  
-
   * src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_avdeinterlace.c,
   src/modules/avformat/producer_avformat.c: filter_avcolour_space.c +
   producer_avformat.c + Corrections for uneven width + Corrections for state
   propogation of top field first and interlaced state  
 
-  * src/modules/xine/filter_deinterlace.c: + Correction for cases where the
-  interlaced state is determined after the image is rendered  
-
 2005-09-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h,
   src/modules/sdl/consumer_sdl_still.c + Application provided preview support
   added  
 
-2005-09-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/plus/filter_invert.c: + Small mod to allow better use of invert
-  as a gui item selector (alpha property)  
-
 2005-09-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_still.c:
 
 2005-08-29  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/inigo/inigo.c: + Keyboard handling events on Darwin  
-
   * src/modules/lumas/Makefile, src/modules/sdl/consumer_sdl.c: lumas/Makefile
   + Correction for non-gui app build on darwin  lumas/luma.c + Handle sdl
   events  sdl/consumer_sdl.c + Audio on Darwin  
   src/modules/sdl/consumer_sdl_preview.c src/modules/sdl/consumer_sdl_still.c +
   Corrections to preview mode switching  
 
-  * src/modules/sdl/consumer_sdl_preview.c:
-  src/modules/sdl/consumer_sdl_preview.c + Temporary rollback for linux  
-
   * configure, src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_preview.c,
   src/modules/sdl/consumer_sdl_still.c: configure + Correction to ldflags for
   src/modules/sdl/consumer_sdl_still.c + Moved initialisation of sdl components
   to the start/stop methods (Darwin requirement)  
 
-  * src/modules/motion_est/configure: + Correction to the disabled case (should
-  be disable-motion_est and plugins should not be registered)  
-
 2005-08-28  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/vmfx/Makefile, src/modules/vmfx/configure,
   alternative wipe mechanism + New producer (pgm) which provides basic
   functionality for portable grey maps  
 
-  * src/modules/core/transition_composite.c: + SMP fix - geometry modifications
-  need explicit locking  
-
-2005-08-22  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_properties.h: + Replaced this with self in new pass
-  functions for C++ compilation  
-
 2005-08-21  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_properties.c, src/framework/mlt_properties.h,
 
 2005-08-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_tractor.c: + Attempt to ensure that the aspect ratio of
-  the background is the reported ar of the output frame  
-
-  * src/modules/core/transition_composite.c: + Yet another aspect ratio
-  correction for the filter transition (not 100% correct yet...) + Correction
-  for aspect_ratio == 0 case (should honour consumer)  
-
-  * src/modules/avformat/consumer_avformat.c: + Correction for aspect ratio  
-
   * src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c:
   producer_pango.c producer_pixbuf.c + More efficient use of pixbuf objects and
   sequences/mlt pango lists  
 
 2005-08-15  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/consumer_westley.c: Fix build errors caused by the
-  (hypothetical) conversion of mlt_position from an int to a float, preserving
-  original behavior.  
-
   * src/framework/mlt_frame.c, src/framework/mlt_playlist.c,
   src/framework/mlt_playlist.h, src/framework/mlt_producer.c,
   src/framework/mlt_property.c, src/framework/mlt_types.h: Fix build errors
   Fix build errors caused by the (hypothetical) conversion of mlt_position from
   an int to a float, preserving original behavior.  
 
-2005-08-07  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/motion_est/filter_vismv.c: Misc changes. May remove this file
-  completely soon.  
-
-  * src/modules/motion_est/filter_motion_est.c: This is a significant rewrite.
-  -Cleared up as many conceptualy sticky points as possible. -Removed chroma
-  comparison code pending a better rewrite. -Added show_residual=1 and
-  show_reconstruction=1 debug modes. See README. -Renamed many variables and
-  functions. -Revamped geometry handling. -Lots more I'm forgeting.  
-
-  * src/modules/motion_est/README: Added some more examples.  
-
-  * src/inigo/inigo.c: Prevent a frame from being skipped when inigo is first
-  paused.  
-
-  * src/modules/motion_est/filter_crop_detect.c: Corrected geometry handling.
-  Removed redundant arrow drawing code. Modified thresholding.  
-
 2005-08-04  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/Makefile, src/modules/avformat/configure: ffmpeg split
   function, enabled by default; the results seem very good. Removed some unused
   development code.  
 
-2005-07-28  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kino/Makefile: + Allow header dependency checks  
-
-  * src/modules/avformat/configure: + Added an additional help message (for
-  ffmpeg suffix)  
-
-  * Makefile: + Force dependency checks on header files  
-
-2005-07-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_types.h: Do not break ABI to workaround a problem in
-  swig.  
-
-2005-07-27  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kino/producer_kino.c: + Stores the resource correctly (to allow
-  serialisation via westley)  
-
-2005-07-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_types.h: Add names to enums to make newer versions of
-  swig (noticed on 1.3.24) happy.  
-
 2005-07-26  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/filter_watermark.c: + Correction to long outstanding
-  oddity regarding composite.out - not needed in many cases now  
-
   * mlt++/swig/Makefile, mlt++/swig/configure, mlt++/swig/perl/Makefile.PL,
   mlt++/swig/python/build, mlt++/swig/tcl/build: + Cleaned up swig build so it
   doesn't require an mlt++ install first - Temporarily disabled java  
 
 2005-07-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kino/riff.cc: + Minor correction for entry length being less
-  than the data length  
-
   * src/modules/kino/avi.cc, src/modules/kino/avi.h, src/modules/kino/riff.cc,
   src/modules/kino/riff.h: + fixes for opendml dv avi  
 
-2005-07-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: - Removed 'resize' property logic and
-  width/height confusion  
-
-  * src/modules/core/filter_resize.c: + Correction for rounding errors  
-
 2005-07-21  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/dv/producer_libdv.c: - Removed unused aspect ratio property  
-
-  * src/modules/avformat/producer_avformat.c: + Hide internal properties via
-  the _ convention  
-
   * src/framework/mlt_playlist.c, src/framework/mlt_service.c: - Remove
   warnings  
 
-2005-07-21  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/motion_est/filter_motion_est.c: autotrack_rectangle and
-  motion_est now convert pixel units to macroblock (whole) units the same way. 
-
-  * .../motion_est/filter_autotrack_rectangle.c: Fixed several accuracy issues.
-  Cleaned up code. Corrected pause behavior.  
-
-2005-07-20  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * .../motion_est/filter_autotrack_rectangle.c: use shared arrow drawing code.
-  improve tracking accuracy.  
-
 2005-07-20  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_filter.c, src/framework/mlt_service.c: mlt_filter.c
 
 2005-07-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/producer_pango.c: producer_pango.c + Correction of
-  oversight - allow serialisation of mpl usage  
-
   * src/modules/avformat/consumer_avformat.c,
   src/modules/avformat/producer_avformat.c: consumer_avformat.c
   producer_avformat.c + Sync with current ffmpeg CVS - PLEASE UPDATE FFMPEG
 
 2005-07-18  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/producer_pango.c: + Mutex protection (temporary work
-  around of SMP systems) + Corrected aspect ratio (should be 1, not 0)  
-
-  * src/modules/core/producer_colour.c: + Accepts modifiable colour property
-  (via resource) + Hides non-public properties  
-
-  * src/modules/fezzik.dict: + Added convenience lookup for MLT Pango List
-  files  
-
-  * src/modules/core/filter_mirror.c: + Alpha handling in silly filter :-)  
-
-  * src/modules/core/transition_composite.c: + Inherits deinterlace method from
-  the consumer + Sanity check on scaled size for compositing  
-
   * src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c:
   producer_pango.c + Added cloning + Added the very silly .mpl (MLT Pango List)
   format [details to follow] + Corrected invalid content  producer_pixbuf.c +
   Corrected invalid content  
 
-  * src/modules/gtk2/producer_pixbuf.c: + Bug fixes to test card handling +
-  Alpha channel cloning + Minor tidy up  
-
 2005-07-16  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/framework/mlt_playlist.c,
   clean up to follow)  src/modules/dv/producer_libdv.c + Frame stored width and
   height are no longer assumed to be 'safe' here (investigating)  
 
-2005-07-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_repository.c: mlt_repository.c + VERY temporary hack to
-  avoid global symbol clashes (RTLD_GLOBAL needed by kino/libquicktime only so
-  far)  
-
-2005-07-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kino/filehandler.cc: filehandler.cc + FOURCC for DVCPRO
-  quicktime  
-
-  * src/modules/vorbis/producer_vorbis.c: producer_vorbis.c + Oops - the frame
-  position is relative to the in point (the internal position is absolute)  
-
-  * src/modules/vorbis/producer_vorbis.c: producer_vorbis.c + Fix for non-zero
-  in point  
-
 2005-07-10  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sdl/consumer_sdl_preview.c,
   src/modules/sdl/consumer_sdl_still.c: consumer_sdl_preview.c
   consumer_sdl_still.c + Fixes a deadlock condition  
 
-  * src/modules/kino/filehandler.cc: src/modules/kino/filehandler.cc + Added
-  missing fourccs to allow compilation  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h,
   src/framework/mlt_repository.c, src/modules/kino/filehandler.cc,
   src/modules/kino/filehandler.h: framework/mlt_frame.c framework/mlt_frame.h +
 
 2005-07-09  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/motion_est/configure: Mention that motion est is disabled by
-  default during ./configure.  
-
   * configure, src/modules/motion_est/configure: Prevent motion estimation
   components from building unless requested.  
 
   src/modules/motion_est/filter_vismv.c, src/modules/motion_est/sad_sse.h:
   Initial import of the motion estimation filter.  
 
-2005-07-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c:
-  src/modules/avformat/consumer_avformat.c + Correction for mpeg encoding -
-  Removal of erroneous frame rate checks  
-
 2005-07-05  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/producer_westley.c:
-  src/modules/westley/producer_westley.c - Rollback on erroneous checkin
-  (functionality covered correctly in playlist)  
-
   * src/framework/mlt_frame.c, src/framework/mlt_playlist.c,
   src/modules/core/transition_composite.c, src/modules/core/transition_luma.c,
   src/modules/fezzik.dict, src/modules/gtk2/producer_pixbuf.c,
   frame rendering notification event  test/server.cpp + Added an example frame
   rendering callback that removes all shotcut related fx  
 
-  * src/modules/sdl/consumer_sdl.c: src/modules/sdl/consumer_sdl.c + (Re)Added
-  audio volume control  
-
-  * src/framework/mlt_tractor.c: src/framework/mlt_tractor.c + Added support
-  for pango usage on audio only fx cuts (sigh...)  
-
-  * src/framework/mlt_tractor.c: src/framework/mlt_tractor.c + Slight
-  modification to allow pango use in fx cuts  
-
 2005-06-26  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/core/filter_transition.c, src/modules/core/filter_transition.h:
   example of how to hide a track on reception  swig/ruby/thumbs.rb + Changed
   generator to run, rather than sleep and poll  
 
-  * src/modules/core/transition_composite.c: + Cleaned up compositing and alpha
-  usage (all frames always have an alpha mask) + Provided an alternative
-  rendering mechanism ('or' which takes a and b alpha into account) + Provided
-  a and b alpha mask overides ('alpha_a' and 'alpha_b')  
-
 2005-06-24  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_geometry.c, src/framework/mlt_tractor.c,
   to avoid rounding errors?)  src/framework/mlt_tractor.c + corrections for
   fx_cuts (allows animated fx)  
 
-2005-06-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: + BGa's request for additional westley extensions 
-
 2005-06-22  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.h, src/framework/mlt_tractor.c,
   src/modules/sdl/consumer_sdl_preview.c src/modules/sdl/consumer_sdl_still.c +
   Takes consumer profile into account  
 
-2005-06-05  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/configure: Quick temporary fix for mlt config in non-standard
-  paths (relates to mlt++)  
-
 2005-06-04  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_tractor.c,
   src/modules/core/filter_resize.c, src/modules/xine/filter_deinterlace.c:
   Sanity checks for normalising filters  
 
-2005-06-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/fezzik.dict: libdv/avformat switching  
-
-2005-06-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/filter_avcolour_space.c: Sanity checks  
-
-  * src/modules/gtk2/producer_pixbuf.c: Fallback to testcard  
-
 2005-05-28  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/avformat/consumer_avformat.c: NTSC fix  
-
-  * src/modules/fezzik.dict: Added bmp support  
-
   * src/framework/mlt_consumer.c, src/framework/mlt_factory.c,
   src/framework/mlt_producer.c: Frame rate properites and factory
   initialisation  
 
-2005-05-27  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: audio out fix  
-
 2005-05-24  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/kino/filehandler.cc, src/modules/kino/filehandler.h: DVCPRO fix
    
 
-2005-05-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/consumer_avformat.c: jpeg and mjpeg fixes  
-
-2005-05-11  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/jackrack/filter_ladspa.c: bugfix segfault on closre when filter
-  never invoked  
-
 2005-05-09  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/westley/configure, src/modules/xine/configure: Bourne shell
   compliance  
 
-  * configure: Bourne shell compliance  
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure: Corrections
   to --avformat-cvs option  
 
   src/modules/avformat/producer_avformat.c: FFMPEG revisions to match current
   CVS (part 1)  
 
-2005-05-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/kino/Makefile: fix compilation  
-
 2005-04-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/modules/configure, src/modules/jackrack/Makefile,
   src/modules/jackrack/ui.h: cleanup and reduce code in jackrack support code
   and add new jack-less filter_ladspa.  
 
-2005-04-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/dv/producer_libdv.c: Fix for file identification and dv  
-
 2005-04-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/kino/avi.h: Minor correction  
-
   * src/modules/kino/Makefile, src/modules/kino/avi.cc, src/modules/kino/avi.h,
   src/modules/kino/configure, src/modules/kino/endian_types.h,
   src/modules/kino/error.cc, src/modules/kino/error.h,
   * src/modules/dv/producer_libdv.c, src/modules/fezzik.dict: Preparation for
   kino support  
 
-2005-04-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/dv/Makefile: corrected pkg-config libdv usage  
-
 2005-04-14  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/sdl/Makefile, src/modules/sdl/consumer_sdl_still.c: Build
   fixes.  
 
-  * src/modules/sdl/consumer_sdl.c: An unfinished attempt at porting the SDL
-  consumer to OS X. What remains is a bug in libSDL where the SDL screen object
-  becomes a NULL pointer when it shouldn't. This also affects 'ffplay' and the
-  SDL test program 'threadwin -threaded' I think.  
-
-  * src/modules/sdl/consumer_sdl_osx_hack.h: A hack to inform Cocoa that is
-  should be multithreaded by spinning of a dummy thread.  
-
   * configure, src/albino/albino.c, src/inigo/inigo.c, src/miracle/miracle.c:
   OS X uses -DDARWIN in
   /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h; This in
   combination with #include <Foundation/Foundation.h> caused compilation errors
   while porting consumer_sdl to OS X.  
 
-2005-04-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * COPYING: License update  
-
-  * src/modules/sox/Makefile, src/modules/sox/configure: Disable sox when
-  unavailable  
-
-  * src/modules/jackrack/configure: Disable jackrack when unavailable  
-
-  * src/modules/dv/configure, src/modules/vorbis/configure: Disable libdv when
-  unavailable  
-
-  * src/modules/resample/configure: Disable libsamplerate when unavailable  
-
-  * src/modules/sdl/configure: Disable sdl when unavailable  
-
-  * src/modules/vorbis/configure: Disable vorbis when unavailable  
-
-  * configure: Automatic disabling off mmx on a OS/X; mmx detection on Linux;
-  other platforms probably broken  
+2005-04-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/xine/configure: Disable xine when mmx not available  
+  * src/modules/sox/Makefile, src/modules/sox/configure: Disable sox when
+  unavailable  
 
-  * src/modules/westley/configure: Conditional compilation of westley/libxml2
-  components  
+  * src/modules/dv/configure, src/modules/vorbis/configure: Disable libdv when
+  unavailable  
 
   * src/modules/gtk2/Makefile, src/modules/gtk2/configure,
   src/modules/gtk2/factory.c: Conditional compilation of gtk2 components  
 
-2005-04-12  dezeroex <dezeroex@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_geometry.c: Minor but confusing comment fix.  
-
 2005-04-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * configure, setenv, src/albino/Makefile, src/albino/albino.c,
   src/modules/xine/configure, src/tests/Makefile, src/valerie/Makefile,
   src/valerie/valerie_socket.c: OS/X Patch from Torsten Spindler  
 
-  * mlt++/CUSTOMISING: Minor doc updates  
-
   * src/framework/mlt_factory.c, src/framework/mlt_factory.h,
   src/framework/mlt_repository.c, src/framework/mlt_repository.h: More const
   usage  
   * src/miracle/miracle_unit.c, src/modules/avformat/consumer_avformat.c: Minor
   mods to playout via avformat and miracle unit generation on an xfer  
 
-  * src/modules/westley/producer_westley.c: Reinstatement of entity handling
-  and removal of libxml2 warning for non-existent file  
-
 2005-02-18  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/modules/core/producer_colour.c,
   src/modules/plus/transition_affine.c: Minor corrections with alpha and
   affines  
 
-2005-02-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/miracle/miracle_unit.c: Smoother unit load  
-
 2005-02-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/src/MltService.cpp: Minor correction  
-
   * src/framework/mlt_producer.c, src/framework/mlt_tractor.c,
   src/modules/core/producer_colour.c, src/modules/core/transition_composite.c,
   src/modules/feeds/PAL/etv.properties, src/modules/gtk2/producer_pango.c,
 
 2005-02-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/plus/transition_affine.c: affine silliness  
-
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   src/framework/mlt_frame.c, src/framework/mlt_tractor.c,
   src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_preview.c,
 
 2005-02-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/feeds/PAL/border.properties: fill for borders  
-
-  * src/modules/gtk2/Makefile: conditional mmx compilation  
-
-  * src/modules/core/transition_composite.c: int handling on the frame image
-  stack  
-
   * src/framework/mlt_deque.c, src/framework/mlt_deque.h,
   src/framework/mlt_frame.c, src/framework/mlt_frame.h: 64 bit fix and deque
   int holding  
 
 2005-01-31  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl_preview.c: Refresh count instead of flag  
-
-  * src/modules/sdl/consumer_sdl_preview.c: Mutex locking for refresh handling 
-
-  * src/modules/core/filter_rescale.c: Warning removal  
-
-  * src/modules/resample/filter_resample.c: Workaround for test card audio (may
-  need to review)  
-
-  * src/modules/inigo/producer_inigo.c: Empty track definition fix  
-
   * src/modules/sdl/consumer_sdl_preview.c,
   src/modules/sdl/consumer_sdl_still.c: Consumer reworked  
 
-  * src/modules/plus/transition_affine.c: Pointless improvement on a bad filter
-  :-)  
-
-  * src/modules/gtk2/producer_pango.c: Memory leak fix  
-
-  * src/modules/westley/consumer_westley.c: titles and global feeds  
-
   * src/modules/feeds/PAL/border.properties,
   src/modules/feeds/PAL/data_fx.properties: Minor corrections  
 
-  * src/modules/core/filter_data_show.c: Global/local data show distinction  
-
-  * src/modules/core/Makefile: Removed superflous mmx compilation  
-
-  * src/framework/mlt_tractor.c: Global data feed handling  
-
   * src/framework/mlt_filter.c, src/framework/mlt_service.c: Wild card filter
   tracks  
 
-  * src/framework/mlt_events.c: Memory leak fix  
-
-  * src/framework/mlt_consumer.c: Small correction to deinterlacing  
-
 2005-01-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/feeds/PAL/border.properties,
   src/framework/mlt_transition.h: Transitions reworked (always_active
   capabilities); remaining audio handling switched to stacks  
 
-  * demo/mlt_news: Correction for audio mix  
-
 2005-01-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_consumer.c: consumer close fix  
-
   * src/modules/feeds/PAL/etv.properties, src/modules/gtk2/producer_pango.c:
   iconv fixes  
 
   src/modules/feeds/PAL/etv.properties: Minor modifications to compositing
   options and etv fx  
 
-  * src/modules/gtk2/producer_pango.c: Added a weight property  
-
 2005-01-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltProperties.cpp, mlt++/src/MltProperties.h: Const string usage
   in properties  
 
-  * demo/mlt_attributes: Correction for ETV specific filters  
-
-  * src/modules/feeds/PAL/etv.properties: Seperation for ETV specific filters  
-
-  * docs/testing.txt: Test case clean up  
-
   * demo/demo, demo/mlt_watermark, src/framework/mlt_producer.c,
   src/framework/mlt_properties.c, src/framework/mlt_properties.h,
   src/framework/mlt_property.c, src/framework/mlt_property.h,
   src/modules/feeds/PAL/obscure.properties, src/modules/fezzik.ini,
   src/modules/gtk2/producer_pango.c: Sundry minor fixes and optimisations  
 
-2005-01-08  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_geometry.c: Corrections to geometry next key and
-  serialise  
-
 2005-01-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltGeometry.cpp, mlt++/src/MltGeometry.h: Next/Prev key
   * src/miracle/miracle_server.c, src/miracle/miracle_server.h: Fetch unit from
   miracle server  
 
-2005-01-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_playlist.c: Correction to clip_start at end of playlist  
-
 2004-12-31  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * demo/demo.ini, src/framework/mlt_producer.c,
   src/framework/mlt_properties.c, src/framework/mlt_property.c,
   src/framework/mlt_transition.c: Corrections after valgrinding  
 
-  * mlt++/src/MltGeometry.h: Update for geometry  
-
   * demo/demo.ini, demo/mlt_attributes, demo/mlt_news, demo/mlt_slideshow,
   demo/mlt_slideshow_black, demo/mlt_squeeze, demo/mlt_ticker,
   demo/mlt_watermark: Corrections and minor fixes to use new geometry spec;
   * src/modules/feeds/NTSC/obscure.properties,
   src/modules/feeds/PAL/data_fx.properties: Feeds updates  
 
-  * src/framework/mlt_producer.c: Extension to mini fezzik for obscures on cuts
-   
-
-  * src/framework/mlt_tractor.c: Option to hold feed processing on a track  
-
-  * src/framework/mlt_playlist.c: Fix for join length correction  
-
-  * src/framework/mlt_frame.c: Resize fix for chroma offsets  
-
   * src/framework/mlt_geometry.c, src/framework/mlt_geometry.h: Improved
   geometry  
 
-2004-12-28  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/jackrack/filter_jackrack.c: bootstrap earlier with fixed number
-  of channels, better initial synchronisation phase, reduced internal buffer
-  size  
-
-  * src/modules/jackrack/filter_jackrack.c: even better close handling?  
-
-  * src/modules/jackrack/filter_jackrack.c: fixup includes  
-
-  * src/modules/jackrack/filter_jackrack.c: ensure disconnected from jack
-  before releasing any resources  
-
 2004-12-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/modules/jackrack/filter_jackrack.c: add
   * mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltGeometry.cpp,
   mlt++/src/MltGeometry.h, mlt++/swig/mltpp.i: Geometry  
 
-  * src/modules/core/transition_composite.c: Luma generation and use  
-
   * src/modules/core/transition_composite.c,
   src/modules/core/transition_luma.c, src/modules/lumas/Makefile,
   src/modules/lumas/create_lumas, src/modules/lumas/luma.c: Luma generation and
   src/modules/data_fx.properties, src/modules/xine/deinterlace.c: Framework
   inclusion of geometry  
 
-2004-12-21  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/data_fx.properties: Correction to obscure data_show config  
-
-  * src/modules/data_fx.properties: Correction to obscure data_show config  
-
 2004-12-20  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_playlist.c, src/modules/core/transition_composite.c,
 
 2004-12-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_consumer.c: Mutex protection on put frame close  
-
   * src/framework/mlt_producer.c, src/framework/mlt_service.c: Mutex locking in
   the get frame  
 
 
 2004-12-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/filter_data_feed.c: ignore attr which are active, but have
-  no value  
-
-  * src/modules/data_fx.properties: Minor mods for ETV data filters  
-
   * src/framework/mlt_consumer.c, src/framework/mlt_consumer.h,
   src/framework/mlt_factory.c, src/framework/mlt_field.c,
   src/framework/mlt_filter.c, src/framework/mlt_filter.h,
 
 2004-11-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/swig/Makefile: Install makefile for swig  
-
   * mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltDeque.cpp,
   mlt++/src/MltDeque.h, mlt++/src/MltFactory.cpp, mlt++/src/MltFactory.h,
   mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h,
   mlt++/src/MltService.h, mlt++/test/Makefile: More playlist modifications;
   service locking  
 
-  * src/modules/sdl/consumer_sdl_still.c: Consumer sdl preview correction -
-  attach colour space conversion on start  
-
   * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h,
   src/framework/mlt_producer.c, src/framework/mlt_service.c,
   src/framework/mlt_service.h: More playlist modifications; service locking;
 
 2004-11-17  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_producer.c: Extendible blank producers  
-
   * mlt++/src/MltProperties.cpp, mlt++/src/MltProperties.h,
   mlt++/src/MltTractor.cpp, mlt++/src/MltTractor.h: Ref count and event firing
   method on properties; locate_cut on tractor  
   mlt++/src/MltTractor.cpp, mlt++/src/MltTractor.h: Simplified playlist and
   track access  
 
-  * src/modules/sdl/consumer_sdl_still.c: Increased delay for polling  
-
   * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h: Simplified
   playlist access  
 
   * mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h: Added cut related
   methods  
 
-  * src/framework/mlt_multitrack.c: Behavioural change - tracks with hide
-  properties now affect length (might be problematic)  
-
-2004-11-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_producer.c: Correction for direct playback of a cut  
-
 2004-11-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/gtk2/consumer_gtk2.c, src/modules/gtk2/producer_pixbuf.c,
 
 2004-10-27  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/plus/filter_charcoal.c: Minor optimisation  
-
   * mlt++/configure, mlt++/swig/configure, mlt++/swig/ruby/build,
   mlt++/swig/ruby/miracle.rb: Config changes  
 
 
 2004-10-24  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl_preview.c: Oops - need to parse the size in
-  the preview  
-
   * mlt-config-template, src/framework/configure, src/miracle/configure,
   src/modules/gtk2/Makefile, src/modules/gtk2/configure,
   src/modules/gtk2/consumer_gtk2.c, src/modules/gtk2/consumer_gtk2.h,
 
 2004-10-21  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl_still.c: SDL Preview second checkin  
-
   * src/framework/mlt_consumer.c, src/inigo/inigo.c,
   src/modules/sdl/consumer_sdl.c, src/modules/sdl/consumer_sdl_preview.c,
   src/modules/sdl/consumer_sdl_still.c: SDL Preview second checkin  
   src/miracle/miracle_server.h: Convenience functionality for properties load
   and miracle_server_id function  
 
-  * src/miracle/miracle_server.c: Server shutdown state oops  
-
-  * mlt++/src/MltMiracle.cpp: Server shutdown state  
-
-  * src/miracle/miracle_server.c: Server shutdown state  
-
-2004-10-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/valerie/consumer_valerie.c: Error property for valerie returned
-   
-
 2004-10-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltConsumer.cpp, mlt++/src/MltConsumer.h, mlt++/test/play.cpp:
   * src/modules/westley/consumer_westley.c, src/valerie/valerie_remote.c:
   buffer fix and tractor handling  
 
-  * mlt++/HOWTO: Doc updates  
-
   * src/miracle/miracle_connection.c, src/miracle/miracle_local.c,
   src/miracle/miracle_server.c, src/miracle/miracle_unit_commands.c,
   src/miracle/miracle_unit_commands.h, src/modules/valerie/consumer_valerie.c,
   src/modules/westley/producer_westley.c: Fix for deep westleys and filter
   in/out points  
 
-  * src/framework/mlt_consumer.c: Oops - fix for consumer progressive  
-
   * docs/services.txt, src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
   src/framework/mlt_playlist.c, src/framework/mlt_properties.c,
   src/framework/mlt_tractor.c, src/inigo/inigo.c,
   * src/modules/avformat/configure, src/modules/avformat/producer_avformat.c:
   Fix for current cvs  
 
-2004-10-09  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_playlist.c: Mix on Mix and length corrections  
-
 2004-10-08  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h: Same and following clip
   * docs/framework.txt, docs/inigo.txt, docs/install.txt: Some documentation
   updates - more to follow  
 
-  * src/framework/mlt_producer.c: Removed fezzik usage from cloning  
-
 2004-10-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_filter.c, src/framework/mlt_producer.c,
   src/modules/westley/producer_westley.c: Cloning optimisations and
   introduction of the service parser  
 
-2004-10-04  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/inigo/producer_inigo.c: Allow filter attachment to clip  
-
 2004-10-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_factory.c, src/framework/mlt_service.c,
   * mlt++/README, mlt++/src/MltPlaylist.cpp, mlt++/src/MltPlaylist.h: Playlist
   repeat clip functionality  
 
-  * src/inigo/inigo.c: Clean up - added new usage options  
-
   * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h,
   src/modules/inigo/producer_inigo.c, src/modules/westley/consumer_westley.c,
   src/modules/westley/producer_westley.c: Splits, joins and repeats  
 
 2004-09-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/consumer_westley.c: Fix for serialising multiple
-  overlapping mixes  
-
-  * src/framework/mlt_playlist.c: Whoops - mix fix  
-
   * src/framework/mlt_playlist.c, src/framework/mlt_playlist.h,
   src/modules/westley/consumer_westley.c,
   src/modules/westley/producer_westley.c: Corrects cuts with filters  
   src/modules/westley/producer_westley.c: Finalisation of first phase of cut
   handling (unmanaged)  
 
-  * src/framework/mlt_transition.c: Transitions ignore test frames  
-
 2004-09-24  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_multitrack.c, src/framework/mlt_playlist.c,
   src/modules/westley/producer_westley.c: Cut management part 2 - corrects
   playlist split/join and a little bit of mix  
 
-  * src/framework/mlt_properties.c: ...gah...  
-
   * mlt++/src/MltProducer.cpp, mlt++/src/MltProducer.h, mlt++/swig/mltpp.i: Cut
   management part 1  
 
   src/framework/mlt_service.c, src/modules/westley/consumer_westley.c,
   src/modules/westley/producer_westley.c: Cut management part 1  
 
-  * src/modules/westley/consumer_westley.c: fix for in/out during serialisation
-   
-
 2004-09-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_tractor.c: Alpha from the tractor fix  
-
   * mlt++/src/MltService.cpp, mlt++/swig/mltpp.i: get_frame and ruby listen fix
    
 
 
   * mlt++/configure, mlt++/src/MltMiracle.cpp: Server shutdown  
 
-  * src/framework/mlt_properties.c: Whoops  
-
   * src/framework/mlt_factory.c, src/framework/mlt_properties.c,
   src/miracle/miracle.c, src/miracle/miracle_local.c,
   src/miracle/miracle_server.c, src/miracle/miracle_server.h,
   mlt++/src/MltMiracle.h, mlt++/src/MltResponse.cpp, mlt++/src/MltResponse.h,
   mlt++/swig/mltpp.i: Added the response object  
 
-  * src/valerie/valerie_response.h: Obtain stdio definitions  
-
   * mlt++/HOWTO, mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltMiracle.cpp,
   mlt++/src/MltMiracle.h, mlt++/swig/mltpp.i, mlt++/swig/ruby/miracle.rb,
   mlt++/test/Makefile, mlt++/test/play.cpp, mlt++/test/server.cpp: Adding
   * Makefile, src/humperdink/Makefile, src/modules/dv/producer_libdv.c: Build
   fix and temporary libdv compatability  
 
-  * src/framework/mlt_frame.c: aspect ratio fix for test card  
-
-  * src/framework/mlt_tractor.c: Aspect ratio fix  
-
-  * src/modules/sdl/consumer_sdl.c: Aspect ratio modifications  
-
-  * src/miracle/Makefile: Customising the miracle server part 1  
-
 2004-09-17  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_service.c, src/framework/mlt_service.h,
   * src/framework/mlt_frame.c, src/modules/core/transition_luma.c: Work arounds
   for scaling related issues  
 
-2004-09-13  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: position fixing  
-
 2004-09-09  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl.c: Ugly temporary hack for aspect ratio  
-
   * src/framework/mlt_playlist.c, src/inigo/inigo.c,
   src/modules/inigo/producer_inigo.c: Fixes for removed tracks before/after mix
    
 
 2004-09-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl.c: Fix occassional sdl core dumps  
-
   * mlt++/src/Makefile, mlt++/src/Mlt.h, mlt++/src/MltEvent.cpp,
   mlt++/src/MltEvent.h, mlt++/src/MltProperties.cpp, mlt++/src/MltProperties.h,
   mlt++/swig/mltpp.i, mlt++/swig/ruby/play.rb, mlt++/test/play.cpp: Event
   src/framework/mlt_frame.h, src/modules/westley/consumer_westley.c,
   src/valerie/Makefile: Minor make/configure mods and mlt_frame_waveform mod  
 
-2004-08-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_frame.c: properly deal with evaluation of magnitude of 2s
-  complement for waveform generation  
-
-  * src/framework/mlt_frame.c: new, faster waveform generator that emphasizes
-  gain as opposed to shape  
-
 2004-08-29  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_frame.c: bugfix in waveform method  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h: add waveform method
   to frame  
 
 
 2004-08-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * mlt++/swig/perl/play.pl: Added play.pl  
-
   * mlt++/src/Makefile, mlt++/swig/mltpp.i: Workaround for perl  
 
 2004-08-21  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
   * src/modules/core/filter_rescale.c, src/modules/gtk2/factory.c: Colour space
   conversion with gdkpixbuf scaling  
 
-  * src/modules/avformat/producer_avformat.c: Another attempted mjpeg work
-  around  
-
-  * src/framework/mlt_consumer.c: Prefil consumer property  
-
 2004-08-18  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/src/MltFrame.cpp, mlt++/src/MltFrame.h, mlt++/src/MltProducer.cpp,
   mlt++/src/MltFilteredProducer.h, mlt++/src/MltService.cpp,
   mlt++/src/MltService.h, mlt++/swig/mltpp.i: Filtered producers and consumers 
 
-  * src/framework/mlt_service.c: NULL accpectance for connect/disconnect  
-
-  * mlt++/test/play.cpp: oops  
-
 2004-08-16  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt++/swig/configure, mlt++/swig/java/Play.java, mlt++/swig/java/Play.sh,
   mlt++/src/MltTransition.cpp, mlt++/src/MltTransition.h, mlt++/test/Makefile,
   mlt++/test/play.cpp: Initial revision  
 
-2004-08-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: gop/b frame fix, http/pipe
-  handling and logging off  
-
 2004-08-10  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/avformat/factory.c, src/modules/avformat/filter_avcolour_space.c,
   src/modules/avformat/filter_avcolour_space.h: Colour space filter  
 
-2004-08-08  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: Rudimentary rgb24 support  
-
-  * src/modules/avformat/producer_avformat.c: optimisations  
-
-2004-08-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_region.c: Flexible and animated shapes  
-
 2004-08-05  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/configure, src/modules/avformat/producer_avformat.c:
   * src/modules/dv/consumer_libdv.c, src/modules/dv/producer_libdv.c,
   src/modules/dv/producer_libdv.h: Fix for current libdv  
 
-  * src/modules/avformat/producer_avformat.c: Pipe workaround  
-
 2004-08-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/core/filter_watermark.c, src/modules/core/transition_region.c:
   Mutable shapes on regions  
 
-2004-08-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/plus/filter_affine.c: Small modifications to allow seeking  
-
-  * src/modules/sdl/consumer_sdl.c: Rectangle added to properties  
-
 2004-07-31  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/plus/filter_invert.c: Minor fix to invert  
-
   * src/modules/core/filter_watermark.c,
   src/modules/core/transition_composite.c: Mutable watermark producer and small
   optimisation  
 
 2004-07-26  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sox/Makefile: link to mad  
-
   * src/modules/core/filter_luma.c, src/modules/core/filter_mirror.c,
   src/modules/core/transition_composite.c,
   src/modules/core/transition_region.c: Mutable properties  
 
 2004-07-23  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/transition_composite.c: Allows runtime modifications to
-  region fx  
-
   * src/modules/core/filter_region.c, src/modules/core/transition_composite.c,
   src/modules/core/transition_region.c: Allows runtime modifications to region
   fx  
 
-2004-07-22  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: Pipe support for audio or video
-  only  
-
 2004-07-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_factory.c,
   src/modules/plus/filter_sepia.h, src/modules/plus/transition_affine.c: affine
   with alpha and a broken sepia  
 
-2004-06-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/plus/transition_affine.c: Affine silliness  
-
 2004-06-14  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * configure, src/modules/configure, src/modules/core/configure,
   src/modules/plus/filter_charcoal.h, src/modules/plus/filter_invert.c,
   src/modules/plus/filter_invert.h: More silliness :-)  
 
-2004-06-09  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * configure: version bump  
-
-  * src/modules/avformat/configure: ffmpeg fixed date for cvs checkout  
-
-  * src/modules/avformat/ffmpeg.patch: ffmpeg patch for mandrake build  
-
-  * src/modules/avformat/producer_avformat.c: Temporary work around for missing
-  aspect ratio  
-
-  * src/framework/mlt_properties.c: Rudimentary arithmetic property assignment 
-
 2004-06-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/modules/core/producer_colour.c,
   src/modules/core/producer_noise.c, src/modules/fezzik.ini,
   src/modules/gtk2/producer_pixbuf.c, src/tests/charlie.c: Minor tweaks  
 
-2004-05-30  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: slightly better seeking in drop
-  frame cases  
-
-  * src/modules/sdl/consumer_sdl.c: real_time=0 fix  
-
-  * src/modules/avformat/consumer_avformat.c: Update to latest ffmpeg cvs  
-
 2004-05-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/Makefile, src/modules/avformat/configure: Yet another
   src/modules/avformat/producer_avformat.c: fix for avformat seek < gop; fix
   for avformat consumer qscale; additional avformat consumer properties  
 
-2004-05-08  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/avformat/producer_avformat.c: Removed unecessary locks in
-  avformat  
-
-2004-05-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: audio off  
-
-2004-05-06  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: aspect ratio and locking  
-
-2004-05-06  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * docs/services.txt: a clarification  
-
-  * src/modules/core/filter_resize.c: set output frame aspect to consumer
-  sample aspect, not display aspect.  
-
-  * src/modules/sdl/consumer_sdl.c: fix aspect handling when rescale != none  
-
-2004-05-05  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: last sdl fix for now (sigh)  
-
-  * src/modules/sdl/consumer_sdl.c: yet another sdl tweak (sigh)  
-
-2004-05-04  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: last sdl fix for now (sigh)  
-
 2004-05-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/consumer_avformat.c, src/modules/fezzik.ini,
   src/modules/sdl/consumer_sdl.c, src/modules/vorbis/producer_vorbis.c: minor
   clean ups; added a null consumer for easier valgrind testing  
 
-2004-05-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_consumer.c: audio/video processing swap  
-
-2004-05-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sox/filter_sox.c: fix st.h include  
-
-2004-05-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_frame.c: test card handling  
-
 2004-05-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
 
 2004-04-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * configure: version shunt  
-
   * README, configure, docs/install.txt, docs/services.txt,
   src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/avformat/consumer_avformat.c, src/modules/avformat/factory.c,
   * configure, docs/services.txt, setenv: GPL checking (provisional
   implementation), mc scaling docs  
 
-  * src/framework/mlt.h: added tokeniser to mlt header  
-
   * src/modules/configure, src/modules/core/Makefile,
   src/modules/core/configure, src/modules/core/factory.c,
   src/modules/core/filter_rescale.c, src/modules/core/filter_rescale.h,
 
 2004-04-17  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sox/Makefile: whoops - missed some libs  
-
-  * src/albino/Makefile: albino Makefile cleanup  
-
   * src/modules/dv/Makefile, src/modules/normalize/Makefile,
   src/modules/sox/Makefile: Makefile cleanup in modules  
 
 
 2004-04-16  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sox/filter_sox.c: add more comments  
-
   * src/modules/core/Makefile, src/modules/core/configure,
   src/modules/core/factory.c, src/modules/core/filter_volume.c,
   src/modules/core/filter_volume.h, src/modules/normalize/Makefile,
 
 2004-04-15  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/fezzik/producer_fezzik.c: Change defaults to LGPL deinterlace
-  and resample  
-
   * src/modules/avformat/Makefile, src/modules/avformat/configure,
   src/modules/avformat/factory.c, src/modules/avformat/filter_avdeinterlace.c,
   src/modules/avformat/filter_avdeinterlace.h,
   src/modules/avformat/consumer_avformat.c: Makefile error handling and
   consumer avformat cleanup  
 
-  * docs/install.txt: Installation docs update  
-
 2004-04-13  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/producer_avformat.c, src/modules/core/filter_resize.c,
 
 2004-04-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_frame.c: test card and aspect ratio woes continued  
-
   * src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
   src/framework/mlt_properties.c: aspect ratio and test card woes  
 
   src/modules/gtk2/filter_rescale.c, src/modules/sdl/consumer_sdl.c: hold
   modifications and test card env var  
 
-2004-04-02  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * demo/demo: remove setenv call  
-
 2004-04-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl.c: added setenv_mc  
-
   * setenv_mc, src/modules/sdl/consumer_sdl.c: added setenv_mc  
 
   * demo/demo.ini, demo/mlt_squeeze, demo/mlt_squeeze_box, docs/framework.txt,
   docs/services.txt, src/modules/core/transition_composite.c: minor mods  
 
-2004-03-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * docs/services.txt: fix something that got disordered  
-
-  * src/modules/westley/producer_westley.c: qualitfy paths of known properties
-  that take a filename with server virtual root  
-
 2004-03-30  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/albino/Makefile, src/framework/Makefile,
 
 2004-03-29  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/valerie/valerie.c: insert fix  
-
   * README, src/framework/configure, src/framework/mlt.h,
   src/framework/mlt_consumer.c, src/framework/mlt_factory.c,
   src/framework/mlt_pool.c, src/modules/avformat/Makefile,
   docs/services.txt, docs/testing.txt, docs/valerie.txt, docs/westley.txt: Doc
   formating  
 
-2004-03-26  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/miracle/configure: make install part 2 - building configs  
-
 2004-03-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * demo/entity.westley, demo/new.westley, docs/westley.txt,
   src/miracle/configure, src/valerie/configure: make install part 2 - building
   configs  
 
-  * src/modules/fezzik/Makefile: make install fix  
-
 2004-03-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * demo/entity.westley, docs/westley.txt,
   src/modules/westley/producer_westley.c: reorganized consumer_westley. added
   branch tracking and other bugfixes to producer_westley.  
 
-2004-03-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_tractor.c: tractor fix  
-
 2004-03-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * demo/mlt_fade_black, demo/mlt_push, src/modules/westley/consumer_westley.c,
   * demo/mlt_fade_black, demo/mlt_title_over_gfx,
   demo/mlt_titleshadow_watermark: couple of fixes to hidden tracks  
 
-  * src/framework/mlt_multitrack.c: ignore length of hidden tracks  
-
   * demo/consumers.ini, demo/luma1.pgm, demo/mlt_clock_in_and_out,
   demo/mlt_fade_black, demo/mlt_my_name_is, demo/mlt_news, demo/mlt_squeeze,
   demo/mlt_title_over_gfx, demo/mlt_voiceover: demo mods for reversed tracks  
 
 2004-03-23  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * docs/install.txt: minor typos  
-
   * README, demo/consumers.ini, docs/framework.txt, docs/install.txt,
   docs/services.txt, docs/westley.txt, src/albino/albino.c,
   src/humperdink/client.c, src/modules/gtk2/producer_pango.c,
   * src/framework/mlt_frame.c, src/miracle/miracle_commands.c,
   src/miracle/miracle_unit_commands.c: root corrections to miracle  
 
-  * src/valerie/valerie.c: quick valerie fix  
-
-  * docs/install.txt: Added install.txt  
-
-2004-03-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/westley/producer_westley.c: null pointer check in end_playlist 
-
-2004-03-22  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
   * src/modules/avformat/producer_avformat.c,
   src/modules/core/producer_colour.c, src/modules/dv/consumer_libdv.c,
   src/modules/fezzik/Makefile, src/modules/fezzik/configure,
 
 2004-03-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/westley/producer_westley.c: touchup on the producer in/out
-  applied to parent entry  
-
   * demo/circle.svg, demo/demo.kino, demo/new.westley, demo/svg.westley,
   src/framework/mlt_filter.c, src/framework/mlt_playlist.c,
   src/modules/fezzik.dict, src/modules/fezzik/producer_fezzik.c,
   * docs/services.txt, src/modules/avformat/producer_avformat.c: revert
   avformat pts offset change and note bug in docs  
 
-  * src/modules/inigo/producer_inigo.c: fix brokenness  
-
 2004-03-18  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/framework.txt, docs/westley.txt, src/framework/config.h,
   filter_resample to reproduce channels when producer does not create as many
   as consumer requested.  
 
-  * src/modules/core/filter_volume.c: bugfix segfault in audio normaliser as
-  well as logical bug in smoothing.  
-
   * docs/services.txt, src/modules/avformat/producer_avformat.c,
   src/modules/fezzik/producer_fezzik.c, src/modules/inigo/producer_inigo.c:
   fezzik now accepts service:resource and strips \'avformat:\' before fallback
   * demo/README, demo/consumers.ini, demo/demo, demo/mlt_clock_in_and_out,
   demo/mlt_voiceover: notes for the demo  
 
-  * demo/demo.ini: bring into sync with changes  
-
-  * src/modules/sdl/consumer_sdl.c: default progressive off  
-
   * demo/circle.png, demo/circle.svg, demo/consumers.ini, demo/luma1.pgm,
   demo/mlt_bouncy_ball, demo/mlt_composite_transition,
   demo/mlt_fade_in_and_out, demo/mlt_obscure, demo/mlt_title_over_gfx,
   demo/mlt_titleshadow_watermark, demo/mlt_voiceover: some demo updates  
 
-  * src/modules/core/transition_luma.c: fix distortion in smoothness  
-
-  * src/modules/core/filter_gamma.c: fix broken gamma  
-
-  * src/modules/core/transition_luma.c: fix field rendering  
-
-  * src/modules/core/transition_composite.c: bugfixes with field rendering  
-
-  * src/modules/dv/producer_libdv.c: fix aspect  
-
 2004-03-12  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * demo/consumers.ini, demo/demo, src/framework/mlt_consumer.c,
   src/framework/mlt_property.h, src/modules/sdl/consumer_sdl.c: more small
   optimisations  
 
-  * demo/demo: demo framework added  
-
   * demo/demo, demo/demo.ini, demo/luma1.pgm, demo/mlt_all,
   demo/mlt_audio_stuff, demo/mlt_avantika_title, demo/mlt_bouncy,
   demo/mlt_bouncy_ball, demo/mlt_clock_in_and_out,
 
 2004-03-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/transition_luma.c: reorg transition_luma to support
-  producer  
-
   * src/modules/Makefile, src/modules/core/Makefile,
   src/modules/core/configure, src/modules/core/factory.c,
   src/modules/core/filter_deinterlace.c, src/modules/core/filter_deinterlace.h,
 
 2004-03-03  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/filter_deinterlace.c: optimise deinterlace path  
-
-  * src/modules/core/producer_colour.c: producer_colour  
-
   * src/framework/mlt_frame.c, src/framework/mlt_frame.h,
   src/modules/core/Makefile, src/modules/core/configure,
   src/modules/core/factory.c, src/modules/core/producer_colour.c,
   src/modules/core/producer_colour.h: producer_colour  
 
-  * src/framework/mlt_frame.c: more accurate and scaled rgb to yuv conversion  
-
 2004-03-03  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_multitrack.c, src/framework/mlt_pool.c,
   src/modules/westley/producer_westley.c: some bugfixes, filter_shape producer,
   pixbuf takes svg xml, fezzik can take a service name  
 
-2004-03-02  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: More SDL fixes  
-
-2004-03-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/sdl/consumer_sdl.c: yet more sdl hacks  
-
 2004-03-01  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/avformat/producer_avformat.c, src/modules/dv/producer_libdv.c,
 
 2004-03-01  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/sdl/consumer_sdl.c: Minor sdl hack  
-
   * src/framework/mlt_consumer.c, src/framework/mlt_factory.c,
   src/framework/mlt_factory.h, src/framework/mlt_frame.c,
   src/framework/mlt_producer.c, src/modules/gtk2/filter_rescale.c,
   src/modules/dv/producer_libdv.c, src/modules/gtk2/producer_pango.c,
   src/modules/gtk2/producer_pixbuf.c: unique ids  
 
-2004-02-27  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/gtk2/scale_line_22_yuv_mmx.S: bugfix mmx scaling with
-  performance loss :-(  
-
 2004-02-27  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/modules/core/filter_resize.c,
   src/modules/gtk2/scale_line_22_yuv_mmx.S: mmx version of non-nearest, 2x2
   rescaling  
 
-2004-02-26  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: composite alignment fix  
-
 2004-02-26  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/modules/gtk2/Makefile, src/modules/gtk2/pixops.c,
 
 2004-02-25  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/transition_composite.c: composite key frames  
-
   * docs/TODO, src/framework/mlt_consumer.c, src/framework/mlt_frame.c,
   src/framework/mlt_frame.h, src/modules/avformat/producer_avformat.c,
   src/modules/core/filter_deinterlace.c, src/modules/core/filter_obscure.c,
   src/modules/core/transition_luma.c, src/modules/sdl/consumer_sdl.c: service
   stack, various fixes  
 
-2004-02-24  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_composite.c: field rendering fix and disable
-  scaling height when normalising pixel aspect when output pixel aspect < 1  
-
 2004-02-24  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/framework/mlt_frame.c, src/framework/mlt_producer.h,
   src/modules/vorbis/producer_vorbis.c, src/tests/Makefile,
   src/valerie/Makefile: Memory pooling part 2 and other optimisations  
 
-2004-02-19  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/transition_luma.c: more dissolve optimisation  
-
-  * src/modules/core/transition_luma.c: optimise dissolve case  
-
 2004-02-19  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * docs/services.txt, src/framework/Makefile, src/framework/mlt_factory.c,
 
 2004-02-18  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/framework/mlt_consumer.c: create consumer_progressive property on frame
-   
-
-  * src/modules/sdl/consumer_sdl.c: default progressive on  
-
-  * src/modules/westley/consumer_westley.c: consumer_westley now only puts
-  in/out as element attributes and not property elements  
-
   * src/modules/core/filter_deinterlace.c,
   src/modules/core/transition_composite.c, src/modules/core/transition_luma.c:
   split getting of b_frame image and composite  
 
   * docs/TODO, src/miracle/miracle_local.c: add TODO  
 
-2004-02-11  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_producer.c: test card handling  
-
-  * src/miracle/miracle_local.c: optional segv handling  
-
 2004-02-11  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/miracle/miracle_local.c: change segv handler to use log facility  
-
-  * src/valerie/valerie_notifier.c: cleanup  
-
   * src/framework/mlt_frame.c, src/framework/mlt_playlist.c,
   src/miracle/miracle_local.c, src/valerie/valerie_notifier.c: segv handler,
   playlist_move bugfix, resize_yuv422 optimisation  
 
 2004-02-11  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/miracle/miracle_unit.c: first of a few local tests  
-
-  * src/miracle/miracle_commands.c: first of a few local tests  
-
   * docs/testing-20040110.txt, src/framework/mlt_frame.c,
   src/miracle/miracle_unit.c, src/miracle/miracle_unit_commands.c,
   src/modules/dv/consumer_libdv.c, src/valerie/valerie_notifier.c,
 
   * src/framework/mlt_filter.c, src/framework/mlt_frame.c: filter fixes  
 
-2004-02-09  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/core/filter_volume.c: remove spurious return in get_audio  
-
-2004-02-09  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
   * src/miracle/miracle_unit.c, src/modules/dv/consumer_libdv.c: brought by a
   resizable bunny  
 
-  * src/modules/dv/consumer_libdv.c: brought by a bunny  
-
   * docs/services.txt, src/modules/gtk2/producer_pango.c: pango colour handling
    
 
   src/modules/gtk2/producer_pango.c, src/modules/gtk2/producer_pixbuf.c:
   pixbuf, composite and fezzik mirrors  
 
-2004-02-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/modules/westley/producer_westley.c: support in/out on entry and track  
-
 2004-02-07  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/producer_pango.c: pango producer rework  
-
   * src/modules/avformat/producer_avformat.c, src/modules/sdl/consumer_sdl.c,
   src/modules/westley/producer_westley.c: Minor corrections, rescale=nearest
   for sdl  
 
 2004-02-07  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/filter_rescale.c: rescale aspect handling redux  
-
   * src/modules/avformat/producer_avformat.c,
   src/modules/gtk2/filter_rescale.c, src/modules/gtk2/producer_pango.c,
   src/modules/gtk2/producer_pixbuf.c: fixup and disable rescale changes  
 
 2004-02-05  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/resample/filter_resample.c: resample fix  
-
   * docs/services.txt, setenv, src/framework/mlt_frame.c,
   src/framework/mlt_multitrack.c, src/framework/mlt_producer.c,
   src/framework/mlt_transition.c, src/miracle/miracle_unit.c,
 
 2004-02-04  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/gtk2/pixops.c: final rescale improvement and some optimisation 
-
-  * src/modules/gtk2/pixops.c: near final rescale improvements?  
-
-  * src/modules/gtk2/pixops.c: interim rescale improvements  
-
-  * src/modules/gtk2/pixops.c: interim rescale improvements  
-
   * src/modules/gtk2/pixops.c, src/modules/gtk2/pixops.h: interim rescale
   improvements  
 
   src/framework/mlt_types.h: added deque, api design for manager, minor affine
   tweaks, experimental destructor work  
 
-2004-01-31  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * docs/services.txt: doc updates  
-
-  * src/modules/core/filter_volume.c: configurable window size on volume
-  normalisation, also set default of max_gain to 20dB  
-
-2004-01-30  lilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
-
-  * src/framework/mlt_frame.c: updated affine  
-
 2004-01-30  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * src/framework/mlt_frame.c, src/modules/avformat/producer_avformat.c,
 
 2004-01-28  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
-  * src/modules/core/filter_volume.c: comment some diagnostics  
-
   * docs/services.txt, src/modules/core/filter_volume.c: doc updates; property
   changes, and tweaks for volume filter normalisation  
 
   src/modules/westley/consumer_westley.c,
   src/modules/westley/producer_westley.c: updated westley  
 
-  * src/tests/dan.c: test cvs  
-
 2004-01-22  ddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
 
   * mlt/src/modules/westley/consumer_westley.c,
index f8434bc1dbc59c7b4d5ab034df9970510108cf1d..3358759f47de4b8ece3d4fead5ac25353a7223eb 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME = mlt
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER = 0.7.6
+PROJECT_NUMBER = 0.8.8
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 
diff --git a/GPLv3 b/GPLv3
new file mode 100644 (file)
index 0000000..94a9ed0
--- /dev/null
+++ b/GPLv3
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, 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
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU 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
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state 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 program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
index a2025c5ef8de0a27b2c19c8c664d716f62880721..cf10b4421deef0c728afbb20786d9beebb743c3b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,15 +28,21 @@ install:
        install -d "$(DESTDIR)$(prefix)/bin"
        install -d "$(DESTDIR)$(prefix)/include"
        install -d "$(DESTDIR)$(libdir)"
-       install -d "$(DESTDIR)$(libdir)/mlt"
+       install -d "$(DESTDIR)$(moduledir)"
+ifeq ($(extra_versioning), true)
+       ln -s "$(moduledir)" "$(DESTDIR)$(unversionedmoduledir)"
+endif
        install -d "$(DESTDIR)$(libdir)/pkgconfig"
-       install -d "$(DESTDIR)$(prefix)/share/mlt"
+       install -d "$(DESTDIR)$(mltdatadir)"
+ifeq ($(extra_versioning), true)
+       ln -s "$(mltdatadir)" "$(DESTDIR)$(unversionedmltdatadir)"
+endif
        install -c -m 644 *.pc "$(DESTDIR)$(libdir)/pkgconfig"
        list='$(SUBDIRS)'; \
        for subdir in $$list; do \
                $(MAKE) DESTDIR=$(DESTDIR) -C $$subdir $@ || exit 1; \
        done
-       cp -R presets "$(DESTDIR)$(prefix)/share/mlt"
+       cp -R presets "$(DESTDIR)$(mltdatadir)"
 
 uninstall:
        rm -f "$(DESTDIR)$(bindir)"/mlt-config
@@ -47,13 +53,16 @@ uninstall:
                $(MAKE) DESTDIR=$(DESTDIR) -C $$subdir $@ || exit 1; \
        done
        rm -rf "$(DESTDIR)$(prefix)/include/mlt"
+       rm -rf "$(DESTDIR)$(mltdatadir)"
+ifeq ($(compat_dirs), true)
        rm -rf "$(DESTDIR)$(prefix)/share/mlt"
+endif
 
 dist:
        git archive --format=tar --prefix=mlt-$(version)/ v$(version) | gzip >mlt-$(version).tar.gz
 
 validate-yml:
-       for file in `find ./ -type f -name \*.yml`; do \
+       for file in `find src/modules -type f -name \*.yml`; do \
                echo "validate: $$file"; \
-               kwalify -f src/framework/metaschema.yaml $$file; \
+               kwalify -f src/framework/metaschema.yaml $$file || exit 1; \
        done
diff --git a/NEWS b/NEWS
index e0b68a48006df30f279100e4f55d531f9db01bf3..aefee7f753a5133098590f1193d76e5d5b42bdd9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,71 @@
 MLT Release Notes
 -----------------
 
+Version 0.8.8 - January 20, 2013
+
+This is purely a bugfix release. See the ChangeLog or git log.
+
+
+Version 0.8.6 - November 14, 2012
+
+This is a re-issue of the 0.8.4 release with a fix for a performance
+regression on videos that use full-range colorspaces such as yuv420p.
+
+Version 0.8.4 - November 13, 2012
+
+This is a bugfix and minor enhancement release.
+
+* Added playlist-next event and PlaylistNextListener to Ruby binding
+* FFmpeg 1.0 and libAV master compatibility
+* Improvements to motion_est filter to generate keyframes for apps
+* Added audiolevel (measurement) filter
+
+
+Version 0.8.2 - August 28, 2012
+
+This is a bugfix and minor enhancement release.
+
+* Overhaul of A/V sync with libavformat-based inputs.
+* Fix a major memory leak introduced in previous release.
+* Fixes to problems revealed by Coverity Scan static analysis.
+* Improved encoding presets.
+* melt can now be built without SDL with define MELT_NOSDL, which is handy
+  for running it as a child process on Windows and OS X.
+* melt can now be signaled to quit, which also makes it more useful as a
+  child process.
+
+Special thanks to Mikko Rapeli who provided many of the Coverity fixes.
+
+
+Version 0.8.0 - June 1, 2012
+
+The minor version is increased due to the addition of time properties!
+The soname version increased in the process because some mlt_property
+functions changed; however, very few if any apps actually directly use
+mlt_property preferring to use mlt_properties instead. In addition:
+
+* improve seek speed on AVCHD when using FFmpeg v0.9.1+ (NOT Libav!)
+* composite and dissolve speed improvements on x86-64
+* improve performance of caching in image producers
+* add device enumeration to decklink producer and consumer
+
+Special thanks go to contributors Maksym Veremeyenko and Ed Rogalsky.
+
+
+Version 0.7.8 - February 13, 2012
+
+This is a bugfix and minor enhancement release.
+
+* Improved support for v53 of libavcodec/libavformat
+* Added "multi" consumer - multiple, simultanous outputs
+* Added framerate adaption to "consumer" producer and "multi" consumer
+* Can now use YADIF deinterlacer with decklink producer
+* Added "rtaudio" consumer for native audio support on multiple platforms
+* Added ability to request image format closest to source (mlt_image_none)
+* Added more audio formats
+* Added vqm (video quality measurement) transition
+
+
 Version 0.7.6 - October 31, 2011
 
 This is a bugfix and minor enhancement release.
index 52ff24d5f233073ed53a2f8e480518d0aa880b3e..23521d16645ba32b67dbeed0dc0ddef668eb2168 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-export version=0.7.7
-export soversion=4
+export version=0.8.8
+export soversion=5
 
 show_help()
 {
@@ -14,18 +14,23 @@ Help options:
 
 General build options:
 
-  --prefix=directory      - install prefix for path (default: $prefix)
-  --libdir=directory      - lib directory (default: $prefix/lib)
-  --datadir=directory     - data directory (default: $prefix/share)
-  --mandir=directory      - man documentation directory (default: $prefix/share/man)
-  --enable-gpl            - Enable GPL components
-  --enable-debug          - Compile without optimizations support (default: off)
-  --disable-debug         - Compile without debug support (default: on)
-  --disable-mmx           - Compile without MMX support (default: on)
-  --disable-sse           - Compile without SSE support (default: on)
-  --disable-sse2          - Compile without SSE2 support (default: on)
-  --arch='arch'           - Compile for a specific architecture (default: none)
-  --cpu='cpu'             - Compile for a specific CPU (default: none)
+  --prefix=directory         - install prefix for path (default: $prefix)
+  --libdir=directory         - lib directory (default: $prefix/lib)
+  --datadir=directory        - data directory (default: $prefix/share)
+  --mandir=directory         - man documentation directory (default: $prefix/share/man)
+  --rename-melt              - Give melt executable a different name (it will not be versioned)
+  --enable-extra-versioning  - Version melt and the data and modules directories
+  --enable-gpl               - Enable GPLv2 components
+  --enable-gpl3              - Enable GPLv3 components
+  --enable-debug             - Compile without optimizations support (default: off)
+  --disable-debug            - Compile without debug support (default: on)
+  --disable-mmx              - Compile without MMX support (default: on)
+  --disable-sse              - Compile without SSE support (default: on)
+  --disable-sse2             - Compile without SSE2 support (default: on)
+  --arch='arch'              - Compile for a specific architecture (default: none)
+  --cpu='cpu'                - Compile for a specific CPU (default: none)
+  --target-os='os'           - Cross-compile to a specific OS (default: $(uname -s))
+  --target-arch='arch'       - Cross-compile to a specific CPU architecture
 
 Module disable options:
 
@@ -52,6 +57,8 @@ build_config()
                echo "bindir=$prefix/bin"
                echo "datadir=$datadir"
                echo "mandir=$mandir"
+               echo "extra_versioning=$extra_versioning"
+               echo "melt_noversion=$melt_noversion"
                echo "targetos=$targetos"
 
                [ "$mmx" = "true" ] && 
@@ -68,6 +75,7 @@ build_config()
 
                echo "LARGE_FILE=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE"
 
+               [ "$amd64" = "true" ] && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                [ "$arch" != "" ] && echo "TARGETARCH=-march=$arch"
                [ "$cpu" != "" ] && echo "TARGETCPU=-mcpu=$cpu"
                if [ "$optimisations" = "true" ]
@@ -83,13 +91,11 @@ build_config()
 
                case $targetos in
                Darwin)
-               sysctl -a hw | grep "x86_64: 1" > /dev/null && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                echo "CFLAGS+=-fPIC -D__DARWIN__ `sdl-config --cflags`"
                echo "SHFLAGS=-dynamiclib"
                echo "LDFLAGS+=`sdl-config --libs`"
                ;;
                Linux|GNU/kFreeBSD|GNU)
-               [ "$(uname -m)" = "x86_64" ] && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                [ "$optimisations" = "true" ] &&
                        echo "OPTIMISATIONS+=-ffast-math"
                echo "CFLAGS+=-fPIC -pthread"
@@ -99,7 +105,6 @@ build_config()
                echo "LDFLAGS+=-Wl,--no-undefined -Wl,--as-needed"
                ;;
                FreeBSD)
-               [ "$(uname -m)" = "amd64" -o "$(uname -m)" = "x86_64" ] && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                [ "$optimisations" = "true" ] &&
                        echo "OPTIMISATIONS+=-ffast-math"
                echo "CFLAGS+=-fPIC -pthread"
@@ -108,16 +113,14 @@ build_config()
                echo "LDFLAGS+=-Wl,--no-undefined -Wl,--as-needed"
                ;;
                NetBSD)
-               [ "$(uname -m)" = "amd64" ] && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                [ "$optimisations" = "true" ] &&
                        echo "OPTIMISATIONS+=-ffast-math"
-               echo "CFLAGS+=-pthread"
+               echo "CFLAGS+=-fPIC -pthread"
                echo "SHFLAGS=-shared"
                echo "RDYNAMIC=-rdynamic"
                echo "LDFLAGS+=-Wl,--no-undefined -Wl,--as-needed"
                ;;
                MinGW)
-               [ "$(uname -m)" = "x86_64" ] && echo "ARCH_X86_64=1" && echo "CFLAGS+=-DARCH_X86_64"
                [ "$optimisations" = "true" ] &&
                        echo "OPTIMISATIONS+=-ffast-math"
                echo "SHFLAGS=-shared"
@@ -129,6 +132,11 @@ build_config()
                ;;
                esac
                echo "LIBSUF=$LIBSUF"
+               echo "moduledir=${moduledir}"
+               echo "mltdatadir=${mltdatadir}"
+               echo "unversionedmoduledir=${unversionedmoduledir}"
+               echo "unversionedmltdatadir=${unversionedmltdatadir}"
+               echo "meltname=${meltname}"
        ) > config.mak
 
        echo "#!/bin/sh" > mlt-config
@@ -156,6 +164,9 @@ build_pkgconfig()
                echo version=$version
                echo cflags=`grep ^framework packages.dat | cut -f 2`
                echo libs=`grep ^framework packages.dat | cut -f 3`
+               echo moduledir=${moduledir}
+               echo mltdatadir=${mltdatadir}
+               echo meltbin=${prefix}/bin/${meltname}
        ) >> mlt-framework.pc
        cat mlt-framework.pc.in >>mlt-framework.pc
 
@@ -189,21 +200,67 @@ export mmx=true
 export sse=true
 export sse2=true
 export gpl=false
+export gpl3=false
 export arch=
 export cpu=
-export targetos=
+export targetos=$(uname -s)
+export targetarch=
+export amd64=false
+export extra_versioning=false
+export melt_noversion=false
+
+# Define the compiler used in tests (gcc is not installed everywhere)
+: ${CC:=gcc}
+
+# Iterate through arguments
+for i in "$@"
+do
+       case $i in
+               --help )                        help=1 ;;
+               --prefix=* )                    prefix="${i#--prefix=}" ;;
+               --libdir=* )                    libdir="${i#--libdir=}" ;;
+               --datadir=* )                   datadir="${i#--datadir=}" ;;
+               --mandir=* )                    mandir="${i#--mandir=}" ;;
+               --rename-melt=* )               meltname="${i#--rename-melt=}"; melt_noversion=true ;;
+               --enable-extra-versioning )     extra_versioning=true ;;
+               --enable-debug )                optimisations=false ;;
+               --disable-debug )               debug=false ;;
+               --disable-mmx )                 mmx=false; sse=false; sse2=false ;;
+               --disable-sse )                 sse=false; sse2=false ;;
+               --disable-sse2 )                sse2=false ;;
+               --enable-gpl )                  gpl=true ;;
+               --enable-gpl3 )                 gpl3=true ;;
+               --arch=* )                      arch="${i#--arch=}" ;;
+               --cpu=* )                       cpu="${i#--cpu=}" ;;
+               --target-os=* )                 targetos="${i#--target-os=}" ;;
+               --target-arch=* )               targetarch="${i#--target-arch=}" ;;
+       esac
+done
+
+if [ -z "${meltname}" ]
+then
+       if [ "$extra_versioning" = "false" ]
+       then
+               meltname=melt
+       else
+               meltname=melt${soversion}
+       fi
+fi
 
-# Determine OS
-targetos=$(uname -s)
 # Chose appropriate suffix for libraries
 case $targetos in
        Darwin)
        LIBSUF=".dylib"
+       if [ "$targetarch" = "" ]
+       then
+               sysctl -a hw | grep "x86_64: 1" > /dev/null
+               [ "$?" = "0" ] && targetarch="amd64"
+       fi
        ;;
        Linux|FreeBSD|NetBSD)
        LIBSUF=".so"
        ;;
-       MINGW32_NT-*)
+       MINGW32_NT-*|MinGW|mingw)
        targetos="MinGW"
        LIBSUF=".dll"
        ;;
@@ -213,31 +270,26 @@ case $targetos in
 esac
 export LIBSUF
 
-# Iterate through arguments
-for i in "$@"
-do
-       case $i in
-               --help )                        help=1 ;;
-               --prefix=* )            prefix="${i#--prefix=}" ;;
-               --libdir=* )            libdir="${i#--libdir=}" ;;
-               --datadir=* )           datadir="${i#--datadir=}" ;;
-               --mandir=* )            mandir="${i#--mandir=}" ;;
-               --enable-debug )        optimisations=false ;;
-               --disable-debug )       debug=false ;;
-               --disable-mmx )         mmx=false; sse=false; sse2=false ;;
-               --disable-sse )         sse=false; sse2=false ;;
-               --disable-sse2 )        sse2=false ;;
-               --enable-gpl )          gpl=true ;;
-               --arch=* )                      arch="${i#--arch=}" ;;
-               --cpu=* )                       cpu="${i#--cpu=}" ;;
-       esac
-done
+# Determine if we are compiling for 64-bit Intel architecture
+[ "$targetarch" = "" ] && targetarch=$(uname -m)
+[ "$targetarch" = "amd64" -o "$targetarch" = "x86_64" ] && amd64=true
 
 # Determine the libdir if it's not specified in the args
 [ "$libdir" = "" ] && libdir=$prefix/lib
 [ "$datadir" = "" ] && datadir=$prefix/share
 [ "$mandir" = "" ] && mandir=$prefix/share/man
 
+export unversionedmoduledir=${libdir}/mlt
+export unversionedmltdatadir=${datadir}/mlt
+if [ "$extra_versioning" = "false" ]
+then
+export moduledir=${libdir}/mlt
+export mltdatadir=${datadir}/mlt
+else
+export moduledir=${libdir}/mlt-${soversion}
+export mltdatadir=${datadir}/mlt-${soversion}
+fi
+
 # Double check MMX (Darwin, Linux and FreeBSD supported, may end up disabling MMX on other platforms incorrectly)
 if [ "$mmx" = "true" ]
 then
@@ -315,7 +367,7 @@ do
                [ $help = 0 ] && echo "Configuring `basename $i`:"
                olddir=`pwd`
                cd src/$i
-               ./configure "$@"
+               CC="$CC" ./configure "$@"
                [ $? != 0 ] && exit 1
                cd $olddir
        fi
@@ -324,8 +376,16 @@ done
 # Build the pkg-config files
 build_pkgconfig
 
-# Report GPL Usage
-[ $help != 1 ] && 
-( [ "$gpl" = "false" ] && 
-echo "GPL Components are disabled" || 
-echo "GPL License Used" )
+# Report license Usage
+if [ $help != 1 ]
+then
+       if [ "$gpl" = "false" ]
+       then
+               echo "LGPLv2.1 license used; GPL components disabled"
+       elif [ "$gpl3" = "false" ]
+       then
+               echo "GPLv2 license used; GPLv3 components disabled"
+       else
+               echo "GPLv3 license used"
+       fi
+fi
index 47db797e8ea249dfbc4f92bca13a8a93076136da..14f14cfe24dc8720cb5d9ca04c4fb90247ce0d3a 100644 (file)
@@ -1,7 +1,7 @@
 melt \
 clip1.dv out=299 \
 -track \
-colour:black out=299 \
+colour:0 out=299 \
 -track \
 "+The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog..txt" \
 out=299 \
index 0ea31b84e03a87015faec3a246bf589f8a66bb73..3594502b6931bcf3f29c0556de493c736ead3951 100644 (file)
@@ -1,5 +1,5 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.36.
-.TH MELT "1" "July 2011" "MLT melt 0.7.6" "User Commands"
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.38.4.
+.TH MELT "1" "January 2013" "melt 0.8.8" "User Commands"
 .SH NAME
 melt \- author, play, and encode multitrack audio/video compositions
 .SH SYNOPSIS
@@ -125,7 +125,7 @@ Add a video\-only track
 .PP
 For more help: <http://www.mltframework.org/>
 .SH COPYRIGHT
-Copyright \(co 2002-2011 Ushodaya Enterprises Limited
+Copyright \(co 2002\-2012 Ushodaya Enterprises Limited
 <http://www.mltframework.org/>
 .br
 This is free software; see the source for copying conditions.  There is NO
index 0a6c1eedfcb5847d612183a0475930f97d96c649..41312a7ca2dee20c32ab33438eb020de2562d0cc 100644 (file)
@@ -202,6 +202,7 @@ Tractors:
            <entry producer="producer0" in="0" out="2999"/>
            <blank length="1000"/>
            <entry producer="producer0" in="3000" out="6999"/>
+         </playlist>
          <playlist id="playlist1">
            <blank length="3000"/>
            <entry producer="producer1" in="0" out="999"/>
@@ -256,6 +257,7 @@ Tractors:
            <entry producer="producer0" in="0" out="2999"/>
            <blank length="1000"/>
            <entry producer="producer0" in="3000" out="6999"/>
+         </playlist>
          <playlist id="playlist1">
            <blank length="3000"/>
            <entry producer="producer1" in="0" out="999"/>
diff --git a/presets/consumer/avformat/AAC b/presets/consumer/avformat/AAC
new file mode 100644 (file)
index 0000000..06b4ae6
--- /dev/null
@@ -0,0 +1,7 @@
+f=mp4
+acodec=aac
+ab=256k
+vn=1
+video_off=1
+meta.preset.extension=m4a
+meta.preset.note=audio only
diff --git a/presets/consumer/avformat/Flash b/presets/consumer/avformat/Flash
new file mode 100644 (file)
index 0000000..4984d3b
--- /dev/null
@@ -0,0 +1,13 @@
+f=flv
+
+acodec=libmp3lame
+ab=128k
+ar=44100
+
+vcodec=flv
+minrate=0
+vb=1M
+progressive=1
+
+meta.preset.extension=flv
+meta.preset.note=This is the old Sorenson H.263-based codec. Most people use H.264 with Flash now.
diff --git a/presets/consumer/avformat/MJPEG b/presets/consumer/avformat/MJPEG
new file mode 100644 (file)
index 0000000..5120f5c
--- /dev/null
@@ -0,0 +1,8 @@
+f=avi
+vcodec=mjpeg
+qscale=4
+acodec=libmp3lame
+ab=256k
+threads=1
+
+meta.preset.extension=avi
diff --git a/presets/consumer/avformat/MP3 b/presets/consumer/avformat/MP3
new file mode 100644 (file)
index 0000000..0ea3a4c
--- /dev/null
@@ -0,0 +1,8 @@
+f=mp3
+acodec=mp3
+ab=256k
+vn=1
+video_off=1
+
+meta.preset.extension=mp3
+meta.preset.note=audio only
diff --git a/presets/consumer/avformat/MPEG-2 b/presets/consumer/avformat/MPEG-2
new file mode 100644 (file)
index 0000000..1f67260
--- /dev/null
@@ -0,0 +1,18 @@
+f=mpeg
+
+acodec=mp2
+ab=256k
+ar=48000
+
+vcodec=mpeg2video
+minrate=0
+vb=8M
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=mpg
+meta.preset.note=a general purpose MPEG-2 preset
diff --git a/presets/consumer/avformat/MPEG-4 b/presets/consumer/avformat/MPEG-4
new file mode 100644 (file)
index 0000000..b5e1ef0
--- /dev/null
@@ -0,0 +1,18 @@
+f=mp4
+
+acodec=libmp3lame
+ab=128k
+ar=44100
+
+vcodec=mpeg4
+minrate=0
+vb=2M
+mbd=rd
+trellis=1
+flags=+mv4+aic
+cmp=satd
+subcmp=satd
+progressive=1
+
+meta.preset.extension=mp4
+meta.preset.note=Part 2 Simple Profile
diff --git a/presets/consumer/avformat/MPEG-4-ASP b/presets/consumer/avformat/MPEG-4-ASP
new file mode 100644 (file)
index 0000000..c9d8d82
--- /dev/null
@@ -0,0 +1,19 @@
+f=mp4
+
+acodec=libmp3lame
+ab=128k
+ar=44100
+
+vcodec=mpeg4
+minrate=0
+vb=2M
+mbd=rd
+trellis=1
+cmp=satd
+subcmp=satd
+
+bf=2
+flags=+mv4+aic+qpel
+
+meta.preset.extension=mp4
+meta.preset.note=Part 2 Advanced Simple Profile
index 189a3f38154d8fb38010b071aa170bb9c0ca7f54..3b55dd6f8f43d69f3d8908d739ba72a6b9b18e71 100644 (file)
@@ -13,10 +13,12 @@ vcodec=libx264
 threads=0
 vpre=medium
 preset=medium
-profile=main
+vprofile=main
 flags2=-dct8x8
 vb=1M
 refs=1
 bf=1
 x264opts=ref=1:bframes=1
 
+meta.preset.extension=mp4
+meta.preset.note=for Sony PlayStation Portable
diff --git a/presets/consumer/avformat/Vorbis b/presets/consumer/avformat/Vorbis
new file mode 100644 (file)
index 0000000..ad34202
--- /dev/null
@@ -0,0 +1,9 @@
+f=ogg
+acodec=vorbis
+ab=256k
+vn=1
+video_off=1
+
+meta.preset.name=Ogg Vorbis
+meta.preset.extension=ogg
+meta.preset.note=audio only
diff --git a/presets/consumer/avformat/WAV b/presets/consumer/avformat/WAV
new file mode 100644 (file)
index 0000000..334f8e7
--- /dev/null
@@ -0,0 +1,7 @@
+f=wav
+acodec=pcm_s16le
+vn=1
+video_off=1
+
+meta.preset.extension=wav
+meta.preset.note=audio only
index 5bb46f27bfac8fce291d89c8bfa03dfdc8cb7b1e..dcfd44f7a92a1654d8243a409c9e11d2bb50bf5c 100644 (file)
@@ -16,3 +16,6 @@ bf=2
 vtag=xd5c
 
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=use with mxf or mov
index e8d7a5052a87c75353084f87622754d2b4edfb39..45e9d17f070045728a93242b1fe3e28ec8f0eea5 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=185M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index ce9998c35c286b0e4f99917d95702170d106164d..d5d01b17adb3459b3c7af9be06454a036da7aa0c 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=175M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index ce9998c35c286b0e4f99917d95702170d106164d..d5d01b17adb3459b3c7af9be06454a036da7aa0c 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=175M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index e8d7a5052a87c75353084f87622754d2b4edfb39..45e9d17f070045728a93242b1fe3e28ec8f0eea5 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=185M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index e8d7a5052a87c75353084f87622754d2b4edfb39..45e9d17f070045728a93242b1fe3e28ec8f0eea5 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=185M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index 1d5010fe902cd8ef31fa0024e7cd62fa1d2fac3f..40e1564dd928fdc66b01fe4267b163f3977f2b16 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=90M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index ce9998c35c286b0e4f99917d95702170d106164d..d5d01b17adb3459b3c7af9be06454a036da7aa0c 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=175M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index b29ae781e51fa055b234ad90bb3bd99340c027fe..07045855ddf5727c279f6b32e83409eed94653e0 100644 (file)
@@ -3,3 +3,6 @@ vcodec=dnxhd
 vb=220M
 threads=2
 acodec=pcm_s16le
+
+meta.preset.extension=mov
+meta.preset.note=A lightly compressed intermediate codec developed by Avid also known as SMPTE VC-3
index 039ec6439e62d9843cf5d20aedc692147d6a11f4..21a2d9ac24d6d4ff93e7b1ca217025bda0794614 100644 (file)
@@ -17,3 +17,6 @@ rc_buf_aggressivity=0.25
 
 acodec=pcm_s16le
 
+
+meta.preset.extension=mxf
+meta.preset.note=Intra-frame only, 50 Mb/s MPEG-2 also known as Sony IMX or SMPTE 365M
index d1b17377c8f9dbb9d86952484dc16187dac0ce17..93624fc54befeb50c33ebb40e4084b7880c5d492 100644 (file)
@@ -2,3 +2,4 @@ pix_fmt=yuv411p
 vcodec=dvvideo
 acodec=pcm_s16le
 
+meta.preset.note=The popular standard definition camcorder digital video format
index 2744e524b352961fb4b162e4aae6ce079e2c9e90..742aec5db5b476147ed6e07c5ce66278ca1b6f2e 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv422p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=Double the amount of chroma as normal DV
index 8a9c0119eb8f7c293c7d57223e9e53e4e038cb97..57aa76efcd39df3a16e33ecde2532ce46439d7a5 100644 (file)
@@ -13,3 +13,6 @@ g=18
 me_range=63
 trellis=1
 
+
+meta.preset.extension=vob
+meta.preset.note=Process the output with a DVD authoring tool such as dvdauthor.
index 039ec6439e62d9843cf5d20aedc692147d6a11f4..21a2d9ac24d6d4ff93e7b1ca217025bda0794614 100644 (file)
@@ -17,3 +17,6 @@ rc_buf_aggressivity=0.25
 
 acodec=pcm_s16le
 
+
+meta.preset.extension=mxf
+meta.preset.note=Intra-frame only, 50 Mb/s MPEG-2 also known as Sony IMX or SMPTE 365M
index 7eaa6b56bebd8f14966ac5bf24ebfeec73a2eed1..93624fc54befeb50c33ebb40e4084b7880c5d492 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv411p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=The popular standard definition camcorder digital video format
index 2744e524b352961fb4b162e4aae6ce079e2c9e90..742aec5db5b476147ed6e07c5ce66278ca1b6f2e 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv422p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=Double the amount of chroma as normal DV
index 8a9c0119eb8f7c293c7d57223e9e53e4e038cb97..57aa76efcd39df3a16e33ecde2532ce46439d7a5 100644 (file)
@@ -13,3 +13,6 @@ g=18
 me_range=63
 trellis=1
 
+
+meta.preset.extension=vob
+meta.preset.note=Process the output with a DVD authoring tool such as dvdauthor.
index a527ab58d745dafadf859bdd2d9601e43b02bb37..b4a0e49412ed8f2faf34a8d7bd247e328f78c8fc 100644 (file)
@@ -18,3 +18,5 @@ rc_buf_aggressivity=0.25
 
 acodec=pcm_s16le
 
+meta.preset.extension=mxf
+meta.preset.note=Intra-frame only, 50 Mb/s MPEG-2 also known as Sony IMX or SMPTE 365M
index 408bb3cdc18560e6ac504104783359a6f61e3c20..6e24b5e71b49a92c2c0fd59d101bf897d8b2e9f2 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv420p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=The popular standard definition camcorder digital video format
index 2744e524b352961fb4b162e4aae6ce079e2c9e90..742aec5db5b476147ed6e07c5ce66278ca1b6f2e 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv422p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=Double the amount of chroma as normal DV
index 4641e15e1c60aa069e37968ec514a61a8ffdff78..ce6673438a5987462f51925f7bea117a0f36c691 100644 (file)
@@ -12,3 +12,6 @@ ar=48000
 g=15
 me_range=63
 trellis=1
+
+meta.preset.extension=vob
+meta.preset.note=Process the output with a DVD authoring tool such as dvdauthor.
index a527ab58d745dafadf859bdd2d9601e43b02bb37..b4a0e49412ed8f2faf34a8d7bd247e328f78c8fc 100644 (file)
@@ -18,3 +18,5 @@ rc_buf_aggressivity=0.25
 
 acodec=pcm_s16le
 
+meta.preset.extension=mxf
+meta.preset.note=Intra-frame only, 50 Mb/s MPEG-2 also known as Sony IMX or SMPTE 365M
index 408bb3cdc18560e6ac504104783359a6f61e3c20..6e24b5e71b49a92c2c0fd59d101bf897d8b2e9f2 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv420p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=The popular standard definition camcorder digital video format
index 2744e524b352961fb4b162e4aae6ce079e2c9e90..742aec5db5b476147ed6e07c5ce66278ca1b6f2e 100644 (file)
@@ -1,3 +1,5 @@
 pix_fmt=yuv422p
 vcodec=dvvideo
 acodec=pcm_s16le
+
+meta.preset.note=Double the amount of chroma as normal DV
index 0b02b70ca56cdc7f2137dca095ba1e80fc06f17b..dae1936bb3d731e0fea207a1a3f9240fc9c71709 100644 (file)
@@ -13,3 +13,6 @@ g=15
 me_range=63
 trellis=1
 
+
+meta.preset.extension=vob
+meta.preset.note=Process the output with a DVD authoring tool such as dvdauthor.
diff --git a/presets/consumer/avformat/hdv_1080_25p/HDV b/presets/consumer/avformat/hdv_1080_25p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_1080_30p/HDV b/presets/consumer/avformat/hdv_1080_30p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_1080_50i/HDV b/presets/consumer/avformat/hdv_1080_50i/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_1080_60i/HDV b/presets/consumer/avformat/hdv_1080_60i/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_720_25p/HDV b/presets/consumer/avformat/hdv_720_25p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_720_30p/HDV b/presets/consumer/avformat/hdv_720_30p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_720_50p/HDV b/presets/consumer/avformat/hdv_720_50p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/hdv_720_60p/HDV b/presets/consumer/avformat/hdv_720_60p/HDV
new file mode 100644 (file)
index 0000000..b5edebb
--- /dev/null
@@ -0,0 +1,19 @@
+f=mpegts
+
+acodec=mp2
+ab=384k
+ar=48000
+ac=2
+
+vcodec=mpeg2video
+vb=25M
+g=15
+trellis=1
+bf=2
+b_strategy=1
+mbd=rd
+cmp=satd
+subcmp=satd
+
+meta.preset.extension=m2t
+meta.preset.note=HD MPEG-2 camcorder format
diff --git a/presets/consumer/avformat/lossless/FFV1 b/presets/consumer/avformat/lossless/FFV1
new file mode 100644 (file)
index 0000000..1f09f1d
--- /dev/null
@@ -0,0 +1,7 @@
+f=mkv
+acodec=flac
+vcodec=ffv1
+threads=1
+
+meta.preset.extension=mkv
+meta.preset.note=FFmpeg video codec 1 with FLAC audio in Matroska container
diff --git a/presets/consumer/avformat/lossless/H.264 b/presets/consumer/avformat/lossless/H.264
new file mode 100644 (file)
index 0000000..c28ed6e
--- /dev/null
@@ -0,0 +1,15 @@
+f=mp4
+acodec=aac
+ab=384k
+vcodec=libx264
+intra=1
+vb=0
+g=0
+bf=0
+preset=medium
+qscale=1
+qp=0
+coder=ac
+
+meta.preset.extension=mp4
+meta.preset.note=Intra-frame only, lossless compressed MPEG-4 AVC with AAC audio
diff --git a/presets/consumer/avformat/lossless/HuffYUV b/presets/consumer/avformat/lossless/HuffYUV
new file mode 100644 (file)
index 0000000..1be88fe
--- /dev/null
@@ -0,0 +1,6 @@
+f=mkv
+acodec=flac
+vcodec=huffyuv
+
+meta.preset.extension=mkv
+meta.preset.note=with FLAC audio in Matroska container
diff --git a/presets/consumer/avformat/lossless/MJPEG b/presets/consumer/avformat/lossless/MJPEG
new file mode 100644 (file)
index 0000000..06d8b3f
--- /dev/null
@@ -0,0 +1,9 @@
+progressive=1
+f=avi
+acodec=pcm_s16le
+vcodec=mjpeg
+qscale=1
+threads=1
+
+meta.preset.extension=avi
+meta.preset.note=not lossless, but still high quality
diff --git a/presets/consumer/avformat/lossless/MPEG-2 b/presets/consumer/avformat/lossless/MPEG-2
new file mode 100644 (file)
index 0000000..9cf2726
--- /dev/null
@@ -0,0 +1,12 @@
+f=mpeg
+acodec=ac3
+ab=512k
+vcodec=mpeg2video
+intra=1
+vb=0
+g=0
+bf=0
+qscale=1
+
+meta.preset.extension=mpg
+meta.preset.note=a little lossy, but intra-frame only with AC-3 audio
diff --git a/presets/consumer/avformat/lossless/MPEG-4 b/presets/consumer/avformat/lossless/MPEG-4
new file mode 100644 (file)
index 0000000..e69dec3
--- /dev/null
@@ -0,0 +1,11 @@
+f=avi
+acodec=pcm_s16le
+vcodec=mpeg4
+qscale=1
+intra=1
+g=0
+vb=0
+bf=0
+
+meta.preset.extension=avi
+meta.preset.note=somewhat lossy, intra-frame only MPEG-4, with uncompressed audio
diff --git a/presets/consumer/avformat/lossless/ProRes b/presets/consumer/avformat/lossless/ProRes
new file mode 100644 (file)
index 0000000..abfc72d
--- /dev/null
@@ -0,0 +1,11 @@
+f=mov
+acodec=pcm_s16le
+vcodec=prores
+vb=0
+g=0
+bf=0
+threads=1
+vprofile=2
+
+meta.preset.extension=mov
+meta.preset.note=Designed by Apple in California. Set vprofile=1 for LT or =3 for HQ.
diff --git a/presets/consumer/avformat/stills/BMP b/presets/consumer/avformat/stills/BMP
new file mode 100644 (file)
index 0000000..648a5c7
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=bmp
+an=1
+audio_off=1
+
+meta.preset.extension=bmp
diff --git a/presets/consumer/avformat/stills/DPX b/presets/consumer/avformat/stills/DPX
new file mode 100644 (file)
index 0000000..44dad8d
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=dpx
+an=1
+audio_off=1
+
+meta.preset.extension=dpx
diff --git a/presets/consumer/avformat/stills/JPEG b/presets/consumer/avformat/stills/JPEG
new file mode 100644 (file)
index 0000000..a3d1429
--- /dev/null
@@ -0,0 +1,8 @@
+progressive=1
+f=image2
+vcodec=mjpeg
+qscale=1
+an=1
+audio_off=1
+
+meta.preset.extension=jpg
diff --git a/presets/consumer/avformat/stills/PNG b/presets/consumer/avformat/stills/PNG
new file mode 100644 (file)
index 0000000..8cd00ed
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=png
+an=1
+audio_off=1
+
+meta.preset.extension=png
diff --git a/presets/consumer/avformat/stills/PPM b/presets/consumer/avformat/stills/PPM
new file mode 100644 (file)
index 0000000..1c44303
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=ppm
+an=1
+audio_off=1
+
+meta.preset.extension=ppm
diff --git a/presets/consumer/avformat/stills/TGA b/presets/consumer/avformat/stills/TGA
new file mode 100644 (file)
index 0000000..5cd84a5
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=targa
+an=1
+audio_off=1
+
+meta.preset.extension=tga
diff --git a/presets/consumer/avformat/stills/TIFF b/presets/consumer/avformat/stills/TIFF
new file mode 100644 (file)
index 0000000..fdc6315
--- /dev/null
@@ -0,0 +1,7 @@
+progressive=1
+f=image2
+vcodec=tiff
+an=1
+audio_off=1
+
+meta.preset.extension=tif
index 48847b237d9b470bbf304ec0a1a2a436e570ba66..7e5ed04a246a5af34cb4d721e2763a8eb652147d 100644 (file)
@@ -1,4 +1,6 @@
 f=webm
+
+acodec=vorbis
 ab=128k
 
 vcodec=libvpx
@@ -6,7 +8,7 @@ g=120
 rc_lookahead=16
 quality=good
 speed=0
-profile=0
+vprofile=0
 qmax=51
 qmin=11
 slices=4
@@ -16,3 +18,7 @@ minrate=100k
 arnr_max_frames=7
 arnr_strength=5
 arnr_type=3
+
+meta.preset.name=WebM
+meta.preset.extension=webm
+meta.preset.note=VP8 video with Ogg Vorbis audio in Matroska container: "Don't be evil"
index 3dd471e26173093c76c48bc76fc1418987ce92c3..bdece6e12caab8c333102f845bcade33ab7608fb 100644 (file)
@@ -1,4 +1,12 @@
+f=mp4
+
+acodec=aac
+ab=256k
+
 vcodec=libx264
 threads=0
 vpre=medium
 preset=medium
+
+meta.preset.extension=mp4
+meta.preset.name=H.264 High Profile
index e577e012c15697a8cef86d106573438b1c66e287..2927a12c6a53017772ebda55cd8b9aaf3a79dbbe 100644 (file)
@@ -1,9 +1,17 @@
+f=mp4
+
+acodec=aac
+ab=256k
+
 vcodec=libx264
 threads=0
 vpre=medium
 preset=medium
-profile=baseline
+vprofile=baseline
 coder=0
 bf=0
 flags2=-wpred-dct8x8
 wpredp=0
+
+meta.preset.extension=mp4
+meta.preset.name=H.264 Baseline Profile
index 6a5413b33269e080381cae7432427fffcd0e7686..d92709452da2eb6ec56fcf89fc79c61e3082d0b5 100644 (file)
@@ -1,6 +1,14 @@
+f=mp4
+
+acodec=aac
+ab=256k
+
 vcodec=libx264
 threads=0
 vpre=medium
 preset=medium
-profile=main
+vprofile=main
 flags2=-dct8x8
+
+meta.preset.extension=mp4
+meta.preset.name=H.264 Main Profile
index 0aebac2085cb07b0569840e210ea0a6bf878d5ac..17b58ac8748e40a03d0c7b0c7f1552ab0d8ddd05 100644 (file)
@@ -1,3 +1,5 @@
+f=mp4
+
 vcodec=libx264
 threads=0
 vpre=medium
@@ -11,3 +13,6 @@ trellis=0
 flags2=+bpyramid-mixed_refs+wpred-dct8x8+fastpskip
 pass=1
 an=1
+audio_off=1
+
+meta.preset.hidden=1
index 4e07644d603feb4cec3af110b064bb12d13675a9..cc6ff46b6b210367d7e8c3c40f8d8314730b20f0 100644 (file)
@@ -9,10 +9,10 @@ distclean:
 clean:
 
 install:       all uninstall
-       install -d "$(DESTDIR)$(datadir)/mlt/profiles"
-       install -m 644 * "$(DESTDIR)$(datadir)/mlt/profiles"
-       rm -f "$(DESTDIR)$(datadir)/mlt/profiles/"*~
-       rm -f "$(DESTDIR)$(datadir)/mlt/profiles/Makefile"
+       install -d "$(DESTDIR)$(mltdatadir)/profiles"
+       install -m 644 * "$(DESTDIR)$(mltdatadir)/profiles"
+       rm -f "$(DESTDIR)$(mltdatadir)/profiles/"*~
+       rm -f "$(DESTDIR)$(mltdatadir)/profiles/Makefile"
 
 uninstall:
-       rm -rf "$(DESTDIR)$(datadir)/mlt/profiles"
+       rm -rf "$(DESTDIR)$(mltdatadir)/profiles"
index a493dfbc2b24224b9279acde0fa151caf95037f5..e5107c699e160fe0336eb0b45536068ce13b1b16 100644 (file)
@@ -18,11 +18,10 @@ NAME = libmlt$(LIBSUF)
 TARGET = $(NAME).$(version)
 SONAME = $(NAME).$(soversion)
 SHFLAGS += -Wl,-soname,$(SONAME)
-       ifeq ($(targetos), FreeBSD)
-               ifdef HAVE_SYS_PARAM_H
-                       CFLAGS += -DHAVE_SYS_PARAM_H
-               endif
-       endif
+endif
+
+ifeq ($(targetos), Linux)
+SHFLAGS += -Wl,--version-script=mlt.vers
 endif
 
 OBJS = mlt_frame.o \
@@ -84,7 +83,7 @@ OBJS += ../win32/win32.o
 SRCS += ../win32/win32.c
 endif
 
-CFLAGS += $(RDYNAMIC) -DPREFIX="\"$(prefix)\"" -DLIBDIR="\"$(libdir)\"" -DMLTDATADIR="\"$(datadir)\""
+CFLAGS += $(RDYNAMIC) -DPREFIX_DATA="\"$(mltdatadir)\"" -DPREFIX_LIB="\"$(moduledir)\""
 
 LDFLAGS += $(LIBDL) -lpthread
 
@@ -119,8 +118,8 @@ install:
        fi
        install -d "$(DESTDIR)$(prefix)/include/mlt/framework"
        install -m 644 $(INCS) "$(DESTDIR)$(prefix)/include/mlt/framework"
-       install -d "$(DESTDIR)$(datadir)/mlt"
-       install -m 644 metaschema.yaml "$(DESTDIR)$(datadir)/mlt/"
+       install -d "$(DESTDIR)$(mltdatadir)"
+       install -m 644 metaschema.yaml "$(DESTDIR)$(mltdatadir)"
 
 uninstall:
        rm -f "$(DESTDIR)$(libdir)/$(TARGET)"
@@ -129,7 +128,7 @@ uninstall:
                rm -f "$(DESTDIR)$(libdir)/$(NAME)" ; \
        fi
        rm -rf "$(DESTDIR)$(prefix)/include/mlt/framework"
-       rm -f "$(DESTDIR)$(datadir)/mlt/metaschema.yaml"
+       rm -f "$(DESTDIR)$(mltdatadir)/metaschema.yaml"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 439a473e3f9107629652287e580d10ae1c656e3e..601b20c90144fb1c0e981e631d8638a7b0310a4a 100755 (executable)
@@ -1,10 +1,4 @@
 #!/bin/sh
 echo "framework        -I$prefix/include -I$prefix/include/mlt -D_REENTRANT    -L$libdir -lmlt" >> ../../packages.dat
 
-echo -n > config.mak
-if [ "$(uname -s)" = "FreeBSD" ]
-then
-       printf "#include <sys/param.h>\n int main(){ return 0;}" | gcc -c -x c - >/dev/null 2>&1
-       [ "$?" -eq 0 ] && echo "HAVE_SYS_PARAM_H=1" >> config.mak
-fi
-exit 0
+echo > config.mak
diff --git a/src/framework/mlt.vers b/src/framework/mlt.vers
new file mode 100644 (file)
index 0000000..7b80f40
--- /dev/null
@@ -0,0 +1,408 @@
+MLT_0.8.8 {
+  global:
+    default_callback;
+    mlt_audio_format_name;
+    mlt_audio_format_size;
+    mlt_cache_close;
+    mlt_cache_get;
+    mlt_cache_get_frame;
+    mlt_cache_get_size;
+    mlt_cache_init;
+    mlt_cache_item_close;
+    mlt_cache_item_data;
+    mlt_cache_purge;
+    mlt_cache_put;
+    mlt_cache_put_frame;
+    mlt_cache_set_size;
+    mlt_consumer_close;
+    mlt_consumer_connect;
+    mlt_consumer_get_frame;
+    mlt_consumer_init;
+    mlt_consumer_is_stopped;
+    mlt_consumer_new;
+    mlt_consumer_position;
+    mlt_consumer_properties;
+    mlt_consumer_purge;
+    mlt_consumer_put_frame;
+    mlt_consumer_rt_frame;
+    mlt_consumer_service;
+    mlt_consumer_start;
+    mlt_consumer_stop;
+    mlt_consumer_stopped;
+    mlt_deque_close;
+    mlt_deque_count;
+    mlt_deque_init;
+    mlt_deque_insert;
+    mlt_deque_peek;
+    mlt_deque_peek_back;
+    mlt_deque_peek_back_double;
+    mlt_deque_peek_back_int;
+    mlt_deque_peek_front;
+    mlt_deque_peek_front_double;
+    mlt_deque_peek_front_int;
+    mlt_deque_pop_back;
+    mlt_deque_pop_back_double;
+    mlt_deque_pop_back_int;
+    mlt_deque_pop_front;
+    mlt_deque_pop_front_double;
+    mlt_deque_pop_front_int;
+    mlt_deque_push_back;
+    mlt_deque_push_back_double;
+    mlt_deque_push_back_int;
+    mlt_deque_push_front;
+    mlt_deque_push_front_double;
+    mlt_deque_push_front_int;
+    mlt_environment;
+    mlt_environment_set;
+    mlt_event_block;
+    mlt_event_close;
+    mlt_event_inc_ref;
+    mlt_events_block;
+    mlt_events_close_wait_for;
+    mlt_events_disconnect;
+    mlt_events_fire;
+    mlt_events_init;
+    mlt_events_listen;
+    mlt_events_register;
+    mlt_events_setup_wait_for;
+    mlt_events_unblock;
+    mlt_events_wait_for;
+    mlt_event_unblock;
+    mlt_factory_close;
+    mlt_factory_consumer;
+    mlt_factory_directory;
+    mlt_factory_event_object;
+    mlt_factory_filter;
+    mlt_factory_init;
+    mlt_factory_producer;
+    mlt_factory_register_for_clean_up;
+    mlt_factory_transition;
+    mlt_field_close;
+    mlt_field_disconnect_service;
+    mlt_field_init;
+    mlt_field_multitrack;
+    mlt_field_new;
+    mlt_field_plant_filter;
+    mlt_field_plant_transition;
+    mlt_field_properties;
+    mlt_field_service;
+    mlt_field_tractor;
+    mlt_filter_close;
+    mlt_filter_connect;
+    mlt_filter_get_in;
+    mlt_filter_get_length;
+    mlt_filter_get_length2;
+    mlt_filter_get_out;
+    mlt_filter_get_position;
+    mlt_filter_get_progress;
+    mlt_filter_get_track;
+    mlt_filter_init;
+    mlt_filter_new;
+    mlt_filter_process;
+    mlt_filter_properties;
+    mlt_filter_service;
+    mlt_filter_set_in_and_out;
+    mlt_frame_clone;
+    mlt_frame_close;
+    mlt_frame_get_alpha_mask;
+    mlt_frame_get_aspect_ratio;
+    mlt_frame_get_audio;
+    mlt_frame_get_image;
+    mlt_frame_get_original_producer;
+    mlt_frame_get_position;
+    mlt_frame_get_waveform;
+    mlt_frame_init;
+    mlt_frame_is_test_audio;
+    mlt_frame_is_test_card;
+    mlt_frame_original_position;
+    mlt_frame_pop_audio;
+    mlt_frame_pop_frame;
+    mlt_frame_pop_get_image;
+    mlt_frame_pop_service;
+    mlt_frame_pop_service_int;
+    mlt_frame_properties;
+    mlt_frame_push_audio;
+    mlt_frame_push_frame;
+    mlt_frame_push_get_image;
+    mlt_frame_push_service;
+    mlt_frame_push_service_int;
+    mlt_frame_replace_image;
+    mlt_frame_service_stack;
+    mlt_frame_set_alpha;
+    mlt_frame_set_aspect_ratio;
+    mlt_frame_set_audio;
+    mlt_frame_set_image;
+    mlt_frame_set_position;
+    mlt_frame_unique_properties;
+    mlt_frame_write_ppm;
+    mlt_geometry_close;
+    mlt_geometry_fetch;
+    mlt_geometry_get_length;
+    mlt_geometry_init;
+    mlt_geometry_insert;
+    mlt_geometry_interpolate;
+    mlt_geometry_next_key;
+    mlt_geometry_parse;
+    mlt_geometry_parse_item;
+    mlt_geometry_prev_key;
+    mlt_geometry_refresh;
+    mlt_geometry_remove;
+    mlt_geometry_serialise;
+    mlt_geometry_serialise_cut;
+    mlt_geometry_set_length;
+    mlt_global_properties;
+    mlt_image_format_name;
+    mlt_image_format_size;
+    mlt_log;
+    mlt_log_get_level;
+    mlt_log_set_callback;
+    mlt_log_set_level;
+    mlt_multitrack_clip;
+    mlt_multitrack_close;
+    mlt_multitrack_connect;
+    mlt_multitrack_count;
+    mlt_multitrack_init;
+    mlt_multitrack_producer;
+    mlt_multitrack_properties;
+    mlt_multitrack_refresh;
+    mlt_multitrack_service;
+    mlt_multitrack_track;
+    mlt_parser_close;
+    mlt_parser_new;
+    mlt_parser_properties;
+    mlt_parser_start;
+    mlt_playlist_append;
+    mlt_playlist_append_io;
+    mlt_playlist_blank;
+    mlt_playlist_blanks_from;
+    mlt_playlist_blank_time;
+    mlt_playlist_clear;
+    mlt_playlist_clip;
+    mlt_playlist_clip_is_mix;
+    mlt_playlist_clip_length;
+    mlt_playlist_clip_start;
+    mlt_playlist_close;
+    mlt_playlist_consolidate_blanks;
+    mlt_playlist_count;
+    mlt_playlist_current;
+    mlt_playlist_current_clip;
+    mlt_playlist_get_clip;
+    mlt_playlist_get_clip_at;
+    mlt_playlist_get_clip_index_at;
+    mlt_playlist_get_clip_info;
+    mlt_playlist_init;
+    mlt_playlist_insert;
+    mlt_playlist_insert_at;
+    mlt_playlist_insert_blank;
+    mlt_playlist_is_blank;
+    mlt_playlist_is_blank_at;
+    mlt_playlist_join;
+    mlt_playlist_mix;
+    mlt_playlist_mix_add;
+    mlt_playlist_move;
+    mlt_playlist_move_region;
+    mlt_playlist_new;
+    mlt_playlist_pad_blanks;
+    mlt_playlist_producer;
+    mlt_playlist_properties;
+    mlt_playlist_remove;
+    mlt_playlist_remove_region;
+    mlt_playlist_repeat_clip;
+    mlt_playlist_replace_with_blank;
+    mlt_playlist_resize_clip;
+    mlt_playlist_service;
+    mlt_playlist_split;
+    mlt_playlist_split_at;
+    mlt_pool_alloc;
+    mlt_pool_close;
+    mlt_pool_init;
+    mlt_pool_purge;
+    mlt_pool_realloc;
+    mlt_pool_release;
+    mlt_producer_attach;
+    mlt_producer_clear;
+    mlt_producer_close;
+    mlt_producer_cut;
+    mlt_producer_cut_parent;
+    mlt_producer_detach;
+    mlt_producer_filter;
+    mlt_producer_frame;
+    mlt_producer_frame_time;
+    mlt_producer_get_fps;
+    mlt_producer_get_in;
+    mlt_producer_get_length;
+    mlt_producer_get_length_time;
+    mlt_producer_get_out;
+    mlt_producer_get_playtime;
+    mlt_producer_get_speed;
+    mlt_producer_init;
+    mlt_producer_is_blank;
+    mlt_producer_is_cut;
+    mlt_producer_is_mix;
+    mlt_producer_new;
+    mlt_producer_optimise;
+    mlt_producer_position;
+    mlt_producer_prepare_next;
+    mlt_producer_properties;
+    mlt_producer_seek;
+    mlt_producer_seek_time;
+    mlt_producer_service;
+    mlt_producer_set_in_and_out;
+    mlt_producer_set_speed;
+    mlt_profile_clone;
+    mlt_profile_close;
+    mlt_profile_dar;
+    mlt_profile_fps;
+    mlt_profile_from_producer;
+    mlt_profile_init;
+    mlt_profile_list;
+    mlt_profile_load_file;
+    mlt_profile_load_properties;
+    mlt_profile_load_string;
+    mlt_profile_sar;
+    mlt_properties_close;
+    mlt_properties_count;
+    mlt_properties_debug;
+    mlt_properties_dec_ref;
+    mlt_properties_dir_list;
+    mlt_properties_dump;
+    mlt_properties_get;
+    mlt_properties_get_data;
+    mlt_properties_get_data_at;
+    mlt_properties_get_double;
+    mlt_properties_get_int;
+    mlt_properties_get_int64;
+    mlt_properties_get_lcnumeric;
+    mlt_properties_get_name;
+    mlt_properties_get_position;
+    mlt_properties_get_time;
+    mlt_properties_get_value;
+    mlt_properties_inc_ref;
+    mlt_properties_inherit;
+    mlt_properties_init;
+    mlt_properties_is_sequence;
+    mlt_properties_load;
+    mlt_properties_lock;
+    mlt_properties_mirror;
+    mlt_properties_new;
+    mlt_properties_parse;
+    mlt_properties_parse_yaml;
+    mlt_properties_pass;
+    mlt_properties_pass_list;
+    mlt_properties_pass_property;
+    mlt_properties_preset;
+    mlt_properties_ref_count;
+    mlt_properties_rename;
+    mlt_properties_save;
+    mlt_properties_serialise_yaml;
+    mlt_properties_set;
+    mlt_properties_set_data;
+    mlt_properties_set_double;
+    mlt_properties_set_int;
+    mlt_properties_set_int64;
+    mlt_properties_set_lcnumeric;
+    mlt_properties_set_or_default;
+    mlt_properties_set_position;
+    mlt_properties_unlock;
+    mlt_property_close;
+    mlt_property_get_data;
+    mlt_property_get_double;
+    mlt_property_get_int;
+    mlt_property_get_int64;
+    mlt_property_get_position;
+    mlt_property_get_string;
+    mlt_property_get_string_l;
+    mlt_property_get_time;
+    mlt_property_init;
+    mlt_property_pass;
+    mlt_property_set_data;
+    mlt_property_set_double;
+    mlt_property_set_int;
+    mlt_property_set_int64;
+    mlt_property_set_position;
+    mlt_property_set_string;
+    mlt_repository_close;
+    mlt_repository_consumers;
+    mlt_repository_create;
+    mlt_repository_filters;
+    mlt_repository_init;
+    mlt_repository_languages;
+    mlt_repository_metadata;
+    mlt_repository_presets;
+    mlt_repository_producers;
+    mlt_repository_register;
+    mlt_repository_register_metadata;
+    mlt_repository_transitions;
+    mlt_sample_calculator;
+    mlt_sample_calculator_to_now;
+    mlt_sdl_mutex;
+    mlt_service_apply_filters;
+    mlt_service_attach;
+    mlt_service_cache_get;
+    mlt_service_cache_get_size;
+    mlt_service_cache_purge;
+    mlt_service_cache_put;
+    mlt_service_cache_set_size;
+    mlt_service_close;
+    mlt_service_connect_producer;
+    mlt_service_consumer;
+    mlt_service_detach;
+    mlt_service_filter;
+    mlt_service_get_frame;
+    mlt_service_get_producer;
+    mlt_service_identify;
+    mlt_service_init;
+    mlt_service_lock;
+    mlt_service_producer;
+    mlt_service_profile;
+    mlt_service_properties;
+    mlt_service_set_profile;
+    mlt_service_unlock;
+    mlt_tokeniser_close;
+    mlt_tokeniser_count;
+    mlt_tokeniser_get_input;
+    mlt_tokeniser_get_string;
+    mlt_tokeniser_init;
+    mlt_tokeniser_parse_new;
+    mlt_tractor_close;
+    mlt_tractor_connect;
+    mlt_tractor_field;
+    mlt_tractor_get_track;
+    mlt_tractor_init;
+    mlt_tractor_multitrack;
+    mlt_tractor_new;
+    mlt_tractor_producer;
+    mlt_tractor_properties;
+    mlt_tractor_refresh;
+    mlt_tractor_service;
+    mlt_tractor_set_track;
+    mlt_transition_close;
+    mlt_transition_connect;
+    mlt_transition_get_a_track;
+    mlt_transition_get_b_track;
+    mlt_transition_get_in;
+    mlt_transition_get_length;
+    mlt_transition_get_out;
+    mlt_transition_get_position;
+    mlt_transition_get_progress;
+    mlt_transition_get_progress_delta;
+    mlt_transition_init;
+    mlt_transition_new;
+    mlt_transition_process;
+    mlt_transition_properties;
+    mlt_transition_service;
+    mlt_transition_set_in_and_out;
+    mlt_version_get_int;
+    mlt_version_get_major;
+    mlt_version_get_minor;
+    mlt_version_get_revision;
+    mlt_version_get_string;
+    mlt_vlog;
+
+  local: *;
+};
+
+MLT_0.9.0 {
+  global:
+    "mlt_service_filter_count";
+} MLT_0.8.8;
index 250ea4156994203b1c4c4fbf7ea6df176ce00bce..0ab2456b177866ac6c177127dbb20d029f401630 100644 (file)
@@ -1,9 +1,9 @@
 /**
- * \file mlt_profile.c
+ * \file mlt_cache.c
  * \brief least recently used cache
  * \see mlt_profile_s
  *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2007-2012 Ushodaya Enterprises Limited
  * \author Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
 #include "mlt_log.h"
 #include "mlt_properties.h"
 #include "mlt_cache.h"
+#include "mlt_frame.h"
 
 #include <stdlib.h>
 #include <pthread.h>
@@ -33,7 +34,7 @@
 #define MAX_CACHE_SIZE (200)
 
 /** the default number of data objects to cache per line */
-#define DEFAULT_CACHE_SIZE (10)
+#define DEFAULT_CACHE_SIZE (4)
 
 /** \brief Cache item class
  *
@@ -82,6 +83,7 @@ struct mlt_cache_s
 {
        int count;             /**< the number of items currently in the cache */
        int size;              /**< the maximum number of items permitted in the cache <= \p MAX_CACHE_SIZE */
+       int is_frames;         /**< indicates if this cache is used to cache frames */
        void* *current;        /**< pointer to the current array of pointers */
        void* A[ MAX_CACHE_SIZE ];
        void* B[ MAX_CACHE_SIZE ];
@@ -121,6 +123,13 @@ static void cache_object_close( mlt_cache cache, void *object, void* data )
 {
        char key[19];
 
+       if ( cache->is_frames )
+       {
+               // Frame caches are easy - just close the object as mlt_frame.
+               mlt_frame_close( object );
+               return;
+       }
+
        // Fetch the cache item from the active list by its owner's address
        sprintf( key, "%p", object );
        mlt_cache_item item = mlt_properties_get_data( cache->active, key, NULL );
@@ -259,6 +268,7 @@ void mlt_cache_close( mlt_cache cache )
 
 void mlt_cache_purge( mlt_cache cache, void *object )
 {
+       if (!cache) return;
        pthread_mutex_lock( &cache->mutex );
        if ( cache && object )
        {
@@ -336,6 +346,11 @@ static void** shuffle_get_hit( mlt_cache cache, void *object )
 }
 
 /** Put a chunk of data in the cache.
+ *
+ * This function and mlt_cache_get() are not scalable with a large volume
+ * of unique \p object paramter values. Therefore, it does not make sense
+ * to use it for a frame/image cache using the frame position for \p object.
+ * Instead, use mlt_cache_put_frame() for that.
  *
  * \public \memberof mlt_cache_s
  * \param cache a cache object
@@ -441,8 +456,10 @@ mlt_cache_item mlt_cache_get( mlt_cache cache, void *object )
                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 );
+                       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;
@@ -451,3 +468,138 @@ mlt_cache_item mlt_cache_get( mlt_cache cache, void *object )
        
        return result;
 }
+
+/** Shuffle the cache entries between the two arrays and return the frame for a position.
+ *
+ * \private \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param position the position of the frame that you want
+ * \return a frame if there was a hit or NULL for a miss
+ */
+
+static mlt_frame* shuffle_get_frame( mlt_cache cache, mlt_position position )
+{
+       int i = cache->count;
+       int j = cache->count - 1;
+       mlt_frame *hit = NULL;
+       mlt_frame *alt = (mlt_frame*) ( 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 )
+               {
+                       mlt_frame *o = (mlt_frame*) &cache->current[ i ];
+                       if ( mlt_frame_original_position( *o ) == position )
+                               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-- )
+       {
+               mlt_frame *o = (mlt_frame*) &cache->current[ i ];
+
+               if ( !hit && mlt_frame_original_position( *o ) == position )
+               {
+                       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 frame in the cache.
+ *
+ * Unlike mlt_cache_put() this version is more suitable for caching frames
+ * and their data - like images. However, this version does not use reference
+ * counting and garbage collection. Rather, frames are cloned with deep copy
+ * to avoid those things.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param frame the frame to cache
+ * \see mlt_frame_get_frame
+ */
+
+void mlt_cache_put_frame( mlt_cache cache, mlt_frame frame )
+{
+       pthread_mutex_lock( &cache->mutex );
+       mlt_frame *hit = shuffle_get_frame( cache, mlt_frame_original_position( frame ) );
+       mlt_frame *alt = (mlt_frame*) ( cache->current == cache->A ? cache->B : cache->A );
+
+       // add the frame to the cache
+       if ( hit )
+       {
+               // release the old data
+               mlt_frame_close( *hit );
+               // 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
+               mlt_frame_close( cache->current[0] );
+
+               // The MRU end gets the new item
+               hit = &alt[ cache->count - 1 ];
+       }
+       *hit = mlt_frame_clone( frame, 1 );
+       mlt_log( NULL, MLT_LOG_DEBUG, "%s: put %d = %p\n", __FUNCTION__, cache->count - 1, frame );
+
+       // swap the current array
+       cache->current = (void**) alt;
+       cache->is_frames = 1;
+       pthread_mutex_unlock( &cache->mutex );
+}
+
+/** Get a frame from the cache.
+ *
+ * You must call mlt_frame_close() on the frame you receive from this.
+ *
+ * \public \memberof mlt_cache_s
+ * \param cache a cache object
+ * \param position the position of the frame that you want
+ * \return a frame if found or NULL if not found or has been flushed from the cache
+ * \see mlt_frame_put_frame
+ */
+
+mlt_frame mlt_cache_get_frame( mlt_cache cache, mlt_position position )
+{
+       mlt_frame result = NULL;
+       pthread_mutex_lock( &cache->mutex );
+       mlt_frame *hit = shuffle_get_frame( cache, position );
+       mlt_frame *alt = (mlt_frame*) ( 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 ];
+
+               result = mlt_frame_clone( *hit, 1 );
+               mlt_log( NULL, MLT_LOG_DEBUG, "%s: get %d = %p\n", __FUNCTION__, cache->count - 1, *hit );
+
+               // swap the current array
+               cache->current = (void**) alt;
+       }
+       pthread_mutex_unlock( &cache->mutex );
+
+       return result;
+}
index fb0cca6a048c9e60f1a1e7c68facb6cb38089288..cd26522cdfbccf8df58a2089383757374a16349b 100644 (file)
@@ -3,7 +3,7 @@
  * \brief least recently used cache
  * \see mlt_cache_s
  *
- * Copyright (C) 2007-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2007-2012 Ushodaya Enterprises Limited
  * \author Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -36,5 +36,7 @@ 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 );
+extern void mlt_cache_put_frame( mlt_cache cache, mlt_frame frame );
+extern mlt_frame mlt_cache_get_frame( mlt_cache cache, mlt_position position );
 
 #endif
index a45ce47288d086ccbbb1930fafa97d8d9a476a62..3421cb67f2d7e6a44d61fdbbc670ddf2292ffefb 100644 (file)
@@ -105,6 +105,8 @@ int mlt_consumer_init( mlt_consumer self, void *child, mlt_profile profile )
 
                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-thread-started", NULL );
+               mlt_events_register( properties, "consumer-thread-stopped", NULL );
                mlt_events_register( properties, "consumer-stopped", NULL );
                mlt_events_listen( properties, self, "consumer-frame-show", ( mlt_listener )on_consumer_frame_show );
 
@@ -176,7 +178,6 @@ static void mlt_consumer_property_changed( mlt_properties owner, mlt_consumer se
                                free( profile->description );
                                memcpy( profile, new_profile, sizeof( struct mlt_profile_s ) );
                                profile->description = strdup( new_profile->description );
-                               mlt_profile_close( new_profile );
                        }
                        else
                        {
@@ -185,6 +186,7 @@ static void mlt_consumer_property_changed( mlt_properties owner, mlt_consumer se
 
                        // Apply to properties
                        apply_profile_properties( self, profile, properties );
+                       mlt_profile_close( new_profile );
                }
        }
        else if ( !strcmp( name, "frame_rate_num" ) )
@@ -232,17 +234,21 @@ static void mlt_consumer_property_changed( mlt_properties owner, mlt_consumer se
        {
                mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );
                mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( self ) );
-               profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
                if ( profile )
+               {
+                       profile->sample_aspect_num = mlt_properties_get_int( properties, "sample_aspect_num" );
                        mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile )  );
+               }
        }
        else if ( !strcmp( name, "sample_aspect_den" ) )
        {
                mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );
                mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( self ) );
-               profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
                if ( profile )
+               {
+                       profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" );
                        mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile )  );
+               }
        }
        else if ( !strcmp( name, "display_aspect_num" ) )
        {
@@ -280,8 +286,8 @@ static void mlt_consumer_property_changed( mlt_properties owner, mlt_consumer se
  * \private \memberof mlt_consumer_s
  * \param listener a function pointer that will be invoked
  * \param owner the events object that will be passed to \p listener
- * \param self  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
+ * \param self a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a frame to \p listener
  */
 
 static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
@@ -297,8 +303,8 @@ static void mlt_consumer_frame_show( mlt_listener listener, mlt_properties owner
  * \private \memberof mlt_consumer_s
  * \param listener a function pointer that will be invoked
  * \param owner the events object that will be passed to \p listener
- * \param self  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
+ * \param self a service that will be passed to \p listener
+ * \param args an array of pointers - the first entry is passed as a frame to \p listener
  */
 
 static void mlt_consumer_frame_render( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
@@ -336,11 +342,16 @@ mlt_consumer mlt_consumer_new( mlt_profile profile )
        mlt_consumer self = malloc( sizeof( struct mlt_consumer_s ) );
 
        // Initialise it
-       if ( self != NULL )
-               mlt_consumer_init( self, NULL, profile );
-
-       // Return it
-       return self;
+       if ( self != NULL && mlt_consumer_init( self, NULL, profile ) == 0 )
+       {
+               // Return it
+               return self;
+       }
+       else
+       {
+               free(self);
+               return NULL;
+       }
 }
 
 /** Get the parent service object.
@@ -407,8 +418,10 @@ int mlt_consumer_start( mlt_consumer self )
        char *test_card = mlt_properties_get( properties, "test_card" );
 
        // Just to make sure nothing is hanging around...
+       pthread_mutex_lock( &self->put_mutex );
        self->put = NULL;
        self->put_active = 1;
+       pthread_mutex_unlock( &self->put_mutex );
 
        // Deal with it now.
        if ( test_card != NULL )
@@ -438,9 +451,19 @@ int mlt_consumer_start( mlt_consumer self )
                mlt_properties_set_data( properties, "test_card_producer", NULL, 0, NULL, NULL );
        }
 
+       // The profile could have changed between a stop and a restart.
+       apply_profile_properties( self, mlt_service_profile( MLT_CONSUMER_SERVICE(self) ), properties );
+
        // 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" );
+       int frame_rate_num = mlt_properties_get_int( properties, "frame_rate_num" );
+       int frame_rate_den = mlt_properties_get_int( properties, "frame_rate_den" );
+       int frame_duration = 0;
+
+       if ( frame_rate_num && frame_rate_den )
+       {
+               frame_duration = 1000000 / frame_rate_num * frame_rate_den;
+       }
+
        mlt_properties_set_int( properties, "frame_duration", frame_duration );
 
        // Check and run an ante command
@@ -467,6 +490,8 @@ int mlt_consumer_start( mlt_consumer self )
                        self->format = mlt_image_yuv420p;
                else if ( !strcmp( format, "none" ) )
                        self->format = mlt_image_none;
+               else if ( !strcmp( format, "glsl" ) )
+                       self->format = mlt_image_glsl_texture;
                else
                        self->format = mlt_image_yuv422;
        }
@@ -581,11 +606,9 @@ mlt_frame mlt_consumer_get_frame( mlt_consumer self )
                if ( test_card != NULL )
                        mlt_properties_set_data( frame_properties, "test_card_producer", test_card, 0, NULL, NULL );
 
-               // Attach the rescale property
+               // Pass along the interpolation and deinterlace options
+               // TODO: get rid of consumer_deinterlace and use profile.progressive
                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" ) );
                mlt_properties_set_int( frame_properties, "consumer_tff", mlt_properties_get_int( properties, "top_field_first" ) );
@@ -650,6 +673,8 @@ static void *consumer_read_ahead_thread( void *arg )
                        afmt = mlt_audio_float;
                else if ( !strcmp( format, "f32le" ) )
                        afmt = mlt_audio_f32le;
+               else if ( !strcmp( format, "u8" ) )
+                       afmt = mlt_audio_u8;
        }
        int counter = 0;
        double fps = mlt_properties_get_double( properties, "fps" );
@@ -685,6 +710,8 @@ static void *consumer_read_ahead_thread( void *arg )
        if ( preview_off && preview_format != 0 )
                self->format = preview_format;
 
+       mlt_events_fire( properties, "consumer-thread-started", NULL );
+
        // Get the first frame
        frame = mlt_consumer_get_frame( self );
 
@@ -832,6 +859,7 @@ static void *consumer_read_ahead_thread( void *arg )
 
        // Remove the last frame
        mlt_frame_close( frame );
+       mlt_events_fire( properties, "consumer-thread-stopped", NULL );
 
        return NULL;
 }
@@ -891,6 +919,8 @@ static void *consumer_worker_thread( void *arg )
        if ( preview_off && preview_format != 0 )
                format = preview_format;
 
+       mlt_events_fire( properties, "consumer-thread-started", NULL );
+
        // Continue to read ahead
        while ( self->ahead )
        {
@@ -943,6 +973,7 @@ static void *consumer_worker_thread( void *arg )
                pthread_cond_broadcast( &self->done_cond );
                pthread_mutex_unlock( &self->done_mutex );
        }
+       mlt_events_fire( properties, "consumer-thread-stopped" );
 
        return NULL;
 }
@@ -1002,6 +1033,7 @@ static void consumer_work_start( mlt_consumer self )
 
        // We're running now
        self->ahead = 1;
+       self->threads = thread;
        
        // These keep track of the accelleration of frame dropping or recovery.
        self->consecutive_dropped = 0;
@@ -1138,8 +1170,8 @@ static void consumer_work_stop( mlt_consumer self )
                        pthread_join( *thread, NULL );
 
                // Deallocate the array of threads
-               if ( thread )
-                       free( thread );
+               if ( self->threads )
+                       free( self->threads );
 
                // Indicate that worker threads no longer running
                self->started = 0;
@@ -1170,13 +1202,16 @@ static void consumer_work_stop( mlt_consumer self )
 
 void mlt_consumer_purge( mlt_consumer self )
 {
-       if ( self->ahead )
+       if ( self && self->ahead )
        {
-               pthread_mutex_lock( &self->queue_mutex );
+               if ( self->ahead && self->real_time )
+                       pthread_mutex_lock( &self->queue_mutex );
                while ( mlt_deque_count( self->queue ) )
                        mlt_frame_close( mlt_deque_pop_back( self->queue ) );
-               pthread_cond_broadcast( &self->queue_cond );
-               pthread_mutex_unlock( &self->queue_mutex );
+               if ( self->ahead && self->real_time ) {
+                       pthread_cond_broadcast( &self->queue_cond );
+                       pthread_mutex_unlock( &self->queue_mutex );
+               }
        }
 }
 
@@ -1357,6 +1392,11 @@ mlt_frame mlt_consumer_rt_frame( mlt_consumer self )
        }
        else // real_time == 0
        {
+               if ( !self->ahead )
+               {
+                       self->ahead = 1;
+                       mlt_events_fire( properties, "consumer-thread-started", NULL );
+               }
                // Get the frame in non real time
                frame = mlt_consumer_get_frame( self );
 
@@ -1447,7 +1487,7 @@ int mlt_consumer_stop( mlt_consumer self )
 int mlt_consumer_is_stopped( mlt_consumer self )
 {
        // Check if the consumer is stopped
-       if ( self->is_stopped != NULL )
+       if ( self && self->is_stopped )
                return self->is_stopped( self );
 
        return 0;
index 741eb0d654db34bc944c3cdf7841bde898fc7376..c76c0e89f4ae5cd51e50a8efcc5cf57c11473fe2 100644 (file)
  * \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
+ * \event \em consumer-frame-show Subclass implementations fire this immediately after showing a frame
+ * or when a frame should be shown (if audio-only consumer).
+ * \event \em consumer-frame-render The base class fires this immediately before rendering a frame.
+ * \event \em consumer-thread-started The base class fires when beginning execution of a rendering thread.
+ * \event \em consumer-thread-stopped The base class fires when a rendering thread has ended.
+ * \event \em consumer-stopped This is fired when the subclass implementation calls mlt_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
@@ -67,7 +70,8 @@
  * \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
  * \properties \em priority the OS scheduling priority for the render threads when real_time is not 0.
- * \properties \em top_field_first when not progressive, whether interlace field order is top-field-first, defaults to 0
+ * \properties \em top_field_first when not progressive, whether interlace field order is top-field-first, defaults to 0.
+ *   Set this to -1 if the consumer does not care about the field order.
  * \properties \em mlt_image_format the image format to request in rendering threads, defaults to yuv422
  * \properties \em mlt_audio_format the audio format to request in rendering threads, defaults to S16
  */
@@ -129,6 +133,7 @@ struct mlt_consumer_s
        int consecutive_rendered;
        int process_head;
        int started;
+       pthread_t *threads; /**< \private used to deallocate all threads */
 };
 
 #define MLT_CONSUMER_SERVICE( consumer )       ( &( consumer )->parent )
index c11c84e4ab82b6dcc71de79d3c307ee8579ad008..ca9c1a622257ca2a9a9404cd2c1dc688633ef42a 100644 (file)
@@ -61,13 +61,7 @@ struct mlt_deque_s
 
 mlt_deque mlt_deque_init( )
 {
-       mlt_deque self = malloc( sizeof( struct mlt_deque_s ) );
-       if ( self != NULL )
-       {
-               self->list = NULL;
-               self->size = 0;
-               self->count = 0;
-       }
+       mlt_deque self = calloc( 1, sizeof( struct mlt_deque_s ) );
        return self;
 }
 
@@ -80,7 +74,10 @@ mlt_deque mlt_deque_init( )
 
 int mlt_deque_count( mlt_deque self )
 {
-       return self->count;
+       if ( self )
+               return self->count;
+       else
+               return 0;
 }
 
 /** Allocate space on the deque.
index 3161d337ccea31dcc58bc30a91f798b6397ccae6..2a9f01530681a4d7b8632ba3d9f61e0e4d892779 100644 (file)
@@ -143,7 +143,7 @@ void mlt_events_init( mlt_properties self )
        mlt_events events = mlt_events_fetch( self );
        if ( events == NULL )
        {
-               events = malloc( sizeof( struct mlt_events_struct ) );
+               events = calloc( 1, sizeof( struct mlt_events_struct ) );
                events->list = mlt_properties_new( );
                mlt_events_store( self, events );
        }
@@ -382,7 +382,6 @@ void mlt_events_disconnect( mlt_properties self, void *service )
 
 typedef struct
 {
-       int done;
        pthread_cond_t cond;
        pthread_mutex_t mutex;
 }
@@ -398,11 +397,8 @@ condition_pair;
 static void mlt_events_listen_for( mlt_properties self, condition_pair *pair )
 {
        pthread_mutex_lock( &pair->mutex );
-       if ( pair->done == 0 )
-       {
-               pthread_cond_signal( &pair->cond );
-               pthread_mutex_unlock( &pair->mutex );
-       }
+       pthread_cond_signal( &pair->cond );
+       pthread_mutex_unlock( &pair->mutex );
 }
 
 /** Prepare to wait for an event.
@@ -416,7 +412,6 @@ static void mlt_events_listen_for( mlt_properties self, condition_pair *pair )
 mlt_event mlt_events_setup_wait_for( mlt_properties self, 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 );
@@ -452,10 +447,10 @@ void mlt_events_close_wait_for( mlt_properties self, mlt_event event )
        {
                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 );
+               free( pair );
        }
 }
 
index cf1261822b7bb855dce20a1665e70ca3145c647c..5c0c877f744c81b0c466e92f8699a5bb748386fa 100644 (file)
 #define PREFIX_LIB "/lib/mlt"
 /** the default subdirectory of the install prefix for holding module (plugin) data */
 #define PREFIX_DATA "/share/mlt"
-#else
-/** 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 MLTDATADIR "/mlt"
 #endif
 
 /** holds the full path to the modules directory - initialized and retained for the entire session */
index 6dc822808d8d98d02d791a7125e452f803e798c5..95c92b96575205dd441ed627f65e5afbcbac75f4 100644 (file)
@@ -57,7 +57,7 @@ struct mlt_field_s
 mlt_field mlt_field_init( )
 {
        // Initialise the field
-       mlt_field self = calloc( sizeof( struct mlt_field_s ), 1 );
+       mlt_field self = calloc( 1, sizeof( struct mlt_field_s ) );
 
        // Initialise it
        if ( self != NULL )
@@ -90,7 +90,7 @@ mlt_field mlt_field_init( )
 mlt_field mlt_field_new( mlt_multitrack multitrack, mlt_tractor tractor )
 {
        // Initialise the field
-       mlt_field self = calloc( sizeof( struct mlt_field_s ), 1 );
+       mlt_field self = calloc( 1, sizeof( struct mlt_field_s ) );
 
        // Initialise it
        if ( self != NULL )
index 19f6f25fd9aa04597aec0a319691d9fdd2d745fb..ed4d9192c32c43e8fe96f26ae053d699a9bcffb9 100644 (file)
@@ -74,9 +74,15 @@ int mlt_filter_init( mlt_filter self, void *child )
 mlt_filter mlt_filter_new( )
 {
        mlt_filter self = calloc( 1, sizeof( struct mlt_filter_s ) );
-       if ( self != NULL )
-               mlt_filter_init( self, NULL );
-       return self;
+       if ( self != NULL && mlt_filter_init( self, NULL ) == 0 )
+       {
+               return self;
+       }
+       else
+       {
+               free(self);
+               return NULL;
+       }
 }
 
 /** Get the service class interface.
@@ -253,8 +259,8 @@ mlt_position mlt_filter_get_position( mlt_filter self, mlt_frame frame )
        char name[20];
 
        // Make the properties key from unique id
-       strcpy( name, "pos." );
-       strcat( name, unique_id );
+       snprintf( name, 20, "pos.%s", unique_id );
+       name[20 - 1] = '\0';
 
        return mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), name ) - in;
 }
@@ -298,8 +304,8 @@ mlt_frame mlt_filter_process( mlt_filter self, mlt_frame frame )
        char name[20];
 
        // Make the properties key from unique id
-       strcpy( name, "pos." );
-       strcat( name, unique_id );
+       snprintf( name, 20, "pos.%s", unique_id );
+       name[20 -1] = '\0';
 
        // Save the position on the frame
        mlt_properties_set_position( MLT_FRAME_PROPERTIES( frame ), name, position );
index 612592932a7df6d7834780178e59b114a3c9759f..7b431df7bcd2bb09930eba5ddb1448039ec550a8 100644 (file)
@@ -41,7 +41,7 @@
 mlt_frame mlt_frame_init( mlt_service service )
 {
        // Allocate a frame
-       mlt_frame self = calloc( sizeof( struct mlt_frame_s ), 1 );
+       mlt_frame self = calloc( 1, sizeof( struct mlt_frame_s ) );
 
        if ( self != NULL )
        {
@@ -56,8 +56,6 @@ mlt_frame mlt_frame_init( mlt_service service )
                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 );
@@ -133,10 +131,15 @@ int mlt_frame_set_aspect_ratio( mlt_frame self, double value )
 }
 
 /** Get the time position of this frame.
+ *
+ * This position is not necessarily the position as the original
+ * producer knows it. It could be the position that the playlist,
+ * multitrack, or tractor producer set.
  *
  * \public \memberof mlt_frame_s
  * \param self a frame
  * \return the position
+ * \see mlt_frame_original_position
  */
 
 mlt_position mlt_frame_get_position( mlt_frame self )
@@ -145,6 +148,21 @@ mlt_position mlt_frame_get_position( mlt_frame self )
        return pos < 0 ? 0 : pos;
 }
 
+/** Get the original time position of this frame.
+ *
+ * This is the position that the original producer set on the frame.
+ *
+ * \public \memberof mlt_frame_s
+ * \param self a frame
+ * \return the position
+ */
+
+mlt_position mlt_frame_original_position( mlt_frame self )
+{
+       int pos = mlt_properties_get_position( MLT_FRAME_PROPERTIES( self ), "original_position" );
+       return pos < 0 ? 0 : pos;
+}
+
 /** Set the time position of this frame.
  *
  * \public \memberof mlt_frame_s
@@ -155,6 +173,9 @@ mlt_position mlt_frame_get_position( mlt_frame self )
 
 int mlt_frame_set_position( mlt_frame self, mlt_position value )
 {
+       // Only set the original_position the first time.
+       if ( ! mlt_properties_get( MLT_FRAME_PROPERTIES( self ), "original_position" ) )
+               mlt_properties_set_position( MLT_FRAME_PROPERTIES( self ), "original_position", value );
        return mlt_properties_set_position( MLT_FRAME_PROPERTIES( self ), "_position", value );
 }
 
@@ -322,6 +343,7 @@ int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructo
 
 int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy )
 {
+       self->get_alpha_mask = NULL;
        return mlt_properties_set_data( MLT_FRAME_PROPERTIES( self ), "alpha", alpha, size, destroy, NULL );
 }
 
@@ -381,6 +403,8 @@ const char * mlt_image_format_name( mlt_image_format format )
                case mlt_image_yuv422:  return "yuv422";
                case mlt_image_yuv420p: return "yuv420p";
                case mlt_image_opengl:  return "opengl";
+               case mlt_image_glsl:    return "glsl";
+               case mlt_image_glsl_texture: return "glsl_texture";
        }
        return "invalid";
 }
@@ -399,9 +423,6 @@ int mlt_image_format_size( mlt_image_format format, int width, int height, int *
        height += 1;
        switch ( format )
        {
-               case mlt_image_none:
-                       if ( bpp ) *bpp = 0;
-                       return 0;
                case mlt_image_rgb24:
                        if ( bpp ) *bpp = 3;
                        return width * height * 3;
@@ -415,6 +436,9 @@ int mlt_image_format_size( mlt_image_format format, int width, int height, int *
                case mlt_image_yuv420p:
                        if ( bpp ) *bpp = 3 / 2;
                        return width * height * 3 / 2;
+               default:
+                       if ( bpp ) *bpp = 0;
+                       return 0;
        }
        return 0;
 }
@@ -484,7 +508,6 @@ int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *for
                if ( test_frame )
                {
                        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 );
@@ -517,10 +540,6 @@ int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *for
 
                switch( *format )
                {
-                       case mlt_image_none:
-                               size = 0;
-                               *buffer = NULL;
-                               break;
                        case mlt_image_rgb24:
                                size *= 3;
                                size += *width * 3;
@@ -554,6 +573,10 @@ int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *for
                                if ( *buffer )
                                        memset( *buffer, 255, size );
                                break;
+                       default:
+                               size = 0;
+                               *buffer = NULL;
+                               break;
                }
 
                mlt_properties_set_data( properties, "image", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
@@ -608,6 +631,7 @@ const char * mlt_audio_format_name( mlt_audio_format format )
                case mlt_audio_s32le:  return "s32le";
                case mlt_audio_float:  return "float";
                case mlt_audio_f32le:  return "f32le";
+               case mlt_audio_u8:     return "u8";
        }
        return "invalid";
 }
@@ -631,6 +655,7 @@ int mlt_audio_format_size( mlt_audio_format format, int samples, int channels )
                case mlt_audio_s32:    return samples * channels * sizeof( int32_t );
                case mlt_audio_f32le:
                case mlt_audio_float:  return samples * channels * sizeof( float );
+               case mlt_audio_u8:     return samples * channels;
        }
        return 0;
 }
@@ -800,9 +825,13 @@ unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h )
 
        // Make an 8-bit buffer large enough to hold rendering
        int size = w * h;
+       if ( size <= 0 )
+               return NULL;
        unsigned char *bitmap = ( unsigned char* )mlt_pool_alloc( size );
        if ( bitmap != NULL )
                memset( bitmap, 0, size );
+       else
+               return NULL;
        mlt_properties_set_data( properties, "waveform", bitmap, size, ( mlt_destructor )mlt_pool_release, NULL );
 
        // Render vertical lines
@@ -926,8 +955,8 @@ int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position
 
 void mlt_frame_write_ppm( mlt_frame frame )
 {
-       int width;
-       int height;
+       int width = 0;
+       int height = 0;
        mlt_image_format format = mlt_image_rgb24;
        uint8_t *image;
        
@@ -1000,6 +1029,13 @@ mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
        int size;
 
        mlt_properties_inherit( new_props, properties );
+
+       // Carry over some special data properties for the multi consumer.
+       mlt_properties_set_data( new_props, "_producer",
+               mlt_frame_get_original_producer( self ), 0, NULL, NULL );
+       mlt_properties_set_data( new_props, "movit.convert",
+               mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );
+
        if ( is_deep )
        {
                data = mlt_properties_get_data( properties, "audio", &size );
@@ -1023,6 +1059,17 @@ mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
                        copy = mlt_pool_alloc( size );
                        memcpy( copy, data, size );
                        mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );
+
+                       data = mlt_properties_get_data( properties, "alpha", &size );
+                       if ( data )
+                       {
+                               if ( ! size )
+                                       size = mlt_properties_get_int( properties, "width" ) *
+                                               mlt_properties_get_int( properties, "height" );
+                               copy = mlt_pool_alloc( size );
+                               memcpy( copy, data, size );
+                               mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
+                       };
                }
        }
        else
@@ -1037,6 +1084,8 @@ mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
                mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
                data = mlt_properties_get_data( properties, "image", &size );
                mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
+               data = mlt_properties_get_data( properties, "alpha", &size );
+               mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );
        }
 
        return new_frame;
index 144d867d0a2fd529e293a96c00eeba4a1b81cef8..74e63b8007143d32b1ab6fba2c72827e08cdd012 100644 (file)
@@ -115,6 +115,7 @@ 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 mlt_position mlt_frame_original_position( mlt_frame self );
 extern int mlt_frame_set_position( mlt_frame self, mlt_position value );
 extern int mlt_frame_set_image( mlt_frame self, uint8_t *image, int size, mlt_destructor destroy );
 extern int mlt_frame_set_alpha( mlt_frame self, uint8_t *alpha, int size, mlt_destructor destroy );
index c4d989fb13408e5b92f89ad8ca41683b1bf58e7d..301963ddca24b0fe0ed0eea7796b8d11ae09bd4b 100644 (file)
@@ -689,7 +689,7 @@ char *mlt_geometry_serialise( mlt_geometry self )
                        free( g->data );
                g->data = ret;
        }
-       return ret;
+       return strdup( ret );
 }
 
 // Close the geometry
index dc030998adb826d7aed42bef17fe9acd2764a965..463090729b2fb845ed78e4e31e55631118c76b86 100644 (file)
@@ -43,7 +43,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 mlt_multitrack mlt_multitrack_init( )
 {
        // Allocate the multitrack object
-       mlt_multitrack self = calloc( sizeof( struct mlt_multitrack_s ), 1 );
+       mlt_multitrack self = calloc( 1, sizeof( struct mlt_multitrack_s ) );
 
        if ( self != NULL )
        {
@@ -323,7 +323,7 @@ mlt_position mlt_multitrack_clip( mlt_multitrack self, mlt_whence whence, int in
        mlt_position position = 0;
        int i = 0;
        int j = 0;
-       mlt_position *map = malloc( 1000 * sizeof( mlt_position ) );
+       mlt_position *map = calloc( 1000, sizeof( mlt_position ) );
        int count = 0;
 
        for ( i = 0; i < self->count; i ++ )
index 356b0d79de09543136165e8c1b8adfe05e41980c..1d2851ec73989d94460e1a44ee503f62c1b250cb 100644 (file)
@@ -53,6 +53,7 @@ struct playlist_entry_s
 static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index );
 static int mlt_playlist_unmix( mlt_playlist self, int clip );
 static int mlt_playlist_resize_mix( mlt_playlist self, int clip, int in, int out );
+static void mlt_playlist_next( mlt_listener listener, mlt_properties owner, mlt_service self, void **args );
 
 /** Construct a playlist.
  *
@@ -64,13 +65,13 @@ static int mlt_playlist_resize_mix( mlt_playlist self, int clip, int in, int out
 
 mlt_playlist mlt_playlist_init( )
 {
-       mlt_playlist self = calloc( sizeof( struct mlt_playlist_s ), 1 );
+       mlt_playlist self = calloc( 1, sizeof( struct mlt_playlist_s ) );
        if ( self != NULL )
        {
                mlt_producer producer = &self->parent;
 
                // Construct the producer
-               mlt_producer_init( producer, self );
+               if ( mlt_producer_init( producer, self ) != 0 ) goto error1;
 
                // Override the producer get_frame
                producer->get_frame = producer_get_frame;
@@ -80,7 +81,7 @@ mlt_playlist mlt_playlist_init( )
                producer->close_object = self;
 
                // Initialise blank
-               mlt_producer_init( &self->blank, NULL );
+               if ( mlt_producer_init( &self->blank, NULL ) != 0 ) goto error1;
                mlt_properties_set( MLT_PRODUCER_PROPERTIES( &self->blank ), "mlt_service", "blank" );
                mlt_properties_set( MLT_PRODUCER_PROPERTIES( &self->blank ), "resource", "blank" );
 
@@ -96,10 +97,35 @@ mlt_playlist mlt_playlist_init( )
                mlt_properties_set_position( MLT_PLAYLIST_PROPERTIES( self ), "length", 0 );
 
                self->size = 10;
-               self->list = malloc( self->size * sizeof( playlist_entry * ) );
+               self->list = calloc( self->size, sizeof( playlist_entry * ) );
+               if ( self->list == NULL ) goto error2;
+               
+               mlt_events_register( MLT_PLAYLIST_PROPERTIES( self ), "playlist-next", (mlt_transmitter) mlt_playlist_next );
        }
 
        return self;
+error2:
+       free( self->list );
+error1:
+       free( self );
+       return NULL;
+}
+
+/** Construct a playlist with a profile.
+ *
+ * Sets the resource property to "<playlist>".
+ * Set the mlt_type to property to "mlt_producer".
+ * \public \memberof mlt_playlist_s
+ * \param profile the profile to use with the profile
+ * \return a new playlist
+ */
+
+mlt_playlist mlt_playlist_new( mlt_profile profile )
+{
+    mlt_playlist self = mlt_playlist_init();
+    if ( self )
+        mlt_properties_set_data( MLT_PLAYLIST_PROPERTIES( self ), "_profile", profile, 0, NULL, NULL );
+    return self;
 }
 
 /** Get the producer associated to this playlist.
@@ -312,7 +338,7 @@ static int mlt_playlist_virtual_append( mlt_playlist self, mlt_producer source,
        }
 
        // Create the entry
-       self->list[ self->count ] = calloc( sizeof( playlist_entry ), 1 );
+       self->list[ self->count ] = calloc( 1, sizeof( playlist_entry ) );
        if ( self->list[ self->count ] != NULL )
        {
                self->list[ self->count ]->producer = producer;
@@ -370,6 +396,24 @@ static mlt_producer mlt_playlist_locate( mlt_playlist self, mlt_position *positi
        return producer;
 }
 
+/** The transmitter for the producer-next event
+ *
+ * Invokes the listener.
+ *
+ * \private \memberof mlt_playlist_s
+ * \param listener a function pointer that will be invoked
+ * \param owner the events object that will be passed to \p listener
+ * \param self a service that will be passed to \p listener
+ * \param args an array of pointers.
+ */
+
+static void mlt_playlist_next( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
+{
+       if ( listener )
+               listener( owner, self, args[ 0 ] );
+}
+
+
 /** Seek in the virtual playlist.
  *
  * This gets the producer at the current position and seeks on the producer
@@ -457,6 +501,10 @@ static mlt_service mlt_playlist_virtual_seek( mlt_playlist self, int *progressiv
                producer = &self->blank;
        }
 
+       // Determine if we have moved to the next entry in the playlist.
+       if ( original == total - 2 )
+               mlt_events_fire( properties, "playlist-next", i, NULL );
+
        return MLT_PRODUCER_SERVICE( producer );
 }
 
@@ -702,15 +750,36 @@ int mlt_playlist_append_io( mlt_playlist self, mlt_producer producer, mlt_positi
  *
  * \public \memberof mlt_playlist_s
  * \param self a playlist
- * \param length the ending time of the blank entry, not its duration
+ * \param out the ending time of the blank entry, not its duration
  * \return true if there was an error
  */
 
-int mlt_playlist_blank( mlt_playlist self, mlt_position length )
+int mlt_playlist_blank( mlt_playlist self, mlt_position out )
 {
        // Append to the virtual list
-       if (length >= 0)
-               return mlt_playlist_virtual_append( self, &self->blank, 0, length );
+       if ( out >= 0 )
+               return mlt_playlist_virtual_append( self, &self->blank, 0, out );
+       else
+               return 1;
+}
+
+/** Append a blank item to the playlist with duration as a time string.
+ *
+ * \public \memberof mlt_playlist_s
+ * \param self a playlist
+ * \param length the duration of the blank entry as a time string
+ * \return true if there was an error
+ */
+
+int mlt_playlist_blank_time( mlt_playlist self, const char* length )
+{
+       if ( self && length )
+       {
+               mlt_properties properties = MLT_PLAYLIST_PROPERTIES( self );
+               mlt_properties_set( properties , "_blank_time", length );
+               mlt_position duration = mlt_properties_get_position( properties, "_blank_time" );
+               return mlt_playlist_blank( self, duration - 1 );
+       }
        else
                return 1;
 }
@@ -767,12 +836,6 @@ int mlt_playlist_remove( mlt_playlist self, int where )
                // Get the clip info
                mlt_playlist_get_clip_info( self, &where_info, where );
 
-               // Make sure the clip to be removed is valid and correct if necessary
-               if ( where < 0 )
-                       where = 0;
-               if ( where >= self->count )
-                       where = self->count - 1;
-
                // Reorganise the list
                for ( i = where + 1; i < self->count; i ++ )
                        self->list[ i - 1 ] = self->list[ i ];
@@ -1067,7 +1130,7 @@ int mlt_playlist_join( mlt_playlist self, int clip, int count, int merge )
        if ( error == 0 )
        {
                int i = clip;
-               mlt_playlist new_clip = mlt_playlist_init( );
+               mlt_playlist new_clip = mlt_playlist_new( mlt_service_profile( MLT_PLAYLIST_SERVICE(self) ) );
                mlt_events_block( MLT_PLAYLIST_PROPERTIES( self ), self );
                if ( clip + count >= self->count )
                        count = self->count - clip - 1;
index a6364316e943d9e4e4f596a122aadc8455df9495..58903823e4c593fdb0ee54b47942002dd0099465 100644 (file)
@@ -63,6 +63,8 @@ typedef struct playlist_entry_s playlist_entry;
  * 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
+ * \event \em playlist-next The playlist fires this when it moves to the next item in the list.
+ * The listener receives one argument that is the index of the entry that just completed.
  */
 
 struct mlt_playlist_s
@@ -80,6 +82,7 @@ struct mlt_playlist_s
 #define MLT_PLAYLIST_PROPERTIES( playlist )    MLT_SERVICE_PROPERTIES( MLT_PLAYLIST_SERVICE( playlist ) )
 
 extern mlt_playlist mlt_playlist_init( );
+extern mlt_playlist mlt_playlist_new( mlt_profile profile );
 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 );
@@ -87,7 +90,8 @@ 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 int mlt_playlist_blank( mlt_playlist self, mlt_position out );
+extern int mlt_playlist_blank_time( mlt_playlist self, const char *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 );
index bffdc905b31ef0c32fed7bc2dbc930b99342fbbe..6e33edf32deb22b4bb0b2797c1466bcfe0c1ef1e 100644 (file)
@@ -156,6 +156,11 @@ mlt_producer mlt_producer_new( mlt_profile profile )
                        mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( self ), "_profile", profile, 0, NULL, NULL );
                        mlt_properties_set_double( MLT_PRODUCER_PROPERTIES( self ), "aspect_ratio", mlt_profile_sar( profile ) );
                }
+               else
+               {
+                       free( self );
+                       return NULL;
+               }
        }
        return self;
 }
@@ -287,6 +292,7 @@ mlt_properties mlt_producer_properties( mlt_producer self )
  * \param position set the "play head" position of the producer
  * \return false
  * \todo Document how the properties affect behavior.
+ * \see mlt_producer_seek_time
  */
 
 int mlt_producer_seek( mlt_producer self, mlt_position position )
@@ -311,7 +317,7 @@ int mlt_producer_seek( mlt_producer self, mlt_position position )
                mlt_producer_set_speed( self, 0 );
                position = mlt_producer_get_playtime( self ) - 1;
        }
-       else if ( use_points && !strcmp( eof, "loop" ) && position >= mlt_producer_get_playtime( self ) )
+       else if ( use_points && eof && !strcmp( eof, "loop" ) && position >= mlt_producer_get_playtime( self ) )
        {
                position = (int)position % (int)mlt_producer_get_playtime( self );
        }
@@ -325,6 +331,22 @@ int mlt_producer_seek( mlt_producer self, mlt_position position )
        return 0;
 }
 
+/** Seek to a specified time string.
+ *
+ * \public \memberof mlt_producer_s
+ * \param self a producer
+ * \param time set the "play head" position of the producer to the time string
+ * \return false
+ * \see mlt_producer_seek
+ */
+
+int mlt_producer_seek_time( mlt_producer self, const char* time )
+{
+    mlt_properties_set( MLT_PRODUCER_PROPERTIES(self), "_seek_time", time );
+    mlt_position position = mlt_properties_get_position( MLT_PRODUCER_PROPERTIES(self), "_seek_time" );
+    return mlt_producer_seek( self, position );
+}
+
 /** Get the current position (relative to in point).
  *
  * \public \memberof mlt_producer_s
@@ -349,6 +371,19 @@ mlt_position mlt_producer_frame( mlt_producer self )
        return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( self ), "_frame" );
 }
 
+/** Get the current position (relative to start of producer) as a time string.
+ *
+ * \public \memberof mlt_producer_s
+ * \param self a producer
+ * \param format the time value format
+ * \return the position of the "play head" regardless of the in point
+ */
+
+char* mlt_producer_frame_time( mlt_producer self, mlt_time_format format )
+{
+    return mlt_properties_get_time( MLT_PRODUCER_PROPERTIES( self ), "_frame", format );
+}
+
 /** Set the playing speed.
  *
  * \public \memberof mlt_producer_s
@@ -509,6 +544,21 @@ mlt_position mlt_producer_get_length( mlt_producer self )
        return mlt_properties_get_position( MLT_PRODUCER_PROPERTIES( self ), "length" );
 }
 
+/** Get the total, unedited length of the producer as a time string.
+ *
+ * The value returned by a live streaming producer is unknown.
+ *
+ * \public \memberof mlt_producer_s
+ * \param self a producer
+ * \param format the time value format
+ * \return the duration of the producer regardless of in and out points
+ */
+
+char* mlt_producer_get_length_time( mlt_producer self, mlt_time_format format )
+{
+    return mlt_properties_get_time( MLT_PRODUCER_PROPERTIES( self ), "length", format );
+}
+
 /** Prepare for next frame.
  *
  * Advance the play out position. If the speed is less than zero, it will
index 9a0400e0a7d494c34e404a286a43a8c6d2b95ff7..8e226f2bdd98dd13b08864b245aef95d424fb131 100644 (file)
@@ -36,7 +36,7 @@
  * service network - that could be through synthesis or reading a stream.
  *
  * \extends mlt_service
- * \event \em producer-changed
+ * \event \em producer-changed either service-changed was fired or the timing of the 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
@@ -93,8 +93,10 @@ extern mlt_producer mlt_producer_new( mlt_profile );
 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 int mlt_producer_seek_time( mlt_producer self, const char* time );
 extern mlt_position mlt_producer_position( mlt_producer self );
 extern mlt_position mlt_producer_frame( mlt_producer self );
+char* mlt_producer_frame_time( mlt_producer self, mlt_time_format );
 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 );
@@ -104,6 +106,7 @@ 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 char* mlt_producer_get_length_time( mlt_producer self, mlt_time_format );
 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 );
index 66f76012aee88f0d89807078e78114230dc7247b..06fa2c3212b505f4c9d9cfe1e2aeda601568e3dd 100644 (file)
@@ -231,6 +231,8 @@ mlt_profile mlt_profile_load_properties( mlt_properties properties )
 mlt_profile mlt_profile_load_string( const char *string )
 {
        mlt_properties properties = mlt_properties_new();
+       mlt_profile profile = NULL;
+
        if ( properties )
        {
                const char *p = string;
@@ -241,8 +243,10 @@ mlt_profile mlt_profile_load_string( const char *string )
                        p = strchr( p, '\n' );
                        if ( p ) p++;
                }
+               profile = mlt_profile_load_properties( properties );
+               mlt_properties_close( properties );
        }
-       return mlt_profile_load_properties( properties );
+       return profile;
 }
 
 /** Get the video frame rate as a floating point value.
@@ -399,14 +403,13 @@ void mlt_profile_from_producer( mlt_profile profile, mlt_producer producer )
 {
        mlt_frame fr = NULL;
        uint8_t *buffer;
-       mlt_image_format fmt = mlt_image_yuv422;
+       mlt_image_format fmt = mlt_image_none;
        mlt_properties p;
        int w = profile->width;
        int h = profile->height;
 
        if ( ! mlt_service_get_frame( MLT_PRODUCER_SERVICE(producer), &fr, 0 ) && fr )
        {
-               mlt_properties_set_double( MLT_FRAME_PROPERTIES( fr ), "consumer_aspect_ratio", mlt_profile_sar( profile ) );
                if ( ! mlt_frame_get_image( fr, &buffer, &fmt, &w, &h, 0 ) )
                {
                        // Some source properties are not exposed until after the first get_image call.
index c381e239a0828a97ed3bbe94ecb74f9f4043d186..4172c405cf6638166db59469574923300099eb53 100644 (file)
@@ -91,7 +91,7 @@ int mlt_properties_init( mlt_properties self, void *child )
                self->child = child;
 
                // Allocate the local structure
-               self->local = calloc( sizeof( property_list ), 1 );
+               self->local = calloc( 1, sizeof( property_list ) );
 
                // Increment the ref count
                ( ( property_list * )self->local )->ref_count = 1;
@@ -113,7 +113,7 @@ int mlt_properties_init( mlt_properties self, void *child )
 mlt_properties mlt_properties_new( )
 {
        // Construct a standalone properties object
-       mlt_properties self = calloc( sizeof( struct mlt_properties_s ), 1 );
+       mlt_properties self = calloc( 1, sizeof( struct mlt_properties_s ) );
 
        // Initialise self
        mlt_properties_init( self, NULL );
@@ -192,8 +192,10 @@ static int load_properties( mlt_properties self, const char *filename )
                // Read each string from the file
                while( fgets( temp, 1024, file ) )
                {
-                       // Chomp the string
-                       temp[ strlen( temp ) - 1 ] = '\0';
+                       // Chomp the new line character from the string
+                       int x = strlen( temp ) - 1;
+                       if ( temp[x] == '\n' || temp[x] == '\r' )
+                               temp[x] = '\0';
 
                        // Check if the line starts with a .
                        if ( temp[ 0 ] == '.' )
@@ -481,6 +483,7 @@ int mlt_properties_pass( mlt_properties self, mlt_properties that, const char *p
 
 static inline mlt_property mlt_properties_find( mlt_properties self, const char *name )
 {
+       if ( !name ) return NULL;
        property_list *list = self->local;
        mlt_property value = NULL;
        int key = generate_hash( name );
@@ -617,7 +620,8 @@ int mlt_properties_pass_list( mlt_properties self, mlt_properties that, const ch
                mlt_properties_pass_property( self, that, ptr );
 
                ptr += count + 1;
-               ptr += strspn( ptr, delim );
+               if ( !done )
+                       ptr += strspn( ptr, delim );
        }
 
        free( props );
@@ -871,8 +875,11 @@ int mlt_properties_parse( mlt_properties self, const char *namevalue )
 
 int mlt_properties_get_int( mlt_properties self, const char *name )
 {
+       mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+       double fps = mlt_profile_fps( profile );
+       property_list *list = self->local;
        mlt_property value = mlt_properties_find( self, name );
-       return value == NULL ? 0 : mlt_property_get_int( value );
+       return value == NULL ? 0 : mlt_property_get_int( value, fps, list->locale );
 }
 
 /** Set a property to an integer value.
@@ -955,9 +962,11 @@ int mlt_properties_set_int64( mlt_properties self, const char *name, int64_t val
 
 double mlt_properties_get_double( mlt_properties self, const char *name )
 {
+       mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+       double fps = mlt_profile_fps( profile );
        mlt_property value = mlt_properties_find( self, name );
        property_list *list = self->local;
-       return value == NULL ? 0 : mlt_property_get_double_l( value, list->locale );
+       return value == NULL ? 0 : mlt_property_get_double( value, fps, list->locale );
 }
 
 /** Set a property to a floating point value.
@@ -998,8 +1007,11 @@ int mlt_properties_set_double( mlt_properties self, const char *name, double val
 
 mlt_position mlt_properties_get_position( mlt_properties self, const char *name )
 {
+       mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+       double fps = mlt_profile_fps( profile );
+       property_list *list = self->local;
        mlt_property value = mlt_properties_find( self, name );
-       return value == NULL ? 0 : mlt_property_get_position( value );
+       return value == NULL ? 0 : mlt_property_get_position( value, fps, list->locale );
 }
 
 /** Set a property to a position value.
@@ -1373,7 +1385,8 @@ struct yaml_parser_context
 {
        mlt_deque stack;
        unsigned int level;
-       unsigned int index;
+       int index;
+       mlt_deque index_stack;
        char block;
        char *block_name;
        unsigned int block_indent;
@@ -1429,7 +1442,7 @@ static int parse_yaml( yaml_parser context, const char *namevalue )
        int error = 0;
        char *ptr = strchr( name, ':' );
        unsigned int indent = ltrim( &name );
-       mlt_properties properties = mlt_deque_peek_front( context->stack );
+       mlt_properties properties = mlt_deque_peek_back( context->stack );
 
        // Ascending one more levels in the tree
        if ( indent < context->level )
@@ -1437,8 +1450,11 @@ static int parse_yaml( yaml_parser context, const char *namevalue )
                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 );
+               {
+                       mlt_deque_pop_back( context->stack );
+                       context->index = mlt_deque_pop_back_int( context->index_stack );
+               }
+               properties = mlt_deque_peek_back( context->stack );
                context->level = indent;
        }
 
@@ -1480,7 +1496,8 @@ static int parse_yaml( yaml_parser context, const char *namevalue )
                        mlt_properties_set_lcnumeric( child, mlt_properties_get_lcnumeric( properties ) );
                        mlt_properties_set_data( properties, name, child, 0,
                                ( mlt_destructor )mlt_properties_close, NULL );
-                       mlt_deque_push_front( context->stack, child );
+                       mlt_deque_push_back( context->stack, child );
+                       mlt_deque_push_back_int( context->index_stack, context->index );
                        context->index = 0;
                        free( name_ );
                        return error;
@@ -1496,7 +1513,8 @@ static int parse_yaml( yaml_parser context, const char *namevalue )
                        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 );
+                       mlt_deque_push_back( context->stack, child );
+                       mlt_deque_push_back_int( context->index_stack, context->index );
 
                        name ++;
                        context->level += ltrim( &name ) + 1;
@@ -1670,7 +1688,9 @@ mlt_properties mlt_properties_parse_yaml( const char *filename )
                        // Parser context
                        yaml_parser context = calloc( 1, sizeof( struct yaml_parser_context ) );
                        context->stack = mlt_deque_init();
-                       mlt_deque_push_front( context->stack, self );
+                       context->index_stack = mlt_deque_init();
+                       mlt_deque_push_back( context->stack, self );
+                       mlt_deque_push_back_int( context->index_stack, 0 );
 
                        // Read each string from the file
                        while( fgets( temp, 1024, file ) )
@@ -1691,6 +1711,7 @@ mlt_properties mlt_properties_parse_yaml( const char *filename )
                        // Close the file
                        fclose( file );
                        mlt_deque_close( context->stack );
+                       mlt_deque_close( context->index_stack );
                        if ( context->block_name )
                                free( context->block_name );
                        free( context );
@@ -1791,6 +1812,23 @@ static inline void indent_yaml( strbuf output, int indent )
                strbuf_printf( output, " " );
 }
 
+static void strbuf_escape( strbuf output, const char *value, char c )
+{
+       char *v = strdup( value );
+       char *s = v;
+       char *found = strchr( s, c );
+
+       while ( found )
+       {
+               *found = '\0';
+               strbuf_printf( output, "%s\\%c", s, c );
+               s = found + 1;
+               found = strchr( s, c );
+       }
+       strbuf_printf( output, "%s", s );
+       free( v );
+}
+
 /** Convert a line string into a YAML block literal.
  *
  * \private \memberof strbuf_s
@@ -1815,6 +1853,7 @@ static void output_yaml_block_literal( strbuf output, const char *value, int ind
        }
        indent_yaml( output, indent );
        strbuf_printf( output, "%s\n", sol );
+       free( v );
 }
 
 /** Recursively serialize a properties list into a string buffer as YAML Tiny.
@@ -1856,6 +1895,12 @@ static void serialise_yaml( mlt_properties self, strbuf output, int indent, int
                                                strbuf_printf( output, "|\n" );
                                                output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( "|" ) );
                                        }
+                                       else if ( strchr( value, ':' ) || strchr( value, '[' ) )
+                                       {
+                                               strbuf_printf( output, "\"" );
+                                               strbuf_escape( output, value, '"' );
+                                               strbuf_printf( output, "\"\n", value );
+                                       }
                                        else
                                        {
                                                strbuf_printf( output, "%s\n", value );
@@ -1886,6 +1931,12 @@ static void serialise_yaml( mlt_properties self, strbuf output, int indent, int
                                        strbuf_printf( output, "%s: |\n", list->name[ i ] );
                                        output_yaml_block_literal( output, value, indent + strlen( list->name[ i ] ) + strlen( ": " ) );
                                }
+                               else if ( strchr( value, ':' ) || strchr( value, '[' ) )
+                               {
+                                       strbuf_printf( output, "%s: \"", list->name[ i ] );
+                                       strbuf_escape( output, value, '"' );
+                                       strbuf_printf( output, "\"\n" );
+                               }
                                else
                                {
                                        strbuf_printf( output, "%s: %s\n", list->name[ i ], value );
@@ -1952,3 +2003,26 @@ void mlt_properties_unlock( mlt_properties self )
        if ( self )
                pthread_mutex_unlock( &( ( property_list* )( self->local ) )->mutex );
 }
+
+/** Get a time string associated to the name.
+ *
+ * Do not free the returned string. It's lifetime is controlled by the property.
+ * \public \memberof mlt_properties_s
+ * \param self a properties list
+ * \param name the property to get
+ * \param format the time format that you want
+ * \return the property's time value or NULL if \p name does not exist or there is no profile
+ */
+
+char *mlt_properties_get_time( mlt_properties self, const char* name, mlt_time_format format )
+{
+       mlt_profile profile = mlt_properties_get_data( self, "_profile", NULL );
+       if ( profile )
+       {
+               double fps = mlt_profile_fps( profile );
+               mlt_property value = mlt_properties_find( self, name );
+               property_list *list = self->local;
+               return value == NULL ? NULL : mlt_property_get_time( value, format, fps, list->locale );
+       }
+       return NULL;
+}
index 57c653ff7ff725cda73574a815293765089d4977..449f3630706aaef1e5049fa9747ad5d621a8c2a8 100644 (file)
@@ -88,5 +88,6 @@ extern mlt_properties mlt_properties_parse_yaml( const char *file );
 extern char *mlt_properties_serialise_yaml( mlt_properties self );
 extern void mlt_properties_lock( mlt_properties self );
 extern void mlt_properties_unlock( mlt_properties self );
+extern char *mlt_properties_get_time( mlt_properties, const char* name, mlt_time_format );
 
 #endif
index 3cc9f8b8bdfc3151916067fb1f11b9c714bdde5e..4d5f57c7c53ed84c1c7acadc77e90e6c0beaf796 100644 (file)
@@ -264,10 +264,105 @@ int mlt_property_set_data( mlt_property self, void *value, int length, mlt_destr
        return 0;
 }
 
-/** Convert a base 10 or base 16 string to an integer.
+/** Parse a SMIL clock value.
+ *
+ * \private \memberof mlt_property_s
+ * \param s the string to parse
+ * \param fps frames per second
+ * \param locale the locale to use for parsing a real number value
+ * \return position in frames
+ */
+
+static int time_clock_to_frames( const char *s, double fps, locale_t locale )
+{
+       char *pos, *copy = strdup( s );
+       int hours = 0, minutes = 0;
+       double seconds;
+
+       s = copy;
+       pos = strrchr( s, ':' );
+       if ( pos ) {
+#if defined(__GLIBC__) || defined(__DARWIN__)
+               if ( locale )
+                       seconds = strtod_l( pos + 1, NULL, locale );
+               else
+#endif
+                       seconds = strtod( pos + 1, NULL );
+               *pos = 0;
+               pos = strrchr( s, ':' );
+               if ( pos ) {
+                       minutes = atoi( pos + 1 );
+                       *pos = 0;
+                       hours = atoi( s );
+               }
+               else {
+                       minutes = atoi( s );
+               }
+       }
+       else {
+#if defined(__GLIBC__) || defined(__DARWIN__)
+               if ( locale )
+                       seconds = strtod_l( s, NULL, locale );
+               else
+#endif
+                       seconds = strtod( s, NULL );
+       }
+       free( copy );
+
+       return fps * ( (hours * 3600) + (minutes * 60) + seconds ) + 0.5;
+}
+
+/** Parse a SMPTE timecode string.
+ *
+ * \private \memberof mlt_property_s
+ * \param s the string to parse
+ * \param fps frames per second
+ * \return position in frames
+ */
+
+static int time_code_to_frames( const char *s, double fps )
+{
+       char *pos, *copy = strdup( s );
+       int hours = 0, minutes = 0, seconds = 0, frames;
+
+       s = copy;
+       pos = strrchr( s, ';' );
+       if ( !pos )
+               pos = strrchr( s, ':' );
+       if ( pos ) {
+               frames = atoi( pos + 1 );
+               *pos = 0;
+               pos = strrchr( s, ':' );
+               if ( pos ) {
+                       seconds = atoi( pos + 1 );
+                       *pos = 0;
+                       pos = strrchr( s, ':' );
+                       if ( pos ) {
+                               minutes = atoi( pos + 1 );
+                               *pos = 0;
+                               hours = atoi( s );
+                       }
+                       else {
+                               minutes = atoi( s );
+                       }
+               }
+               else {
+                       seconds = atoi( s );
+               }
+       }
+       else {
+               frames = atoi( s );
+       }
+       free( copy );
+
+       return frames + ( fps * ( (hours * 3600) + (minutes * 60) + seconds ) + 0.5 );
+}
+
+/** Convert a 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.
@@ -277,14 +372,17 @@ int mlt_property_set_data( mlt_property self, void *value, int length, mlt_destr
  * right to obtain RGB without alpha in order to make it do a logical instead
  * of arithmetic shift.
  *
+ * If the string contains a colon it is interpreted as a time value. If it also
+ * contains a period or comma character, the string is parsed as a clock value:
+ * HH:MM:SS. Otherwise, the time value is parsed as a SMPTE timecode: HH:MM:SS:FF.
  * \private \memberof mlt_property_s
  * \param value a string to convert
+ * \param fps frames per second, used when converting from time value
+ * \param locale the locale to use when converting from time clock value
  * \return the resultant integer
  */
-static inline int mlt_property_atoi( const char *value )
+static int mlt_property_atoi( const char *value, double fps, locale_t locale )
 {
-       if ( value == NULL )
-               return 0;
        // Parse a hex color value as #RRGGBB or #AARRGGBB.
        if ( value[0] == '#' )
        {
@@ -298,6 +396,13 @@ static inline int mlt_property_atoi( const char *value )
        {
                return strtoul( value + 2, NULL, 16 );
        }
+       else if ( fps > 0 && strchr( value, ':' ) )
+       {
+               if ( strchr( value, '.' ) || strchr( value, ',' ) )
+                       return time_clock_to_frames( value, fps, locale );
+               else
+                       return time_code_to_frames( value, fps );
+       }
        else
        {
                return strtol( value, NULL, 10 );
@@ -308,10 +413,12 @@ static inline int mlt_property_atoi( const char *value )
  *
  * \public \memberof mlt_property_s
  * \param self a property
+ * \param fps frames per second, used when converting from time value
+ * \param locale the locale to use when converting from time clock value
  * \return an integer value
  */
 
-int mlt_property_get_int( mlt_property self )
+int mlt_property_get_int( mlt_property self, double fps, locale_t locale )
 {
        if ( self->types & mlt_prop_int )
                return self->prop_int;
@@ -322,41 +429,50 @@ int mlt_property_get_int( mlt_property self )
        else if ( self->types & mlt_prop_int64 )
                return ( int )self->prop_int64;
        else if ( ( self->types & mlt_prop_string ) && self->prop_string )
-               return mlt_property_atoi( self->prop_string );
+               return mlt_property_atoi( self->prop_string, fps, locale );
        return 0;
 }
 
-/** Get the property as a floating point.
+/** Convert a string to a floating point number.
  *
- * \public \memberof mlt_property_s
- * \param self a property
- * \return a floating point value
+ * If the string contains a colon it is interpreted as a time value. If it also
+ * contains a period or comma character, the string is parsed as a clock value:
+ * HH:MM:SS. Otherwise, the time value is parsed as a SMPTE timecode: HH:MM:SS:FF.
+ * \private \memberof mlt_property_s
+ * \param value the string to convert
+ * \param fps frames per second, used when converting from time value
+ * \param locale the locale to use when converting from time clock value
+ * \return the resultant real number
  */
-
-double mlt_property_get_double( mlt_property self )
+static double mlt_property_atof( const char *value, double fps, locale_t locale )
 {
-       if ( self->types & mlt_prop_double )
-               return self->prop_double;
-       else if ( self->types & mlt_prop_int )
-               return ( double )self->prop_int;
-       else if ( self->types & mlt_prop_position )
-               return ( double )self->prop_position;
-       else if ( self->types & mlt_prop_int64 )
-               return ( double )self->prop_int64;
-       else if ( ( self->types & mlt_prop_string ) && self->prop_string )
-               return atof( self->prop_string );
-       return 0;
+       if ( fps > 0 && strchr( value, ':' ) )
+       {
+               if ( strchr( value, '.' ) || strchr( value, ',' ) )
+                       return time_clock_to_frames( value, fps, locale );
+               else
+                       return time_code_to_frames( value, fps );
+       }
+       else
+       {
+#if defined(__GLIBC__) || defined(__DARWIN__)
+               if ( locale )
+                       return strtod_l( value, NULL, locale );
+#endif
+               return strtod( value, NULL );
+       }
 }
 
-/** Get the property (with locale) as a floating point.
+/** Get the property as a floating point.
  *
  * \public \memberof mlt_property_s
  * \param self a property
+ * \param fps frames per second, used when converting from time value
  * \param locale the locale to use for this conversion
  * \return a floating point value
  */
 
-double mlt_property_get_double_l( mlt_property self, locale_t locale )
+double mlt_property_get_double( mlt_property self, double fps, locale_t locale )
 {
        if ( self->types & mlt_prop_double )
                return self->prop_double;
@@ -366,12 +482,8 @@ double mlt_property_get_double_l( mlt_property self, locale_t locale )
                return ( double )self->prop_position;
        else if ( self->types & mlt_prop_int64 )
                return ( double )self->prop_int64;
-#if defined(__GLIBC__) || defined(__DARWIN__)
-       else if ( locale && ( self->types & mlt_prop_string ) && self->prop_string )
-               return strtod_l( self->prop_string, NULL, locale );
-#endif
        else if ( ( self->types & mlt_prop_string ) && self->prop_string )
-               return strtod( self->prop_string, NULL );
+               return mlt_property_atof( self->prop_string, fps, locale );
        return 0;
 }
 
@@ -380,10 +492,12 @@ double mlt_property_get_double_l( mlt_property self, locale_t locale )
  * A position is an offset time in terms of frame units.
  * \public \memberof mlt_property_s
  * \param self a property
+ * \param fps frames per second, used when converting from time value
+ * \param locale the locale to use when converting from time clock value
  * \return the position in frames
  */
 
-mlt_position mlt_property_get_position( mlt_property self )
+mlt_position mlt_property_get_position( mlt_property self, double fps, locale_t locale )
 {
        if ( self->types & mlt_prop_position )
                return self->prop_position;
@@ -394,7 +508,7 @@ mlt_position mlt_property_get_position( mlt_property self )
        else if ( self->types & mlt_prop_int64 )
                return ( mlt_position )self->prop_int64;
        else if ( ( self->types & mlt_prop_string ) && self->prop_string )
-               return ( mlt_position )atol( self->prop_string );
+               return ( mlt_position )mlt_property_atoi( self->prop_string, fps, locale );
        return 0;
 }
 
@@ -643,3 +757,170 @@ void mlt_property_pass( mlt_property self, mlt_property that )
        }
        pthread_mutex_unlock( &self->mutex );
 }
+
+/** Convert frame count to a SMPTE timecode string.
+ *
+ * \private \memberof mlt_property_s
+ * \param frames a frame count
+ * \param fps frames per second
+ * \param[out] s the string to write into - must have enough space to hold largest time string
+ */
+
+static void time_smpte_from_frames( int frames, double fps, char *s )
+{
+       int hours, mins, secs;
+       char frame_sep = ':';
+
+       if ( fps == 30000.0/1001.0 )
+       {
+               fps = 30.0;
+               int i, max_frames = frames;
+               for ( i = 1800; i <= max_frames; i += 1800 )
+               {
+                       if ( i % 18000 )
+                       {
+                               max_frames += 2;
+                               frames += 2;
+                       }
+               }
+               frame_sep = ';';
+       }
+       hours = frames / ( fps * 3600 );
+       frames -= hours * ( fps * 3600 );
+       mins = frames / ( fps * 60 );
+       frames -= mins * ( fps * 60 );
+       secs = frames / fps;
+       frames -= secs * fps;
+
+       sprintf( s, "%02d:%02d:%02d%c%02d", hours, mins, secs, frame_sep, frames );
+}
+
+/** Convert frame count to a SMIL clock value string.
+ *
+ * \private \memberof mlt_property_s
+ * \param frames a frame count
+ * \param fps frames per second
+ * \param[out] s the string to write into - must have enough space to hold largest time string
+ */
+
+static void time_clock_from_frames( int frames, double fps, char *s )
+{
+       int hours, mins;
+       double secs;
+
+       hours = frames / ( fps * 3600 );
+       frames -= hours * ( fps * 3600 );
+       mins = frames / ( fps * 60 );
+       frames -= mins * ( fps * 60 );
+       secs = (double) frames / fps;
+
+       sprintf( s, "%02d:%02d:%06.3f", hours, mins, secs );
+}
+
+/** Get the property as a time string.
+ *
+ * The time value can be either a SMPTE timecode or SMIL clock value.
+ * The caller is not responsible for deallocating the returned string!
+ * The string is deallocated when the property is closed.
+ * \public \memberof mlt_property_s
+ * \param self a property
+ * \param format the time format that you want
+ * \param fps frames per second
+ * \param locale the locale to use for this conversion
+ * \return a string representation of the property or NULL if failed
+ */
+
+char *mlt_property_get_time( mlt_property self, mlt_time_format format, double fps, locale_t locale )
+{
+       char *orig_localename = NULL;
+       const char *localename = "";
+
+       // Optimization for mlt_time_frames
+       if ( format == mlt_time_frames )
+               return mlt_property_get_string_l( self, locale );
+
+       // Remove existing string
+       if ( self->prop_string )
+               mlt_property_set_int( self, mlt_property_get_int( self, fps, locale ) );
+
+       // Use the specified locale
+       if ( locale )
+       {
+               // TODO: when glibc gets sprintf_l, start using it! For now, hack on setlocale.
+               // Save the current locale
+#if defined(__DARWIN__)
+               localename = querylocale( LC_NUMERIC, locale );
+#elif defined(__GLIBC__)
+               localename = locale->__names[ LC_NUMERIC ];
+#else
+               // TODO: not yet sure what to do on other platforms
+#endif
+               // Protect damaging the global locale from a temporary locale on another thread.
+               pthread_mutex_lock( &self->mutex );
+
+               // Get the current locale
+               orig_localename = strdup( setlocale( LC_NUMERIC, NULL ) );
+
+               // Set the new locale
+               setlocale( LC_NUMERIC, localename );
+       }
+       else
+       {
+               // Make sure we have a lock before accessing self->types
+               pthread_mutex_lock( &self->mutex );
+       }
+
+       // Convert number to string
+       if ( self->types & mlt_prop_int )
+       {
+               self->types |= mlt_prop_string;
+               self->prop_string = malloc( 32 );
+               if ( format == mlt_time_clock )
+                       time_clock_from_frames( self->prop_int, fps, self->prop_string );
+               else
+                       time_smpte_from_frames( self->prop_int, fps, self->prop_string );
+       }
+       else if ( self->types & mlt_prop_position )
+       {
+               self->types |= mlt_prop_string;
+               self->prop_string = malloc( 32 );
+               if ( format == mlt_time_clock )
+                       time_clock_from_frames( (int) self->prop_position, fps, self->prop_string );
+               else
+                       time_smpte_from_frames( (int) self->prop_position, fps, self->prop_string );
+       }
+       else if ( self->types & mlt_prop_double )
+       {
+               self->types |= mlt_prop_string;
+               self->prop_string = malloc( 32 );
+               if ( format == mlt_time_clock )
+                       time_clock_from_frames( self->prop_double, fps, self->prop_string );
+               else
+                       time_smpte_from_frames( self->prop_double, fps, self->prop_string );
+       }
+       else if ( self->types & mlt_prop_int64 )
+       {
+               self->types |= mlt_prop_string;
+               self->prop_string = malloc( 32 );
+               if ( format == mlt_time_clock )
+                       time_clock_from_frames( (int) self->prop_int64, fps, self->prop_string );
+               else
+                       time_smpte_from_frames( (int) self->prop_int64, fps, self->prop_string );
+       }
+
+       // Restore the current locale
+       if ( locale )
+       {
+               setlocale( LC_NUMERIC, orig_localename );
+               free( orig_localename );
+               pthread_mutex_unlock( &self->mutex );
+       }
+       else
+       {
+               // Make sure we have a lock before accessing self->types
+               pthread_mutex_unlock( &self->mutex );
+       }
+
+       // Return the string (may be NULL)
+       return self->prop_string;
+}
index c50302f779d262cb84366f5bb807edb53094cb8a..3322434e21130e13d9f84f24f6fa3fb73c474933 100644 (file)
 
 #include "mlt_types.h"
 
-#ifdef HAVE_SYS_PARAM_H
+#if defined(__FreeBSD__)
+/* This header has existed since 1994 and defines __FreeBSD_version below. */
 #include <sys/param.h>
 #endif
 
-#if defined(__GLIBC__) || defined(__DARWIN__) || (__FreeBSD_version >= 1000002)
+#if defined(__GLIBC__) || defined(__DARWIN__) || (__FreeBSD_version >= 900506)
 #include <xlocale.h>
 #else
 typedef void* locale_t;
@@ -43,16 +44,15 @@ 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 double mlt_property_get_double_l( mlt_property self, locale_t );
-extern mlt_position mlt_property_get_position( mlt_property self );
+extern int mlt_property_get_int( mlt_property self, double fps, locale_t );
+extern double mlt_property_get_double( mlt_property self, double fps, locale_t );
+extern mlt_position mlt_property_get_position( mlt_property self, double fps, locale_t );
 extern int64_t mlt_property_get_int64( mlt_property self );
 extern char *mlt_property_get_string( mlt_property self );
 extern char *mlt_property_get_string_l( mlt_property self, locale_t );
 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 self, mlt_property that );
+extern char *mlt_property_get_time( mlt_property self, mlt_time_format, double fps, locale_t );
 
 #endif
index acda89cc6272e4e007f75f44c5c9a590951e1ef8..e5e5e79388458f3d31fd46f22edafb8d9fcf51a6 100644 (file)
@@ -70,7 +70,7 @@ mlt_repository mlt_repository_init( const char *directory )
                return NULL;
 
        // Construct the repository
-       mlt_repository self = calloc( sizeof( struct mlt_repository_s ), 1 );
+       mlt_repository self = calloc( 1, sizeof( struct mlt_repository_s ));
        mlt_properties_init( &self->parent, self );
        self->consumers = mlt_properties_new();
        self->filters = mlt_properties_new();
index dfaad57294ffbaccce771a0b2e119686ca8aefd4..8a02da3af2cc0bafc607fcc294b6227d8bc36710 100644 (file)
@@ -87,7 +87,7 @@ int mlt_service_init( mlt_service self, void *child )
        self->child = child;
 
        // Generate local space
-       self->local = calloc( sizeof( mlt_service_base ), 1 );
+       self->local = calloc( 1, sizeof( mlt_service_base ) );
 
        // Associate the methods
        self->get_frame = service_get_frame;
@@ -265,7 +265,7 @@ int mlt_service_connect_producer( mlt_service self, mlt_service producer, int in
 
 /** Disconnect a service from its consumer.
  *
- * \public \memberof mlt_service_s
+ * \private \memberof mlt_service_s
  * \param self a service
  */
 
@@ -521,6 +521,19 @@ static void mlt_service_filter_changed( mlt_service owner, mlt_service self )
        mlt_events_fire( MLT_SERVICE_PROPERTIES( self ), "service-changed", NULL );
 }
 
+/** The property-changed event handler.
+ *
+ * \private \memberof mlt_service_s
+ * \param owner ignored
+ * \param self the service on which the "property-changed" event is fired
+ * \param name the name of the property that changed
+ */
+
+static void mlt_service_filter_property_changed( mlt_service owner, mlt_service self, char *name )
+{
+    mlt_events_fire( MLT_SERVICE_PROPERTIES( self ), "property-changed", name, NULL );
+}
+
 /** Attach a filter.
  *
  * \public \memberof mlt_service_s
@@ -559,7 +572,7 @@ int mlt_service_attach( mlt_service self, mlt_filter filter )
                                mlt_events_fire( properties, "service-changed", NULL );
                                mlt_events_fire( props, "service-changed", NULL );
                                mlt_events_listen( props, self, "service-changed", ( mlt_listener )mlt_service_filter_changed );
-                               mlt_events_listen( props, self, "property-changed", ( mlt_listener )mlt_service_filter_changed );
+                               mlt_events_listen( props, self, "property-changed", ( mlt_listener )mlt_service_filter_property_changed );
                        }
                        else
                        {
@@ -605,7 +618,25 @@ int mlt_service_detach( mlt_service self, mlt_filter filter )
        return error;
 }
 
-/** Retrieve a filter.
+/** Get the number of filters attached.
+ *
+ * \public \memberof mlt_service_s
+ * \param self a service
+ * \return the number of attached filters or -1 if there was an error
+ */
+
+int mlt_service_filter_count( mlt_service self )
+{
+       int result = -1;
+       if ( self )
+       {
+               mlt_service_base *base = self->local;
+               result = base->filter_count;
+       }
+       return result;
+}
+
+/** Retrieve an attached filter.
  *
  * \public \memberof mlt_service_s
  * \param self a service
@@ -637,6 +668,18 @@ mlt_profile mlt_service_profile( mlt_service self )
        return self? mlt_properties_get_data( MLT_SERVICE_PROPERTIES( self ), "_profile", NULL ) : NULL;
 }
 
+/** Set the profile for a service.
+ *
+ * \public \memberof mlt_service_s
+ * \param self a service
+ * \param profile the profile to set onto the service
+ */
+
+void mlt_service_set_profile( mlt_service self, mlt_profile profile )
+{
+    mlt_properties_set_data( MLT_SERVICE_PROPERTIES( self ), "_profile", profile, 0, NULL, NULL );
+}
+
 /** Destroy a service.
  *
  * \public \memberof mlt_service_s
index 0ba168608be699799cc58d7852571cb6270f96cc..1d28ac99ae8cee27f2ba0ed9ecd4c6fd53202e07 100644 (file)
@@ -39,7 +39,7 @@
  * 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 service-changed a filter was attached or detached or a transition was connected or disconnected
  * \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
@@ -92,8 +92,10 @@ 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 int mlt_service_filter_count( mlt_service self );
 extern mlt_filter mlt_service_filter( mlt_service self, int index );
 extern mlt_profile mlt_service_profile( mlt_service self );
+extern void mlt_service_set_profile( mlt_service self, mlt_profile profile );
 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 );
index 17b0a47d1fa6a16c9491c467f95e0180d4e1478a..b39b194937b18b0a63f31d7d95e9625da5fc2c2c 100644 (file)
@@ -49,7 +49,7 @@ static void mlt_tractor_listener( mlt_multitrack tracks, mlt_tractor self );
 
 mlt_tractor mlt_tractor_init( )
 {
-       mlt_tractor self = calloc( sizeof( struct mlt_tractor_s ), 1 );
+       mlt_tractor self = calloc( 1, sizeof( struct mlt_tractor_s ) );
        if ( self != NULL )
        {
                mlt_producer producer = &self->parent;
@@ -88,7 +88,7 @@ mlt_tractor mlt_tractor_init( )
 
 mlt_tractor mlt_tractor_new( )
 {
-       mlt_tractor self = calloc( sizeof( struct mlt_tractor_s ), 1 );
+       mlt_tractor self = calloc( 1, sizeof( struct mlt_tractor_s ) );
        if ( self != NULL )
        {
                mlt_producer producer = &self->parent;
@@ -267,11 +267,8 @@ static int producer_get_image( mlt_frame self, uint8_t **buffer, mlt_image_forma
        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_properties_set_int( frame_properties, "consumer_tff", mlt_properties_get_int( properties, "consumer_tff" ) );
        mlt_frame_get_image( frame, buffer, format, width, height, writable );
        mlt_frame_set_image( self, *buffer, 0, NULL );
@@ -351,15 +348,15 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra
                // 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 )
                {
+                       // 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( );
+
                        // Used to garbage collect all frames
                        char label[ 30 ];
 
@@ -481,10 +478,6 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra
                                        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;
                                }
@@ -507,8 +500,7 @@ static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int tra
                                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_pass_list( frame_properties, video_properties, "meta.media.width, meta.media.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 );
index 7657d6ec743fd1d736cc1be7abc5b052cd56795a..90eb774ef2389c584f27c624b8dc2e84e3865040 100644 (file)
@@ -311,6 +311,7 @@ mlt_frame mlt_transition_process( mlt_transition self, mlt_frame a_frame, mlt_fr
 
 static int get_image_a( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
+       mlt_transition self = mlt_frame_pop_service( a_frame );
        mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
 
        // All transitions get scaling
@@ -319,14 +320,15 @@ static int get_image_a( mlt_frame a_frame, uint8_t **image, mlt_image_format *fo
                mlt_properties_set( a_props, "rescale.interp", "nearest" );
 
        // Ensure sane aspect ratio
-       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_frame_get_aspect_ratio( a_frame ) == 0.0 )
+               mlt_frame_set_aspect_ratio( a_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) );
 
        return mlt_frame_get_image( a_frame, image, format, width, height, writable );
 }
 
 static int get_image_b( mlt_frame b_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
+       mlt_transition self = mlt_frame_pop_service( b_frame );
        mlt_frame a_frame = mlt_frame_pop_frame( b_frame );
        mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
        mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
@@ -341,11 +343,11 @@ static int get_image_b( mlt_frame b_frame, uint8_t **image, mlt_image_format *fo
        }
 
        // Ensure sane 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" ) );
+       if ( mlt_frame_get_aspect_ratio( b_frame ) == 0.0 )
+               mlt_frame_set_aspect_ratio( b_frame, mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) ) );
 
        mlt_properties_pass_list( b_props, a_props,
-               "consumer_deinterlace, deinterlace_method, consumer_aspect_ratio, consumer_tff" );
+               "consumer_deinterlace, deinterlace_method, consumer_tff" );
 
        return mlt_frame_get_image( b_frame, image, format, width, height, writable );
 }
@@ -478,8 +480,10 @@ static int transition_get_frame( mlt_service service, mlt_frame_ptr frame, int i
                        if ( !( a_hide & type ) && !( b_hide & type ) )
                        {
                                // Add hooks for pre-processing frames
+                               mlt_frame_push_service( a_frame_ptr, self );
                                mlt_frame_push_get_image( a_frame_ptr, get_image_a );
                                mlt_frame_push_frame( b_frame_ptr, a_frame_ptr );
+                               mlt_frame_push_service( b_frame_ptr, self );
                                mlt_frame_push_get_image( b_frame_ptr, get_image_b );
 
                                // Process the transition
index f30e94db8f3da75bfd392fc4108ccfd36a2b7c26..c1574d4471481d80ceca65fcb4223167d4886cf5 100644 (file)
@@ -2,7 +2,7 @@
  * \file mlt_types.h
  * \brief Provides forward definitions of all public types
  *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * \author Charles Yates <charles.yates@pandora.be>
  *
  * This library is free software; you can redistribute it and/or
@@ -44,7 +44,9 @@ typedef enum
        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_opengl,  /**< (deprecated) suitable for OpenGL texture */
+       mlt_image_glsl,    /**< for opengl module internal use only */
+       mlt_image_glsl_texture /**< an OpenGL texture name */
 }
 mlt_image_format;
 
@@ -57,11 +59,22 @@ typedef enum
        mlt_audio_s16 = 1, /**< signed 16-bit interleaved PCM */
        mlt_audio_s32,     /**< signed 32-bit non-interleaved PCM */
        mlt_audio_float,   /**< 32-bit non-interleaved floating point */
-       mlt_audio_s32le,   /**< signed 32-bit interleaved PCM, may only used by producers */
-       mlt_audio_f32le    /**< 32-bit interleaved floating point, may only be used by producers */
+       mlt_audio_s32le,   /**< signed 32-bit interleaved PCM */
+       mlt_audio_f32le,   /**< 32-bit interleaved floating point */
+       mlt_audio_u8       /**< unsigned 8-bit interleaved PCM */
 }
 mlt_audio_format;
 
+/** The time string formats */
+
+typedef enum
+{
+       mlt_time_frames = 0, /**< frame count */
+       mlt_time_clock,      /**< SMIL clock-value as [[hh:]mm:]ss[.fraction] */
+       mlt_time_smpte       /**< SMPTE timecode as [[[hh:]mm:]ss:]frames */
+}
+mlt_time_format;
+
 /** The relative time qualifiers */
 
 typedef enum
index a4571792878d4799d4801e7b4ce3eafea5445aea..2b7e4d0fadb093ed65a219db23493f7da15095ab 100644 (file)
@@ -2,7 +2,7 @@
  * \file mlt_version.h
  * \brief contains version information
  *
- * Copyright (C) 2010 Ushodaya Enterprises Limited
+ * Copyright (C) 2010-2013 Ushodaya Enterprises Limited
  * \author Jonathan Thomas <Jonathan.Oomph@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -28,8 +28,8 @@
 #define STRINGIZE(s)            STRINGIZE2(s)
 
 #define LIBMLT_VERSION_MAJOR    0
-#define LIBMLT_VERSION_MINOR    7
-#define LIBMLT_VERSION_REVISION 7
+#define LIBMLT_VERSION_MINOR    8
+#define LIBMLT_VERSION_REVISION 8
 #define LIBMLT_VERSION_INT      ((LIBMLT_VERSION_MAJOR<<16)+(LIBMLT_VERSION_MINOR<<8)+LIBMLT_VERSION_REVISION)
 #define LIBMLT_VERSION          STRINGIZE(LIBMLT_VERSION_MAJOR.LIBMLT_VERSION_MINOR.LIBMLT_VERSION_REVISION)
 
index 6d501d96793a2dc8bc5f7cd149ebfbf1054148f4..acac736e3d174d4301f8a4b35de849c1bd285db4 100644 (file)
@@ -1,5 +1,4 @@
 include ../../config.mak
-include config.mak
 
 OBJS = melt.o \
           io.o
@@ -11,14 +10,16 @@ LDFLAGS += -L../framework -lmlt -lpthread
 SRCS := $(OBJS:.o=.c)
 
 ifeq ($(targetos), MinGW)
+ifeq (, $(findstring MELT_NOSDL, $(CFLAGS)))
 CFLAGS += `sdl-config --cflags`
 LDFLAGS += `sdl-config --libs`
+endif
 bindir = $(prefix)
 endif
 
-all: $(TARGET)
+all: $(meltname)
 
-$(TARGET): $(OBJS)
+$(meltname): $(OBJS)
                $(CC) -o $@ $(OBJS) $(LDFLAGS)
 
 depend:        $(SRCS)
@@ -28,14 +29,24 @@ distclean:  clean
                rm -f .depend
 
 clean: 
-               rm -f $(OBJS) $(TARGET)
+               rm -f $(OBJS) $(meltname)
 
 install:       all
        install -d "$(DESTDIR)$(bindir)"
-       install -c -m 755 $(TARGET) "$(DESTDIR)$(bindir)"
+       install -c -m 755 $(meltname) "$(DESTDIR)$(bindir)"
+ifeq ($(extra_versioning), true)
+ifeq ($(melt_noversion), false)
+       ln -s $(meltname) "$(DESTDIR)$(bindir)/melt"
+endif
+endif
 
 uninstall:
-       rm -f "$(DESTDIR)$(bindir)/$(TARGET)"
+       rm -f "$(DESTDIR)$(bindir)/$(meltname)"
+ifeq ($(extra_versioning), true)
+ifeq ($(melt_noversion), false)
+       rm -f "$(DESTDIR)$(bindir)/melt"
+endif
+endif
 
 ifneq ($(wildcard .depend),)
 include .depend
diff --git a/src/melt/configure b/src/melt/configure
deleted file mode 100755 (executable)
index c109c84..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-if [ "$help" = "1" ]
-then
-       cat << EOF
-Melt options:
-
-  --rename-melt=name      - Give melt executable a different name.
-
-EOF
-
-else
-       target=melt
-       for i in "$@"
-       do
-               case $i in
-                       --rename-melt=* ) target="${i#--rename-melt=}" ;;
-               esac
-       done
-       echo "TARGET=$target" > config.mak
-fi
index 2c5a5b334411113b2f6684100c6b4368a99a3931..483952a901254a94176bb958ca6ec2bafdac30da 100644 (file)
@@ -169,7 +169,7 @@ int term_read( )
         return n;
     }
 #else
-       struct timespec tm = { 0, 40000 };
+       struct timespec tm = { 0, 40000000 };
        nanosleep( &tm, NULL );
 #endif
     return -1;
index 8b221cadbdd0cffe4d71fb1720694a10be0e3cb7..a5cf16537b895e3a000dd03e1eb844f0259e74db 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * melt.c -- MLT command line utility
- * Copyright (C) 2002-2011 Ushodaya Enterprises Limited
+ * Copyright (C) 2002-2013 Ushodaya Enterprises Limited
  * Authors: Charles Yates <charles.yates@pandora.be>
  *          Dan Dennedy <dan@dennedy.org>
  *
 #include <libgen.h>
 #include <limits.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <framework/mlt.h>
 
-#if defined(__DARWIN__) || defined(WIN32)
+#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL)
 #include <SDL.h>
 #endif
 
 #include "io.h"
 
+static mlt_producer melt = NULL;
+
+static void stop_handler(int signum)
+{
+       if ( melt )
+       {
+               mlt_properties properties = MLT_PRODUCER_PROPERTIES( melt );
+               mlt_properties_set_int( properties, "done", 1 );
+       }
+}
+
+static void abnormal_exit_handler(int signum)
+{
+       // The process is going down hard. Restore the terminal first.
+       term_exit();
+       // Reset the default handler so the core gets dumped.
+       signal( signum, SIG_DFL );
+       raise( signum );
+}
+
 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 jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL );
-       mlt_position position = mlt_producer_position( producer );
+       mlt_position position = producer? mlt_producer_position( producer ) : 0;
 
        mlt_properties_set_int( properties, "stats_off", 1 );
 
@@ -263,11 +284,21 @@ static void load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc
 {
        int i;
        int multi = 0;
+       int qglsl = 0;
+
+       for ( i = 1; i < argc; i ++ ) {
+               // See if we need multi consumer.
+               multi += !strcmp( argv[i], "-consumer" );
+               // Seee if we need the qglsl variant of multi consumer.
+               if ( !strncmp( argv[i], "glsl.", 5 ) || !strncmp( argv[i], "movit.", 6 ) )
+                       qglsl = 1;
+       }
+       // Disable qglsl if xgl is being used!
+       for ( i = 1; qglsl && i < argc; i ++ )
+               if ( !strcmp( argv[i], "xgl" ) )
+                       qglsl = 0;
 
-       for ( i = 1; i < argc; i ++ )
-               multi += !strcmp( argv[ i ], "-consumer" );
-
-       if ( multi > 1 )
+       if ( multi > 1 || qglsl )
        {
                // If there is more than one -consumer use the 'multi' consumer.
                int k = 0;
@@ -275,7 +306,7 @@ static void load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc
 
                if ( *consumer )
                        mlt_consumer_close( *consumer );
-               *consumer = create_consumer( profile, "multi" );
+               *consumer = create_consumer( profile, ( qglsl? "qglsl" : "multi" ) );
                mlt_properties properties = MLT_CONSUMER_PROPERTIES( *consumer );
                for ( i = 1; i < argc; i ++ )
                {
@@ -321,7 +352,7 @@ static void load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc
        }
 }
 
-#if defined(__DARWIN__) || defined(WIN32)
+#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL)
 
 static void event_handling( mlt_producer producer, mlt_consumer consumer )
 {
@@ -353,7 +384,7 @@ 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 };
+       struct timespec tm = { 0, 40000000 };
        int total_length = mlt_producer_get_length( producer );
        int last_position = 0;
 
@@ -385,7 +416,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer )
                                transport_action( producer, string );
                        }
 
-#if defined(__DARWIN__) || defined(WIN32)
+#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL)
                        event_handling( producer, consumer );
 #endif
 
@@ -406,6 +437,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer )
                                {
                                        fprintf( stderr, "Current Position: %10d\r", (int)mlt_consumer_position( consumer ) );
                                }
+                               fflush( stderr );
                        }
 
                        if ( silent || progress )
@@ -661,7 +693,6 @@ int main( int argc, char **argv )
 {
        int i;
        mlt_consumer consumer = NULL;
-       mlt_producer melt = NULL;
        FILE *store = NULL;
        char *name = NULL;
        mlt_profile profile = NULL;
@@ -669,10 +700,15 @@ int main( int argc, char **argv )
        int is_silent = 0;
        mlt_profile backup_profile;
 
+       // Handle abnormal exit situations.
+       signal( SIGSEGV, abnormal_exit_handler );
+       signal( SIGILL, abnormal_exit_handler );
+       signal( SIGABRT, abnormal_exit_handler );
+
        // Construct the factory
        mlt_repository repo = mlt_factory_init( NULL );
 
-#ifdef WIN32
+#if defined(WIN32) && !defined(MELT_NOSDL)
        is_silent = 1;
 #endif
        
@@ -769,8 +805,8 @@ query_all:
                }
                else if ( !strcmp( argv[ i ], "-version" ) || !strcmp( argv[ i ], "--version" ) )
                {
-                       fprintf( stdout, "MLT %s " VERSION "\n"
-                               "Copyright (C) 2002-2011 Ushodaya Enterprises Limited\n"
+                       fprintf( stdout, "%s " VERSION "\n"
+                               "Copyright (C) 2002-2013 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",
@@ -782,7 +818,7 @@ query_all:
                        mlt_log_set_level( MLT_LOG_DEBUG );
                }
        }
-       if ( !is_silent && !isatty( STDIN_FILENO ) )
+       if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress )
                is_progress = 1;
 
        // Create profile if not set explicitly
@@ -906,6 +942,14 @@ query_all:
                        mlt_events_listen( properties, consumer, "consumer-fatal-error", ( mlt_listener )on_fatal_error );
                        if ( mlt_consumer_start( consumer ) == 0 )
                        {
+                               // Try to exit gracefully upon these signals
+                               signal( SIGINT, stop_handler );
+                               signal( SIGTERM, stop_handler );
+#ifndef WIN32
+                               signal( SIGHUP, stop_handler );
+                               signal( SIGPIPE, stop_handler );
+#endif
+
                                // Transport functionality
                                transport( melt, consumer );
                                
@@ -926,7 +970,10 @@ query_all:
 
        // Disconnect producer from consumer to prevent ref cycles from closing services
        if ( consumer )
+       {
                mlt_consumer_connect( consumer, NULL );
+               mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-cleanup", NULL);
+       }
 
        // Close the producer
        if ( melt != NULL )
index 3f8c4196833a85c77f0020ba3b179bee3169fc1a..f4746e255478d13e4118c25ef99e99968fff69ac 100644 (file)
@@ -19,9 +19,12 @@ SONAME = $(NAME).$(soversion)
 LIBFLAGS += -Wl,-soname,$(SONAME)
 endif
 
-CXXFLAGS += -I.. $(RDYNAMIC) -DVERSION=\"$(version)\"
+CXXFLAGS += -I.. $(RDYNAMIC) -DVERSION=\"$(version)\" -fvisibility=hidden
 
 LDFLAGS += -L../framework -lmlt
+ifeq ($(targetos), Linux)
+LDFLAGS += -Wl,--version-script=mlt++.vers
+endif
 
 OBJS = MltConsumer.o \
           MltDeque.o \
index 694974eb38e4221e6dd334e70549151de7d8d74b..a50be2b31253a5188ea25e37f2790774774d1a4c 100644 (file)
@@ -66,3 +66,8 @@ void *Deque::peek_front( )
        return mlt_deque_peek_front( deque );
 }
 
+void *Deque::peek( int index )
+{
+       return mlt_deque_peek( deque, index );
+}
+
index ce6b0365a97f004ca4a99519232ca00c3cd9b154..5a1c1eb3f11f4a6711907190a875d47499873add 100644 (file)
@@ -41,6 +41,7 @@ namespace Mlt
                        void *pop_front( );
                        void *peek_back( );
                        void *peek_front( );
+                       void *peek( int index );
        };
 }
 
index 6196c1e3e250dc47d70ee48cd0269dd0d161059a..4c8c961a42e2db2e6a90275e867100ffe3cb24b3 100644 (file)
@@ -21,7 +21,7 @@
 #include "MltFilteredConsumer.h"
 using namespace Mlt;
 
-FilteredConsumer::FilteredConsumer( Profile& profile, char *id, char *arg ) :
+FilteredConsumer::FilteredConsumer( Profile& profile, const char *id, const char *arg ) :
        Consumer( profile, id, arg )
 {
        // Create a reference to the first service
index c66a5e5f3a8ec0ddcafc02a82ed8f2b157192572..b90f1e581e79b5380febd26115284f16c9ce3b0e 100644 (file)
@@ -39,7 +39,7 @@ namespace Mlt
                private:
                        Service *first;
                public:
-                       FilteredConsumer( Profile& profile, char *id, char *arg = NULL );
+                       FilteredConsumer( Profile& profile, const char *id, const char *arg = NULL );
                        FilteredConsumer( Consumer &consumer );
                        virtual ~FilteredConsumer( );
                        int connect( Service &service );
index ea665450f6f6b248beb8d7f5e995ffd8ecc6e919..87d1025b3d3144224f6ed654038b1a75b7a66bf6 100644 (file)
  */
 
 #include "MltFilteredProducer.h"
+#include "MltProfile.h"
 using namespace Mlt;
 
-FilteredProducer::FilteredProducer( Profile& profile, char *id, char *arg ) :
+FilteredProducer::FilteredProducer( Profile& profile, const char *id, const char *arg ) :
        Producer( profile, id, arg )
 {
        // Create a reference to the last service
@@ -71,7 +72,8 @@ int FilteredProducer::detach( Filter &filter )
                        Service *consumer = it->consumer( );
                        if ( consumer->is_valid( ) )
                                consumer->connect_producer( *producer );
-                       Producer dummy( *profile(), "colour" );
+                       Profile p( get_profile() );
+                       Producer dummy( p, "colour" );
                        dummy.connect_producer( *it );
                        if ( last->get_service( ) == it->get_service( ) )
                        {
index da635ffa1cc66e00238a18c03e3b5c8d27ee6a90..0d49b001df48dfb82290a7a27a4414fca8797b2f 100644 (file)
@@ -39,7 +39,7 @@ namespace Mlt
                private:
                        Service *last;
                public:
-                       FilteredProducer( Profile& profile, char *id, char *arg = NULL );
+                       FilteredProducer( Profile& profile, const char *id, const char *arg = NULL );
                        virtual ~FilteredProducer( );
                        int attach( Filter &filter );
                        int detach( Filter &filter );
index 30c30fd21a030b006004b0a737d481b5689be9d6..2594f62ca6d6c996ba5c86e8cb0bcf2d53190cda 100644 (file)
@@ -95,6 +95,11 @@ mlt_properties Frame::get_unique_properties( Service &service )
        return mlt_frame_unique_properties( get_frame(), service.get_service() );
 }
 
+int Frame::get_position( )
+{
+       return mlt_frame_get_position( get_frame() );
+}
+
 int Frame::set_image( uint8_t *image, int size, mlt_destructor destroy )
 {
        return mlt_frame_set_image( get_frame(), image, size, destroy );
index 273d459f141d5708a632277818f6d688b2ef680c..44d4031f3f4785511e8aba6c4e182963abf0a4f4 100644 (file)
@@ -47,6 +47,7 @@ namespace Mlt
                        void *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
                        unsigned char *get_waveform( int w, int h );
                        Producer *get_original_producer( );
+                       int get_position( );
                        mlt_properties get_unique_properties( Service &service );
                        int set_image( uint8_t *image, int size, mlt_destructor destroy );
                        int set_alpha( uint8_t *alpha, int size, mlt_destructor destroy );
index a13faf35a5e0e1c3b4934139c3818f8767352ef9..557cd7d65d4bef6afe6b35b292e687fe71195f6f 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include "MltPlaylist.h"
 #include "MltTransition.h"
+#include "MltProfile.h"
 using namespace Mlt;
 
 ClipInfo::ClipInfo( ) :
@@ -85,6 +86,12 @@ Playlist::Playlist( ) :
        instance = mlt_playlist_init( );
 }
 
+Playlist::Playlist( Profile& profile ) :
+       instance( NULL )
+{
+       instance = mlt_playlist_new( profile.get_profile() );
+}
+
 Playlist::Playlist( Service &producer ) :
        instance( NULL )
 {
@@ -138,9 +145,14 @@ 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 )
+int Playlist::blank( int out )
+{
+       return mlt_playlist_blank( get_playlist( ), out );
+}
+
+int Playlist::blank( const char *length )
 {
-       return mlt_playlist_blank( get_playlist( ), length );
+       return mlt_playlist_blank_time( get_playlist( ), length );
 }
 
 int Playlist::clip( mlt_whence whence, int index )
index 1a48503286c0654919a87b4ed0589d7ef0a64fd3..7d0325562e7b48da1957ab4da9a587c13b98528c 100644 (file)
@@ -33,6 +33,7 @@ namespace Mlt
        class Service;
        class Playlist;
        class Transition;
+       class Profile;
 
        class MLTPP_DECLSPEC ClipInfo
        {
@@ -60,6 +61,7 @@ namespace Mlt
                        mlt_playlist instance;
                public:
                        Playlist( );
+                       Playlist( Profile& profile );
                        Playlist( Service &playlist );
                        Playlist( Playlist &playlist );
                        Playlist( mlt_playlist playlist );
@@ -69,7 +71,8 @@ namespace Mlt
                        int count( );
                        int clear( );
                        int append( Producer &producer, int in = -1, int out = -1 );
-                       int blank( int length );
+                       int blank( int out );
+                       int blank( const char *length );
                        int clip( mlt_whence whence, int index );
                        int current_clip( );
                        Producer *current( );
index 49ba11ae58dc0a77488491be68f81f54f6cc36b1..0e3842a1e6a431d064b5823e818df8b67a99a00c 100644 (file)
@@ -111,6 +111,11 @@ int Producer::seek( int position )
        return mlt_producer_seek( get_producer( ), position );
 }
 
+int Producer::seek( const char *time )
+{
+       return mlt_producer_seek_time( get_producer( ), time );
+}
+
 int Producer::position( )
 {
        return mlt_producer_position( get_producer( ) );
@@ -121,6 +126,11 @@ int Producer::frame( )
        return mlt_producer_frame( get_producer( ) );
 }
 
+char* Producer::frame_time( mlt_time_format format )
+{
+       return mlt_producer_frame_time( get_producer(), format );
+}
+
 int Producer::set_speed( double speed )
 {
        return mlt_producer_set_speed( get_producer( ), speed );
@@ -174,6 +184,11 @@ int Producer::get_length( )
        return mlt_producer_get_length( get_producer( ) );
 }
 
+char* Producer::get_length_time( mlt_time_format format )
+{
+       return mlt_producer_get_length_time( get_producer( ), format );
+}
+
 int Producer::get_playtime( )
 {
        return mlt_producer_get_playtime( get_producer( ) );
index dc0b03635a3c54b50b1e1b6223deaaffeb113e81..473f2f410fb8dc18594299559dc11ae33c4db690 100644 (file)
@@ -52,8 +52,10 @@ namespace Mlt
                        mlt_producer get_parent( );
                        mlt_service get_service( );
                        int seek( int position );
+                       int seek( const char* time );
                        int position( );
                        int frame( );
+                       char* frame_time( mlt_time_format = mlt_time_smpte );
                        int set_speed( double speed );
                        int pause( );
                        double get_speed( );
@@ -62,6 +64,7 @@ namespace Mlt
                        int get_in( );
                        int get_out( );
                        int get_length( );
+                       char* get_length_time( mlt_time_format = mlt_time_smpte );
                        int get_playtime( );
                        Producer *cut( int in = 0, int out = -1 );
                        bool is_cut( );
index 051a9a42785ea2ea3eaa55c47bd5e5dd2772624b..f4dce193b97169f3f7069e25278a3d5b176525b3 100644 (file)
@@ -123,6 +123,16 @@ double Profile::dar() const
        return mlt_profile_dar( instance );
 }
 
+int Profile::is_explicit() const
+{
+       return instance->is_explicit;
+}
+
+int Profile::colorspace() const
+{
+       return instance->colorspace;
+}
+
 Properties* Profile::list()
 {
        return new Properties( mlt_profile_list() );
@@ -161,8 +171,8 @@ void Profile::set_colorspace( int colorspace )
 
 void Profile::set_frame_rate( int numerator, int denominator )
 {
-       instance->sample_aspect_num = numerator;
-       instance->sample_aspect_den = denominator;
+       instance->frame_rate_num = numerator;
+       instance->frame_rate_den = denominator;
 }
 
 void Profile::set_explicit( int boolean )
index 248c83703afbe00197464b983a68d5c3361ab661..d1fc09c0116491f0d3e3c5e2008d6906368bdfd3 100644 (file)
@@ -58,6 +58,8 @@ namespace Mlt
                        int display_aspect_num() const;
                        int display_aspect_den() const;
                        double dar() const;
+                       int is_explicit() const;
+                       int colorspace() const;
                        static Properties* list();
                        void from_producer( Producer &producer );
                        void set_width( int width );
index f37f777aeedb127eaac9de689ec6782e1bad8571..c80756eb17abe013df6be19d918387dd11a4be45 100644 (file)
@@ -331,3 +331,8 @@ const char *Properties::get_lcnumeric( )
 {
        return mlt_properties_get_lcnumeric( get_properties() );
 }
+
+char *Properties::get_time( const char *name, mlt_time_format format )
+{
+       return mlt_properties_get_time( get_properties(), name, format );
+}
index 5a8718c65a36be16cd76fce1d69162611a90607c..dfbc5eecdd85c5894e00e77ed5d1767b6c02f695 100644 (file)
@@ -96,6 +96,7 @@ namespace Mlt
                        int preset( const char *name );
                        int set_lcnumeric( const char *locale );
                        const char *get_lcnumeric( );
+                       char *get_time( const char *name, mlt_time_format = mlt_time_smpte );
        };
 }
 
index 2af9fb431a06fbf6cbea329165c81ace99540948..b52c8b9a5105848ebb4ed8433bd6c18caa7655a9 100644 (file)
@@ -39,7 +39,7 @@ static void filter_destructor( void *arg )
        delete filter;
 }
 
-PushConsumer::PushConsumer( Profile& profile, char *id , char *service ) :
+PushConsumer::PushConsumer( Profile& profile, const char *id , const char *service ) :
        Consumer( profile, id, service ),
        m_private( new PushPrivate( ) )
 {
index d98ca70ca505472e48e5ec730ea8c3767df9b6e9..6fae610fcf152e6a4d8d3b5b663bcaca1de52d4b 100644 (file)
@@ -37,7 +37,7 @@ namespace Mlt
                private:
                        PushPrivate *m_private;
                public:
-                       PushConsumer( Profile& profile, char *id , char *service = NULL );
+                       PushConsumer( Profile& profile, const char *id , const char *service = NULL );
                        virtual ~PushConsumer( );
                        void set_render( int width, int height, double aspect_ratio );
                        virtual int connect( Service &service );
index 39c4a93eb72a4c0b4bd57377689de84b8349e65d..a320f29983a40e0b32914883340d6a01d9ed273f 100644 (file)
@@ -89,6 +89,11 @@ Profile *Service::profile( )
        return new Profile( mlt_service_profile( get_service() ) );
 }
 
+mlt_profile Service::get_profile()
+{
+       return mlt_service_profile( get_service() );
+}
+
 Frame *Service::get_frame( int index )
 {
        mlt_frame frame = NULL;
@@ -113,9 +118,18 @@ int Service::detach( Filter &filter )
        return mlt_service_detach( get_service( ), filter.get_filter( ) );
 }
 
+int Service::filter_count()
+{
+       return mlt_service_filter_count( get_service() );
+}
+
 Filter *Service::filter( int index )
 {
        mlt_filter result = mlt_service_filter( get_service( ), index );
        return result == NULL ? NULL : new Filter( result );
 }
 
+void Service::set_profile( Profile &profile )
+{
+       mlt_service_set_profile( get_service( ), profile.get_profile( ) );
+}
index 379d2925acbec4da47b1a25b94a457ace670610f..b755970f3df11048edd1d87267a2bd84ad45b208 100644 (file)
@@ -52,11 +52,14 @@ namespace Mlt
                        Service *consumer( );
                        Service *producer( );
                        Profile *profile( );
+                       mlt_profile get_profile( );
                        Frame *get_frame( int index = 0 );
                        mlt_service_type type( );
                        int attach( Filter &filter );
                        int detach( Filter &filter );
+                       int filter_count( );
                        Filter *filter( int index );
+                       void set_profile( Profile &profile );
        };
 }
 
index f25c66bd7a4c6ed71df4e18c7f8c54ce89371afc..4900fe6e5ea6da55eef925c9ab1b174a3135c893 100644 (file)
         #define MLTPP_DECLSPEC __declspec( dllimport )
     #endif
 #else
-    #define MLTPP_DECLSPEC
+    #if __GNUC__ >= 4
+        #define MLTPP_DECLSPEC __attribute__ ((visibility ("default")))
+    #else
+        #define MLTPP_DECLSPEC
+    #endif
 #endif
 
 #endif
index 98e470af90d2fa6d59949a27e307de51bb58fd0e..0a4d37a187b657ca7bb63420b693f3a7d7b7bb81 100755 (executable)
@@ -18,6 +18,6 @@ case $targetos in
        MinGW)
                echo LIBSUF=.dll
                echo "CXXFLAGS+=-Wall $WARNINGS -DPIC"
-               echo "LIBFLAGS=-enable-auto-import -shared"
+               echo "LIBFLAGS=-Wl,-enable-auto-import -shared"
                ;;
 esac >> config.mak
diff --git a/src/mlt++/mlt++.vers b/src/mlt++/mlt++.vers
new file mode 100644 (file)
index 0000000..c1f11a0
--- /dev/null
@@ -0,0 +1,444 @@
+MLTPP_0.8.8 {
+  global:
+    extern "C++" {
+      "Mlt::ClipInfo::~ClipInfo()";
+      "Mlt::ClipInfo::ClipInfo()";
+      "Mlt::ClipInfo::ClipInfo(mlt_playlist_clip_info*)";
+      "Mlt::ClipInfo::update(mlt_playlist_clip_info*)";
+      "typeinfo for Mlt::Consumer";
+      "typeinfo name for Mlt::Consumer";
+      "vtable for Mlt::Consumer";
+      "Mlt::Consumer::connect(Mlt::Service&)";
+      "Mlt::Consumer::~Consumer()";
+      "Mlt::Consumer::Consumer()";
+      "Mlt::Consumer::Consumer(Mlt::Consumer&)";
+      "Mlt::Consumer::Consumer(mlt_consumer_s*)";
+      "Mlt::Consumer::Consumer(Mlt::Profile&)";
+      "Mlt::Consumer::Consumer(Mlt::Profile&, char const*, char const*)";
+      "Mlt::Consumer::Consumer(Mlt::Service&)";
+      "Mlt::Consumer::get_consumer()";
+      "Mlt::Consumer::get_service()";
+      "Mlt::Consumer::is_stopped()";
+      "Mlt::Consumer::position()";
+      "Mlt::Consumer::purge()";
+      "Mlt::Consumer::run()";
+      "Mlt::Consumer::start()";
+      "Mlt::Consumer::stop()";
+      "Mlt::Deque::count()";
+      "Mlt::Deque::~Deque()";
+      "Mlt::Deque::Deque()";
+      "Mlt::Deque::peek_back()";
+      "Mlt::Deque::peek_front()";
+      "Mlt::Deque::pop_back()";
+      "Mlt::Deque::pop_front()";
+      "Mlt::Deque::push_back(void*)";
+      "Mlt::Deque::push_front(void*)";
+      "Mlt::Event::block()";
+      "Mlt::Event::~Event()";
+      "Mlt::Event::Event(Mlt::Event&)";
+      "Mlt::Event::Event(mlt_event_struct*)";
+      "Mlt::Event::get_event()";
+      "Mlt::Event::is_valid()";
+      "Mlt::Event::unblock()";
+      "Mlt::Factory::close()";
+      "Mlt::Factory::consumer(Mlt::Profile&, char*, char*)";
+      "Mlt::Factory::event_object()";
+      "Mlt::Factory::filter(Mlt::Profile&, char*, char*)";
+      "Mlt::Factory::init(char const*)";
+      "Mlt::Factory::producer(Mlt::Profile&, char*, char*)";
+      "Mlt::Factory::transition(Mlt::Profile&, char*, char*)";
+      "typeinfo for Mlt::Field";
+      "typeinfo name for Mlt::Field";
+      "vtable for Mlt::Field";
+      "Mlt::Field::disconnect_service(Mlt::Service&)";
+      "Mlt::Field::~Field()";
+      "Mlt::Field::Field(Mlt::Field&)";
+      "Mlt::Field::Field(mlt_field_s*)";
+      "Mlt::Field::get_field()";
+      "Mlt::Field::get_service()";
+      "Mlt::Field::plant_filter(Mlt::Filter&, int)";
+      "Mlt::Field::plant_transition(Mlt::Transition&, int, int)";
+      "typeinfo for Mlt::FilteredConsumer";
+      "typeinfo name for Mlt::FilteredConsumer";
+      "vtable for Mlt::FilteredConsumer";
+      "Mlt::FilteredConsumer::attach(Mlt::Filter&)";
+      "Mlt::FilteredConsumer::connect(Mlt::Service&)";
+      "Mlt::FilteredConsumer::detach(Mlt::Filter&)";
+      "Mlt::FilteredConsumer::~FilteredConsumer()";
+      "Mlt::FilteredConsumer::FilteredConsumer(Mlt::Consumer&)";
+      "Mlt::FilteredConsumer::FilteredConsumer(Mlt::Profile&, char const*, char const*)";
+      "Mlt::FilteredConsumer::last(Mlt::Filter&)";
+      "typeinfo for Mlt::FilteredProducer";
+      "typeinfo name for Mlt::FilteredProducer";
+      "vtable for Mlt::FilteredProducer";
+      "Mlt::FilteredProducer::attach(Mlt::Filter&)";
+      "Mlt::FilteredProducer::detach(Mlt::Filter&)";
+      "Mlt::FilteredProducer::~FilteredProducer()";
+      "Mlt::FilteredProducer::FilteredProducer(Mlt::Profile&, char const*, char const*)";
+      "typeinfo for Mlt::Filter";
+      "typeinfo name for Mlt::Filter";
+      "vtable for Mlt::Filter";
+      "Mlt::Filter::connect(Mlt::Service&, int)";
+      "Mlt::Filter::~Filter()";
+      "Mlt::Filter::Filter(Mlt::Filter&)";
+      "Mlt::Filter::Filter(mlt_filter_s*)";
+      "Mlt::Filter::Filter(Mlt::Profile&, char const*, char const*)";
+      "Mlt::Filter::Filter(Mlt::Service&)";
+      "Mlt::Filter::get_filter()";
+      "Mlt::Filter::get_in()";
+      "Mlt::Filter::get_length()";
+      "Mlt::Filter::get_length2(Mlt::Frame&)";
+      "Mlt::Filter::get_out()";
+      "Mlt::Filter::get_position(Mlt::Frame&)";
+      "Mlt::Filter::get_progress(Mlt::Frame&)";
+      "Mlt::Filter::get_service()";
+      "Mlt::Filter::get_track()";
+      "Mlt::Filter::set_in_and_out(int, int)";
+      "typeinfo for Mlt::Frame";
+      "typeinfo name for Mlt::Frame";
+      "vtable for Mlt::Frame";
+      "Mlt::Frame::fetch_image(mlt_image_format, int, int, int)";
+      "Mlt::Frame::~Frame()";
+      "Mlt::Frame::Frame(Mlt::Frame&)";
+      "Mlt::Frame::Frame(mlt_frame_s*)";
+      "Mlt::Frame::get_audio(mlt_audio_format&, int&, int&, int&)";
+      "Mlt::Frame::get_frame()";
+      "Mlt::Frame::get_image(mlt_image_format&, int&, int&, int)";
+      "Mlt::Frame::get_original_producer()";
+      "Mlt::Frame::get_position()";
+      "Mlt::Frame::get_properties()";
+      "Mlt::Frame::get_unique_properties(Mlt::Service&)";
+      "Mlt::Frame::get_waveform(int, int)";
+      "Mlt::Frame::set_alpha(unsigned char*, int, void (*)(void*))";
+      "Mlt::Frame::set_image(unsigned char*, int, void (*)(void*))";
+      "Mlt::Geometry::fetch(Mlt::GeometryItem*, float)";
+      "Mlt::Geometry::fetch(Mlt::GeometryItem&, float)";
+      "Mlt::Geometry::~Geometry()";
+      "Mlt::Geometry::Geometry(char*, int, int, int)";
+      "Mlt::Geometry::insert(Mlt::GeometryItem*)";
+      "Mlt::Geometry::insert(Mlt::GeometryItem&)";
+      "Mlt::Geometry::interpolate()";
+      "Mlt::Geometry::next_key(Mlt::GeometryItem*, int)";
+      "Mlt::Geometry::next_key(Mlt::GeometryItem&, int)";
+      "Mlt::Geometry::parse(char*, int, int, int)";
+      "Mlt::Geometry::prev_key(Mlt::GeometryItem*, int)";
+      "Mlt::Geometry::prev_key(Mlt::GeometryItem&, int)";
+      "Mlt::Geometry::remove(int)";
+      "Mlt::Geometry::serialise()";
+      "Mlt::Geometry::serialise(int, int)";
+      "typeinfo for Mlt::Multitrack";
+      "typeinfo name for Mlt::Multitrack";
+      "vtable for Mlt::Multitrack";
+      "Mlt::Multitrack::clip(mlt_whence, int)";
+      "Mlt::Multitrack::connect(Mlt::Producer&, int)";
+      "Mlt::Multitrack::count()";
+      "Mlt::Multitrack::get_multitrack()";
+      "Mlt::Multitrack::get_producer()";
+      "Mlt::Multitrack::~Multitrack()";
+      "Mlt::Multitrack::Multitrack(Mlt::Multitrack&)";
+      "Mlt::Multitrack::Multitrack(mlt_multitrack_s*)";
+      "Mlt::Multitrack::Multitrack(Mlt::Service&)";
+      "Mlt::Multitrack::refresh()";
+      "Mlt::Multitrack::track(int)";
+      "typeinfo for Mlt::Parser";
+      "typeinfo name for Mlt::Parser";
+      "vtable for Mlt::Parser";
+      "Mlt::Parser::get_properties()";
+      "Mlt::Parser::on_end_filter(Mlt::Filter*)";
+      "Mlt::Parser::on_end_multitrack(Mlt::Multitrack*)";
+      "Mlt::Parser::on_end_playlist(Mlt::Playlist*)";
+      "Mlt::Parser::on_end_producer(Mlt::Producer*)";
+      "Mlt::Parser::on_end_track()";
+      "Mlt::Parser::on_end_tractor(Mlt::Tractor*)";
+      "Mlt::Parser::on_end_transition(Mlt::Transition*)";
+      "Mlt::Parser::on_invalid(Mlt::Service*)";
+      "Mlt::Parser::on_start_filter(Mlt::Filter*)";
+      "Mlt::Parser::on_start_multitrack(Mlt::Multitrack*)";
+      "Mlt::Parser::on_start_playlist(Mlt::Playlist*)";
+      "Mlt::Parser::on_start_producer(Mlt::Producer*)";
+      "Mlt::Parser::on_start_track()";
+      "Mlt::Parser::on_start_tractor(Mlt::Tractor*)";
+      "Mlt::Parser::on_start_transition(Mlt::Transition*)";
+      "Mlt::Parser::on_unknown(Mlt::Service*)";
+      "Mlt::Parser::~Parser()";
+      "Mlt::Parser::Parser()";
+      "Mlt::Parser::start(Mlt::Service&)";
+      "typeinfo for Mlt::Playlist";
+      "typeinfo name for Mlt::Playlist";
+      "vtable for Mlt::Playlist";
+      "Mlt::Playlist::append(Mlt::Producer&, int, int)";
+      "Mlt::Playlist::blank(char const*)";
+      "Mlt::Playlist::blank(int)";
+      "Mlt::Playlist::blanks_from(int, int)";
+      "Mlt::Playlist::clear()";
+      "Mlt::Playlist::clip_info(int, Mlt::ClipInfo*)";
+      "Mlt::Playlist::clip_length(int)";
+      "Mlt::Playlist::clip(mlt_whence, int)";
+      "Mlt::Playlist::clip_start(int)";
+      "Mlt::Playlist::consolidate_blanks(int)";
+      "Mlt::Playlist::count()";
+      "Mlt::Playlist::current()";
+      "Mlt::Playlist::current_clip()";
+      "Mlt::Playlist::delete_clip_info(Mlt::ClipInfo*)";
+      "Mlt::Playlist::get_clip_at(int)";
+      "Mlt::Playlist::get_clip_index_at(int)";
+      "Mlt::Playlist::get_clip(int)";
+      "Mlt::Playlist::get_playlist()";
+      "Mlt::Playlist::get_producer()";
+      "Mlt::Playlist::insert_at(int, Mlt::Producer*, int)";
+      "Mlt::Playlist::insert_at(int, Mlt::Producer&, int)";
+      "Mlt::Playlist::insert_blank(int, int)";
+      "Mlt::Playlist::insert(Mlt::Producer&, int, int, int)";
+      "Mlt::Playlist::is_blank_at(int)";
+      "Mlt::Playlist::is_blank(int)";
+      "Mlt::Playlist::is_mix(int)";
+      "Mlt::Playlist::join(int, int, int)";
+      "Mlt::Playlist::mix_add(int, Mlt::Transition*)";
+      "Mlt::Playlist::mix(int, int, Mlt::Transition*)";
+      "Mlt::Playlist::move(int, int)";
+      "Mlt::Playlist::move_region(int, int, int)";
+      "Mlt::Playlist::pad_blanks(int, int, int)";
+      "Mlt::Playlist::~Playlist()";
+      "Mlt::Playlist::Playlist()";
+      "Mlt::Playlist::Playlist(Mlt::Playlist&)";
+      "Mlt::Playlist::Playlist(mlt_playlist_s*)";
+      "Mlt::Playlist::Playlist(Mlt::Profile&)";
+      "Mlt::Playlist::Playlist(Mlt::Service&)";
+      "Mlt::Playlist::remove(int)";
+      "Mlt::Playlist::remove_region(int, int)";
+      "Mlt::Playlist::repeat(int, int)";
+      "Mlt::Playlist::replace_with_blank(int)";
+      "Mlt::Playlist::resize_clip(int, int, int)";
+      "Mlt::Playlist::split_at(int, bool)";
+      "Mlt::Playlist::split(int, int)";
+      "typeinfo for Mlt::Producer";
+      "typeinfo name for Mlt::Producer";
+      "vtable for Mlt::Producer";
+      "Mlt::Producer::clear()";
+      "Mlt::Producer::cut(int, int)";
+      "Mlt::Producer::frame()";
+      "Mlt::Producer::frame_time(mlt_time_format)";
+      "Mlt::Producer::get_fps()";
+      "Mlt::Producer::get_in()";
+      "Mlt::Producer::get_length()";
+      "Mlt::Producer::get_length_time(mlt_time_format)";
+      "Mlt::Producer::get_out()";
+      "Mlt::Producer::get_parent()";
+      "Mlt::Producer::get_playtime()";
+      "Mlt::Producer::get_producer()";
+      "Mlt::Producer::get_service()";
+      "Mlt::Producer::get_speed()";
+      "Mlt::Producer::is_blank()";
+      "Mlt::Producer::is_cut()";
+      "Mlt::Producer::optimise()";
+      "Mlt::Producer::parent()";
+      "Mlt::Producer::pause()";
+      "Mlt::Producer::position()";
+      "Mlt::Producer::~Producer()";
+      "Mlt::Producer::Producer()";
+      "Mlt::Producer::Producer(Mlt::Producer*)";
+      "Mlt::Producer::Producer(Mlt::Producer&)";
+      "Mlt::Producer::Producer(mlt_producer_s*)";
+      "Mlt::Producer::Producer(Mlt::Profile&, char const*, char const*)";
+      "Mlt::Producer::Producer(Mlt::Service&)";
+      "Mlt::Producer::runs_into(Mlt::Producer&)";
+      "Mlt::Producer::same_clip(Mlt::Producer&)";
+      "Mlt::Producer::seek(char const*)";
+      "Mlt::Producer::seek(int)";
+      "Mlt::Producer::set_in_and_out(int, int)";
+      "Mlt::Producer::set_speed(double)";
+      "Mlt::Profile::colorspace() const";
+      "Mlt::Profile::dar() const";
+      "Mlt::Profile::description() const";
+      "Mlt::Profile::display_aspect_den() const";
+      "Mlt::Profile::display_aspect_num() const";
+      "Mlt::Profile::fps() const";
+      "Mlt::Profile::frame_rate_den() const";
+      "Mlt::Profile::frame_rate_num() const";
+      "Mlt::Profile::from_producer(Mlt::Producer&)";
+      "Mlt::Profile::get_profile() const";
+      "Mlt::Profile::height() const";
+      "Mlt::Profile::is_explicit() const";
+      "Mlt::Profile::list()";
+      "Mlt::Profile::~Profile()";
+      "Mlt::Profile::Profile()";
+      "Mlt::Profile::Profile(char const*)";
+      "Mlt::Profile::Profile(mlt_profile_s*)";
+      "Mlt::Profile::Profile(Mlt::Properties&)";
+      "Mlt::Profile::progressive() const";
+      "Mlt::Profile::sample_aspect_den() const";
+      "Mlt::Profile::sample_aspect_num() const";
+      "Mlt::Profile::sar() const";
+      "Mlt::Profile::set_colorspace(int)";
+      "Mlt::Profile::set_explicit(int)";
+      "Mlt::Profile::set_frame_rate(int, int)";
+      "Mlt::Profile::set_height(int)";
+      "Mlt::Profile::set_progressive(int)";
+      "Mlt::Profile::set_sample_aspect(int, int)";
+      "Mlt::Profile::set_width(int)";
+      "Mlt::Profile::width() const";
+      "typeinfo for Mlt::Properties";
+      "typeinfo name for Mlt::Properties";
+      "vtable for Mlt::Properties";
+      "Mlt::Properties::block(void*)";
+      "Mlt::Properties::count()";
+      "Mlt::Properties::debug(char const*, _IO_FILE*)";
+      "Mlt::Properties::dec_ref()";
+      "Mlt::Properties::delete_event(Mlt::Event*)";
+      "Mlt::Properties::dump(_IO_FILE*)";
+      "Mlt::Properties::fire_event(char const*)";
+      "Mlt::Properties::get(char const*)";
+      "Mlt::Properties::get_data(char const*)";
+      "Mlt::Properties::get_data(char const*, int&)";
+      "Mlt::Properties::get_data(int, int&)";
+      "Mlt::Properties::get_double(char const*)";
+      "Mlt::Properties::get(int)";
+      "Mlt::Properties::get_int64(char const*)";
+      "Mlt::Properties::get_int(char const*)";
+      "Mlt::Properties::get_lcnumeric()";
+      "Mlt::Properties::get_name(int)";
+      "Mlt::Properties::get_properties()";
+      "Mlt::Properties::get_time(char const*, mlt_time_format)";
+      "Mlt::Properties::inc_ref()";
+      "Mlt::Properties::inherit(Mlt::Properties&)";
+      "Mlt::Properties::is_sequence()";
+      "Mlt::Properties::is_valid()";
+      "Mlt::Properties::listen(char const*, void*, void (*)(void*, ...))";
+      "Mlt::Properties::load(char const*)";
+      "Mlt::Properties::lock()";
+      "Mlt::Properties::mirror(Mlt::Properties&)";
+      "Mlt::Properties::parse(char const*)";
+      "Mlt::Properties::parse_yaml(char const*)";
+      "Mlt::Properties::pass_list(Mlt::Properties&, char const*)";
+      "Mlt::Properties::pass_property(Mlt::Properties&, char const*)";
+      "Mlt::Properties::pass_values(Mlt::Properties&, char const*)";
+      "Mlt::Properties::preset(char const*)";
+      "Mlt::Properties::~Properties()";
+      "Mlt::Properties::Properties()";
+      "Mlt::Properties::Properties(bool)";
+      "Mlt::Properties::Properties(char const*)";
+      "Mlt::Properties::Properties(Mlt::Properties&)";
+      "Mlt::Properties::Properties(mlt_properties_s*)";
+      "Mlt::Properties::Properties(void*)";
+      "Mlt::Properties::ref_count()";
+      "Mlt::Properties::rename(char const*, char const*)";
+      "Mlt::Properties::save(char const*)";
+      "Mlt::Properties::serialise_yaml()";
+      "Mlt::Properties::set(char const*, char const*)";
+      "Mlt::Properties::set(char const*, double)";
+      "Mlt::Properties::set(char const*, int)";
+      "Mlt::Properties::set(char const*, long)";
+      "Mlt::Properties::set(char const*, void*, int, void (*)(void*), char* (*)(void*, int))";
+      "Mlt::Properties::set_lcnumeric(char const*)";
+      "Mlt::Properties::setup_wait_for(char const*)";
+      "Mlt::Properties::unblock(void*)";
+      "Mlt::Properties::unlock()";
+      "Mlt::Properties::wait_for(char const*)";
+      "Mlt::Properties::wait_for(Mlt::Event*, bool)";
+      "typeinfo for Mlt::PushConsumer";
+      "typeinfo name for Mlt::PushConsumer";
+      "vtable for Mlt::PushConsumer";
+      "Mlt::PushConsumer::connect(Mlt::Service&)";
+      "Mlt::PushConsumer::construct(int)";
+      "Mlt::PushConsumer::drain()";
+      "Mlt::PushConsumer::~PushConsumer()";
+      "Mlt::PushConsumer::PushConsumer(Mlt::Profile&, char const*, char const*)";
+      "Mlt::PushConsumer::push(Mlt::Frame*)";
+      "Mlt::PushConsumer::push(Mlt::Frame&)";
+      "Mlt::PushConsumer::set_render(int, int, double)";
+      "Mlt::Repository::consumers() const";
+      "Mlt::Repository::create(Mlt::Profile&, mlt_service_type, char const*, void*)";
+      "Mlt::Repository::filters() const";
+      "Mlt::Repository::languages() const";
+      "Mlt::Repository::metadata(mlt_service_type, char const*) const";
+      "Mlt::Repository::presets()";
+      "Mlt::Repository::producers() const";
+      "Mlt::Repository::register_metadata(mlt_service_type, char const*, mlt_properties_s* (*)(mlt_service_type, char const*, void*), void*)";
+      "Mlt::Repository::register_service(mlt_service_type, char const*, void* (*)(mlt_profile_s*, mlt_service_type, char const*, void const*))";
+      "Mlt::Repository::~Repository()";
+      "Mlt::Repository::Repository(char const*)";
+      "Mlt::Repository::Repository(mlt_repository_s*)";
+      "Mlt::Repository::transitions() const";
+      "typeinfo for Mlt::Service";
+      "typeinfo name for Mlt::Service";
+      "vtable for Mlt::Service";
+      "Mlt::Service::attach(Mlt::Filter&)";
+      "Mlt::Service::connect_producer(Mlt::Service&, int)";
+      "Mlt::Service::consumer()";
+      "Mlt::Service::detach(Mlt::Filter&)";
+      "Mlt::Service::filter(int)";
+      "Mlt::Service::get_frame(int)";
+      "Mlt::Service::get_profile()";
+      "Mlt::Service::get_properties()";
+      "Mlt::Service::get_service()";
+      "Mlt::Service::lock()";
+      "Mlt::Service::producer()";
+      "Mlt::Service::profile()";
+      "Mlt::Service::~Service()";
+      "Mlt::Service::Service()";
+      "Mlt::Service::Service(Mlt::Service&)";
+      "Mlt::Service::Service(mlt_service_s*)";
+      "Mlt::Service::set_profile(Mlt::Profile&)";
+      "Mlt::Service::type()";
+      "Mlt::Service::unlock()";
+      "Mlt::Tokeniser::count()";
+      "Mlt::Tokeniser::get(int)";
+      "Mlt::Tokeniser::input()";
+      "Mlt::Tokeniser::parse(char*, char*)";
+      "Mlt::Tokeniser::~Tokeniser()";
+      "Mlt::Tokeniser::Tokeniser(char*, char*)";
+      "typeinfo for Mlt::Tractor";
+      "typeinfo name for Mlt::Tractor";
+      "vtable for Mlt::Tractor";
+      "Mlt::Tractor::connect(Mlt::Producer&)";
+      "Mlt::Tractor::count()";
+      "Mlt::Tractor::field()";
+      "Mlt::Tractor::get_producer()";
+      "Mlt::Tractor::get_tractor()";
+      "Mlt::Tractor::locate_cut(Mlt::Producer*, int&, int&)";
+      "Mlt::Tractor::multitrack()";
+      "Mlt::Tractor::plant_filter(Mlt::Filter*, int)";
+      "Mlt::Tractor::plant_filter(Mlt::Filter&, int)";
+      "Mlt::Tractor::plant_transition(Mlt::Transition*, int, int)";
+      "Mlt::Tractor::plant_transition(Mlt::Transition&, int, int)";
+      "Mlt::Tractor::refresh()";
+      "Mlt::Tractor::set_track(Mlt::Producer&, int)";
+      "Mlt::Tractor::track(int)";
+      "Mlt::Tractor::~Tractor()";
+      "Mlt::Tractor::Tractor()";
+      "Mlt::Tractor::Tractor(Mlt::Profile&, char*, char*)";
+      "Mlt::Tractor::Tractor(Mlt::Service&)";
+      "Mlt::Tractor::Tractor(Mlt::Tractor&)";
+      "Mlt::Tractor::Tractor(mlt_tractor_s*)";
+      "typeinfo for Mlt::Transition";
+      "typeinfo name for Mlt::Transition";
+      "vtable for Mlt::Transition";
+      "Mlt::Transition::connect(Mlt::Producer&, int, int)";
+      "Mlt::Transition::get_a_track()";
+      "Mlt::Transition::get_b_track()";
+      "Mlt::Transition::get_in()";
+      "Mlt::Transition::get_length()";
+      "Mlt::Transition::get_out()";
+      "Mlt::Transition::get_position(Mlt::Frame&)";
+      "Mlt::Transition::get_progress_delta(Mlt::Frame&)";
+      "Mlt::Transition::get_progress(Mlt::Frame&)";
+      "Mlt::Transition::get_service()";
+      "Mlt::Transition::get_transition()";
+      "Mlt::Transition::set_in_and_out(int, int)";
+      "Mlt::Transition::~Transition()";
+      "Mlt::Transition::Transition(Mlt::Profile&, char const*, char const*)";
+      "Mlt::Transition::Transition(Mlt::Service&)";
+      "Mlt::Transition::Transition(Mlt::Transition&)";
+      "Mlt::Transition::Transition(mlt_transition_s*)";
+    };
+
+  local: *;
+};
+
+MLTPP_0.9.0 {
+  global:
+    extern "C++" {
+      "Mlt::Deque::peek(int)";
+      "Mlt::Service::filter_count()";
+    };
+} MLTPP_0.8.8;
index fcbf3ea6830a4a5943812d349e3223e6618a3d8c..928b1fdd2296a8a70ae2378f16af72cf8addc298 100644 (file)
@@ -27,5 +27,5 @@ install:
        done
 
 uninstall:
-       rm -rf "$(DESTDIR)$(libdir)/mlt"
+       rm -rf "$(DESTDIR)$(moduledir)"
 
index 14ecbb84235da5c05d7e432bdcca343c542740de..eceb375934b59b838fa230a520d82d9da5e1899e 100644 (file)
@@ -65,15 +65,15 @@ clean:
        rm -f $(OBJS) ../libmltffmpeg$(LIBSUF) ../libmltavformat$(LIBSUF)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/avformat"
-       install -m 644 producer_avformat.yml "$(DESTDIR)$(datadir)/mlt/avformat"
-       install -m 644 consumer_avformat.yml "$(DESTDIR)$(datadir)/mlt/avformat"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/avformat"
+       install -m 644 producer_avformat.yml "$(DESTDIR)$(mltdatadir)/avformat"
+       install -m 644 consumer_avformat.yml "$(DESTDIR)$(mltdatadir)/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)$(datadir)/mlt/avformat"
+       rm "$(DESTDIR)$(moduledir)/libmltavformat$(LIBSUF)" 2> /dev/null || true
+       rm "$(DESTDIR)$(moduledir)/libmltffmpeg$(LIBSUF)" 2> /dev/null || true
+       rm -rf "$(DESTDIR)$(mltdatadir)/avformat"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 5e3a7a245da00950d4e7c9e5c1d047025b998260..c8f55a387071cf2295c4bd6332a4a610739247bc 100755 (executable)
@@ -3,8 +3,8 @@
 # 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.
-ffmpeg_ver="0.8"
-libav_ver="0.7"
+ffmpeg_ver="1.0"
+libav_ver="0.8.4"
 micro_version=$(echo $version | cut -d . -f 3)
 odd_version=$(($micro_version % 2))
 [ "$odd_version" -eq "1" ] && ffmpeg_ver="HEAD" && libav_ver="HEAD"
@@ -54,7 +54,7 @@ else
        echo > config.mak
 
        export static_ffmpeg=
-       export shared_ffmpeg=$(pkg-config --variable=prefix libavformat)
+       export shared_ffmpeg=
        export extra_libs=
        export avformat_suffix=
        export swscale=
@@ -82,6 +82,8 @@ else
                esac
        done
 
+       : ${shared_ffmpeg:=$(pkg-config --variable=prefix libavformat${avformat_suffix})}
+
        if [ "$static_ffmpeg" != "" ]
        then 
                if [ -d "$static_ffmpeg" ]
@@ -105,7 +107,7 @@ else
                        
                        if [ "$vdpau" = "true" ]
                        then
-                               printf "#include <libavcodec/vdpau.h>\n int main(){ VdpBitstreamBuffer test; test.struct_version; return 0;}" | gcc -I"$static_ffmpeg" $CFLAGS -c -x c -  >/dev/null 2>&1
+                               printf "#include <libavcodec/vdpau.h>\n int main(){ VdpBitstreamBuffer test; test.struct_version; return 0;}" | $CC -I"$static_ffmpeg" $CFLAGS -c -x c -  >/dev/null 2>&1
                                [ "$x11" = "0" -a "$?" = "0" ] && echo "VDPAU=1" >> config.mak
                        fi
                else
@@ -121,27 +123,27 @@ else
                                echo "CFLAGS+=-DAVDATADIR=\\\"share/ffmpeg/\\\"" >> config.mak
                        ;;
                        *)
-                               echo "CFLAGS+=-DAVDATADIR=\\\"${shared_ffmpeg}/share/ffmpeg/\\\"" >> config.mak
+                               echo "CFLAGS+=-DAVDATADIR=\\\"${shared_ffmpeg}/share/ffmpeg${avformat_suffix}/\\\"" >> config.mak
                        ;;
                esac
-               echo "CFLAGS+=$(pkg-config --cflags libavformat)" >> config.mak
-               echo "LDFLAGS+=$(pkg-config --libs-only-L libavformat)" >> config.mak
+               echo "CFLAGS+=$(pkg-config --cflags libavformat${avformat_suffix})" >> config.mak
+               echo "LDFLAGS+=$(pkg-config --libs-only-L libavformat${avformat_suffix})" >> config.mak
                if [ "$devices" = "true" ]
                then
-                       echo "CFLAGS+=$(pkg-config --cflags libavdevice)" >> config.mak
-                       echo "LDFLAGS+=$(pkg-config --libs-only-L libavdevice)" >> config.mak
+                       echo "CFLAGS+=$(pkg-config --cflags libavdevice${avformat_suffix})" >> config.mak
+                       echo "LDFLAGS+=$(pkg-config --libs-only-L libavdevice${avformat_suffix})" >> config.mak
                fi
-               avcodec_version=$(pkg-config --modversion libavcodec)
+               avcodec_version=$(pkg-config --modversion libavcodec${avformat_suffix})
                if [ "$swscale" != "" ] || [ $(echo $avcodec_version | cut -d. -f1) -gt 52 ] || ( [ $(echo $avcodec_version | cut -d. -f1) -ge 52 ] && [ $(echo $avcodec_version | cut -d. -f2) -ge 21 ] )
                then
-                       echo "CFLAGS+=$(pkg-config --cflags libswscale)" >> config.mak
-                       echo "LDFLAGS+=$(pkg-config --libs-only-L libswscale)" >> config.mak
+                       echo "CFLAGS+=$(pkg-config --cflags libswscale${avformat_suffix})" >> config.mak
+                       echo "LDFLAGS+=$(pkg-config --libs-only-L libswscale${avformat_suffix})" >> config.mak
                        echo "SWSCALE=1" >> config.mak
                fi
                
                if [ "$vdpau" = "true" ]
                then
-                       printf "#include <libavcodec/vdpau.h>\n int main(){ VdpBitstreamBuffer test; test.struct_version; return 0;}" | gcc -I"$(pkg-config --cflags libavformat)" -I"$shared_ffmpeg/include" $CFLAGS -c -x c -  >/dev/null 2>&1
+                       printf "#include <libavcodec/vdpau.h>\n int main(){ VdpBitstreamBuffer test; test.struct_version; return 0;}" | $CC $(pkg-config --cflags libavformat${avformat_suffix}) -I"$shared_ffmpeg/include" $CFLAGS -c -x c -  >/dev/null 2>&1
                        [ "$x11" = "0" -a "$?" = "0" ] && echo "VDPAU=1" >> config.mak
                fi
        else
index 1db204299ff83c3df13f64f34a34acb22449b351..4f56dd74d32d8be51fbce12c289809914f4ed774 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * consumer_avformat.c -- an encoder based on avformat
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Charles Yates <charles.yates@pandora.be>
+ * Author: Dan Dennedy <dan@dennedy.org>
  * Much code borrowed from ffmpeg.c: Copyright (c) 2000-2003 Fabrice Bellard
  *
  * This library is free software; you can redistribute it and/or
 #if LIBAVUTIL_VERSION_INT >= ((50<<16)+(8<<8)+0)
 #include <libavutil/pixdesc.h>
 #endif
+#include <libavutil/mathematics.h>
+
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(38<<8)+0)
+#  include <libavutil/samplefmt.h>
+#else
+#  define AV_SAMPLE_FMT_NONE SAMPLE_FMT_NONE
+#  define AV_SAMPLE_FMT_U8  SAMPLE_FMT_U8
+#  define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
+#  define AV_SAMPLE_FMT_S32 SAMPLE_FMT_S32
+#  define AV_SAMPLE_FMT_FLT SAMPLE_FMT_FLT
+#endif
 
 #if LIBAVUTIL_VERSION_INT < (50<<16)
 #define PIX_FMT_RGB32 PIX_FMT_RGBA32
 #define AUDIO_BUFFER_SIZE (1024 * 42)
 #define VIDEO_BUFFER_SIZE (2048 * 1024)
 
-void avformat_lock( );
-void avformat_unlock( );
-
 //
 // This structure should be extended and made globally available in mlt
 //
 
 typedef struct
 {
-       int16_t *buffer;
+       uint8_t *buffer;
        int size;
        int used;
        double time;
@@ -90,42 +99,16 @@ sample_fifo sample_fifo_init( int frequency, int channels )
        return fifo;
 }
 
-// sample_fifo_clear and check are temporarily aborted (not working as intended)
-
-void sample_fifo_clear( sample_fifo fifo, double time )
-{
-       int words = ( float )( time - fifo->time ) * fifo->frequency * fifo->channels;
-       if ( ( int )( ( float )time * 100 ) < ( int )( ( float )fifo->time * 100 ) && fifo->used > words && words > 0 )
-       {
-               memmove( fifo->buffer, &fifo->buffer[ words ], ( fifo->used - words ) * sizeof( int16_t ) );
-               fifo->used -= words;
-               fifo->time = time;
-       }
-       else if ( ( int )( ( float )time * 100 ) != ( int )( ( float )fifo->time * 100 ) )
-       {
-               fifo->used = 0;
-               fifo->time = time;
-       }
-}
-
-void sample_fifo_check( sample_fifo fifo, double time )
-{
-       if ( fifo->used == 0 )
-       {
-               if ( ( int )( ( float )time * 100 ) < ( int )( ( float )fifo->time * 100 ) )
-                       fifo->time = time;
-       }
-}
-
-void sample_fifo_append( sample_fifo fifo, int16_t *samples, int count )
+// count is the number of samples multiplied by the number of bytes per sample
+void sample_fifo_append( sample_fifo fifo, uint8_t *samples, int count )
 {
        if ( ( fifo->size - fifo->used ) < count )
        {
                fifo->size += count * 5;
-               fifo->buffer = realloc( fifo->buffer, fifo->size * sizeof( int16_t ) );
+               fifo->buffer = realloc( fifo->buffer, fifo->size );
        }
 
-       memcpy( &fifo->buffer[ fifo->used ], samples, count * sizeof( int16_t ) );
+       memcpy( &fifo->buffer[ fifo->used ], samples, count );
        fifo->used += count;
 }
 
@@ -134,14 +117,14 @@ int sample_fifo_used( sample_fifo fifo )
        return fifo->used;
 }
 
-int sample_fifo_fetch( sample_fifo fifo, int16_t *samples, int count )
+int sample_fifo_fetch( sample_fifo fifo, uint8_t *samples, int count )
 {
        if ( count > fifo->used )
                count = fifo->used;
 
-       memcpy( samples, fifo->buffer, count * sizeof( int16_t ) );
+       memcpy( samples, fifo->buffer, count );
        fifo->used -= count;
-       memmove( fifo->buffer, &fifo->buffer[ count ], fifo->used * sizeof( int16_t ) );
+       memmove( fifo->buffer, &fifo->buffer[ count ], fifo->used );
 
        fifo->time += ( double )count / fifo->channels / fifo->frequency;
 
@@ -240,7 +223,9 @@ static int consumer_start( mlt_consumer consumer )
                        snprintf( key, sizeof(key), "%d", mlt_properties_count( formats ) );
                        mlt_properties_set( formats, key, format->name );
                }
-               fprintf( stdout, "%s", mlt_properties_serialise_yaml( doc ) );
+               s = mlt_properties_serialise_yaml( doc );
+               fprintf( stdout, "%s", s );
+               free( s );
                mlt_properties_close( doc );
                error = 1;
        }
@@ -255,12 +240,20 @@ static int consumer_start( mlt_consumer consumer )
                mlt_properties_set_data( properties, "acodec", codecs, 0, (mlt_destructor) mlt_properties_close, NULL );
                mlt_properties_set_data( doc, "audio_codecs", codecs, 0, NULL, NULL );
                while ( ( codec = av_codec_next( codec ) ) )
+#if (defined(FFUDIV) && LIBAVCODEC_VERSION_INT >= ((54<<16)+(56<<8)+100)) || (LIBAVCODEC_VERSION_INT >= ((54<<16)+(27<<8)+0))
+                       if ( codec->encode2 && codec->type == CODEC_TYPE_AUDIO )
+#elif LIBAVCODEC_VERSION_INT >= ((54<<16)+(0<<8)+0)
+                       if ( ( codec->encode || codec->encode2 ) && codec->type == CODEC_TYPE_AUDIO )
+#else
                        if ( codec->encode && codec->type == CODEC_TYPE_AUDIO )
+#endif
                        {
                                snprintf( key, sizeof(key), "%d", mlt_properties_count( codecs ) );
                                mlt_properties_set( codecs, key, codec->name );
                        }
-               fprintf( stdout, "%s", mlt_properties_serialise_yaml( doc ) );
+               s = mlt_properties_serialise_yaml( doc );
+               fprintf( stdout, "%s", s );
+               free( s );
                mlt_properties_close( doc );
                error = 1;
        }
@@ -275,12 +268,20 @@ static int consumer_start( mlt_consumer consumer )
                mlt_properties_set_data( properties, "vcodec", codecs, 0, (mlt_destructor) mlt_properties_close, NULL );
                mlt_properties_set_data( doc, "video_codecs", codecs, 0, NULL, NULL );
                while ( ( codec = av_codec_next( codec ) ) )
+#if (defined(FFUDIV) && LIBAVCODEC_VERSION_INT >= ((54<<16)+(56<<8)+100)) || (LIBAVCODEC_VERSION_INT >= ((54<<16)+(27<<8)+0))
+                       if ( codec->encode2 && codec->type == CODEC_TYPE_VIDEO )
+#elif LIBAVCODEC_VERSION_INT >= ((54<<16)+(0<<8)+0)
+                       if ( (codec->encode || codec->encode2) && codec->type == CODEC_TYPE_VIDEO )
+#else
                        if ( codec->encode && codec->type == CODEC_TYPE_VIDEO )
+#endif
                        {
                                snprintf( key, sizeof(key), "%d", mlt_properties_count( codecs ) );
                                mlt_properties_set( codecs, key, codec->name );
                        }
-               fprintf( stdout, "%s", mlt_properties_serialise_yaml( doc ) );
+               s = mlt_properties_serialise_yaml( doc );
+               fprintf( stdout, "%s", s );
+               free( s );
                mlt_properties_close( doc );
                error = 1;
        }
@@ -328,6 +329,38 @@ static int consumer_start( mlt_consumer consumer )
                        profile->height = height;
                }
 
+               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 );
+                       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 * height / width, 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, "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 ) );
+                       }
+               }
+
                // Handle the ffmpeg command line "-r" property for frame rate
                if ( mlt_properties_get( properties, "r" ) )
                {
@@ -352,11 +385,11 @@ static int consumer_start( mlt_consumer consumer )
                // 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, consumer );
+
+               // Set the running state
+               mlt_properties_set_int( properties, "running", 1 );
        }
        return error;
 }
@@ -368,18 +401,18 @@ static int consumer_stop( mlt_consumer consumer )
 {
        // Get the properties
        mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+       pthread_t *thread = mlt_properties_get_data( properties, "thread", NULL );
 
        // Check that we're running
-       if ( mlt_properties_get_int( properties, "running" ) )
+       if ( thread )
        {
-               // 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 );
+
+               mlt_properties_set_data( properties, "thread", NULL, 0, NULL, NULL );
        }
 
        return 0;
@@ -402,21 +435,33 @@ static void apply_properties( void *obj, mlt_properties properties, int flags )
 {
        int i;
        int count = mlt_properties_count( properties );
+#if LIBAVUTIL_VERSION_INT < ((51<<16)+(12<<8)+0)
        int alloc = 1;
+#endif
 
        for ( i = 0; i < count; i++ )
        {
                const char *opt_name = mlt_properties_get_name( properties, i );
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(10<<8)+0)
+               const AVOption *opt = av_opt_find( obj, opt_name, NULL, flags, flags );
+#else
                const AVOption *opt = av_find_opt( obj, opt_name, NULL, flags, flags );
+#endif
 
                // If option not found, see if it was prefixed with a or v (-vb)
                if ( !opt && (
                        ( opt_name[0] == 'v' && ( flags & AV_OPT_FLAG_VIDEO_PARAM ) ) ||
                        ( opt_name[0] == 'a' && ( flags & AV_OPT_FLAG_AUDIO_PARAM ) ) ) )
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(10<<8)+0)
+                       opt = av_opt_find( obj, ++opt_name, NULL, flags, flags );
+#else
                        opt = av_find_opt( obj, ++opt_name, NULL, flags, flags );
+#endif
                // Apply option if found
                if ( opt )
-#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(12<<8)+0)
+                       av_opt_set( obj, opt_name, mlt_properties_get_value( properties, i), 0 );
+#elif LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
                        av_set_string3( obj, opt_name, mlt_properties_get_value( properties, i), alloc, NULL );
 #elif LIBAVCODEC_VERSION_INT >= ((51<<16)+(59<<8)+0)
                        av_set_string2( obj, opt_name, mlt_properties_get_value( properties, i), alloc );
@@ -426,6 +471,104 @@ static void apply_properties( void *obj, mlt_properties properties, int flags )
        }
 }
 
+static int get_mlt_audio_format( int av_sample_fmt )
+{
+       switch ( av_sample_fmt )
+       {
+       case AV_SAMPLE_FMT_U8:
+               return mlt_audio_u8;
+       case AV_SAMPLE_FMT_S32:
+               return mlt_audio_s32le;
+       case AV_SAMPLE_FMT_FLT:
+               return mlt_audio_f32le;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+       case AV_SAMPLE_FMT_U8P:
+               return mlt_audio_u8;
+       case AV_SAMPLE_FMT_S32P:
+               return mlt_audio_s32le;
+       case AV_SAMPLE_FMT_FLTP:
+               return mlt_audio_f32le;
+#endif
+       default:
+               return mlt_audio_s16;
+       }
+}
+
+static int pick_sample_fmt( mlt_properties properties, AVCodec *codec )
+{
+       int sample_fmt = AV_SAMPLE_FMT_S16;
+       const char *format = mlt_properties_get( properties, "mlt_audio_format" );
+       const int *p = codec->sample_fmts;
+
+       // get default av_sample_fmt from mlt_audio_format
+       if ( format )
+       {
+               if ( !strcmp( format, "s32le" ) )
+                       sample_fmt = AV_SAMPLE_FMT_S32;
+               else if ( !strcmp( format, "f32le" ) )
+                       sample_fmt = AV_SAMPLE_FMT_FLT;
+               else if ( !strcmp( format, "u8" ) )
+                       sample_fmt = AV_SAMPLE_FMT_U8;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+               else if ( !strcmp( format, "s32" ) )
+                       sample_fmt = AV_SAMPLE_FMT_S32P;
+               else if ( !strcmp( format, "float" ) )
+                       sample_fmt = AV_SAMPLE_FMT_FLTP;
+#endif
+       }
+       // check if codec supports our mlt_audio_format
+       for ( ; *p != -1; p++ )
+       {
+               if ( *p == sample_fmt )
+                       return sample_fmt;
+       }
+       // no match - pick first one we support
+       for ( p = codec->sample_fmts; *p != -1; p++ )
+       {
+               switch (*p)
+               {
+               case AV_SAMPLE_FMT_U8:
+               case AV_SAMPLE_FMT_S16:
+               case AV_SAMPLE_FMT_S32:
+               case AV_SAMPLE_FMT_FLT:
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+               case AV_SAMPLE_FMT_U8P:
+               case AV_SAMPLE_FMT_S16P:
+               case AV_SAMPLE_FMT_S32P:
+               case AV_SAMPLE_FMT_FLTP:
+#endif
+                       return *p;
+               default:
+                       break;
+               }
+       }
+       mlt_log_error( properties, "audio codec sample_fmt not compatible" );
+
+       return AV_SAMPLE_FMT_NONE;
+}
+
+static uint8_t* interleaved_to_planar( int samples, int channels, uint8_t* audio, int bytes_per_sample )
+{
+       int size = samples * channels * bytes_per_sample;
+       uint8_t *buffer = mlt_pool_alloc( AUDIO_ENCODE_BUFFER_SIZE );
+       uint8_t *p = buffer;
+       int c;
+
+       memset( buffer, 0, AUDIO_ENCODE_BUFFER_SIZE );
+       for ( c = 0; c < channels; c++ )
+       {
+               uint8_t *q = audio + c * bytes_per_sample;
+               int i = samples + 1;
+               while ( --i )
+               {
+                       memcpy( p, q, bytes_per_sample );
+                       p += bytes_per_sample;
+                       q += channels * bytes_per_sample;
+               }
+       }
+       return buffer;
+}
+
 /** Add an audio output stream
 */
 
@@ -435,7 +578,11 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A
        mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
 
        // Create a new stream
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(10<<8)+0)
+       AVStream *st = avformat_new_stream( oc, codec );
+#else
        AVStream *st = av_new_stream( oc, oc->nb_streams );
+#endif
 
        // If created, then initialise from properties
        if ( st != NULL ) 
@@ -451,7 +598,7 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A
 
                c->codec_id = codec->id;
                c->codec_type = CODEC_TYPE_AUDIO;
-               c->sample_fmt = SAMPLE_FMT_S16;
+               c->sample_fmt = pick_sample_fmt( properties, codec );
 
 #if 0 // disabled until some audio codecs are multi-threaded
                // Setup multi-threading
@@ -490,7 +637,10 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A
         if ( audio_qscale > QSCALE_NONE )
                {
                        c->flags |= CODEC_FLAG_QSCALE;
-                       c->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
+                       c->global_quality = FF_QP2LAMBDA * audio_qscale;
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+                       st->quality = c->global_quality;
+#endif
                }
 
                // Set parameters controlled by MLT
@@ -500,7 +650,11 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A
 
                if ( mlt_properties_get( properties, "alang" ) != NULL )
 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(43<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+                       av_dict_set( &oc->metadata, "language", mlt_properties_get( properties, "alang" ), 0 );
+#else
                        av_metadata_set2( &oc->metadata, "language", mlt_properties_get( properties, "alang" ), 0 );
+#endif
 #else
 
                        strncpy( st->language, mlt_properties_get( properties, "alang" ), sizeof( st->language ) );
@@ -529,7 +683,7 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream
        else
                codec = avcodec_find_encoder( c->codec_id );
 
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(122<<8)+0)
        // Process properties as AVOptions on the AVCodec
        if ( codec && codec->priv_class )
        {
@@ -550,10 +704,12 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream
        }
 #endif
 
-       avformat_lock();
-       
        // Continue if codec found and we can open it
-       if ( codec != NULL && avcodec_open( c, codec ) >= 0 )
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
+       if ( codec && avcodec_open2( c, codec, NULL ) >= 0 )
+#else
+       if ( codec && avcodec_open( c, codec ) >= 0 )
+#endif
        {
                // ugly hack for PCM codecs (will be removed ASAP with new PCM
                // support to compute the input frame size in samples
@@ -586,9 +742,8 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream
        else
        {
                mlt_log_warning( NULL, "%s: Unable to encode audio - disabling audio output.\n", __FILE__ );
+               audio_input_frame_size = 0;
        }
-       
-       avformat_unlock();
 
        return audio_input_frame_size;
 }
@@ -596,11 +751,7 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream
 static void close_audio( AVFormatContext *oc, AVStream *st )
 {
        if ( st && st->codec )
-       {
-               avformat_lock();
                avcodec_close( st->codec );
-               avformat_unlock();
-       }
 }
 
 /** Add a video output stream 
@@ -612,7 +763,11 @@ static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, A
        mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
 
        // Create a new stream
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(10<<8)+0)
+       AVStream *st = avformat_new_stream( oc, codec );
+#else
        AVStream *st = av_new_stream( oc, oc->nb_streams );
+#endif
 
        if ( st != NULL ) 
        {
@@ -716,33 +871,7 @@ static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, A
                {
                        // "-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( consumer ) );
-                       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 ) );
-                       }
+                       c->sample_aspect_ratio = av_d2q( ar * c->height / c->width, 255 );
                }
                else
                {
@@ -756,7 +885,10 @@ static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, A
                if ( mlt_properties_get_double( properties, "qscale" ) > 0 )
                {
                        c->flags |= CODEC_FLAG_QSCALE;
-                       st->quality = FF_QP2LAMBDA * mlt_properties_get_double( properties, "qscale" );
+                       c->global_quality = FF_QP2LAMBDA * mlt_properties_get_double( properties, "qscale" );
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+                       st->quality = c->global_quality;
+#endif
                }
 
                // Allow the user to override the video fourcc
@@ -857,11 +989,14 @@ static AVStream *add_video_stream( mlt_consumer consumer, AVFormatContext *oc, A
                                                mlt_log_fatal( MLT_CONSUMER_SERVICE( consumer ), "Could not allocate log buffer\n" );
                                        else
                                        {
-                                               size = fread( logbuffer, 1, size, f );
-                                               fclose( f );
-                                               logbuffer[size] = '\0';
-                                               c->stats_in = logbuffer;
+                                               if ( size >= 0 )
+                                               {
+                                                       size = fread( logbuffer, 1, size, f );
+                                                       logbuffer[size] = '\0';
+                                                       c->stats_in = logbuffer;
+                                               }
                                        }
+                                       fclose( f );
                                }
                        }
                }
@@ -914,7 +1049,7 @@ static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream
        else
                codec = avcodec_find_encoder( video_enc->codec_id );
 
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(122<<8)+0)
        // Process properties as AVOptions on the AVCodec
        if ( codec && codec->priv_class )
        {
@@ -947,10 +1082,11 @@ static int open_video( mlt_properties properties, AVFormatContext *oc, AVStream
                        video_enc->pix_fmt = codec->pix_fmts[ 0 ];
        }
 
-       // Open the codec safely
-       avformat_lock();
-       int result = codec != NULL && avcodec_open( video_enc, codec ) >= 0;
-       avformat_unlock();
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
+       int result = codec && avcodec_open2( video_enc, codec, NULL ) >= 0;
+#else
+       int result = codec && avcodec_open( video_enc, codec ) >= 0;
+#endif
        
        return result;
 }
@@ -959,10 +1095,8 @@ void close_video(AVFormatContext *oc, AVStream *st)
 {
        if ( st && st->codec )
        {
-               avformat_lock();
                av_freep( &st->codec->stats_in );
                avcodec_close(st->codec);
-               avformat_unlock();
        }
 }
 
@@ -985,7 +1119,6 @@ static void write_transmitter( mlt_listener listener, mlt_properties owner, mlt_
        listener( owner, service, (uint8_t*) args[0], (int) args[1] );
 }
 
-
 /** The main thread - the argument is simply the consumer.
 */
 
@@ -1017,11 +1150,10 @@ static void *consumer_thread( void *arg )
        int img_height = height;
 
        // Get default audio properties
-       mlt_audio_format aud_fmt = mlt_audio_s16;
        int channels = mlt_properties_get_int( properties, "channels" );
        int total_channels = channels;
        int frequency = mlt_properties_get_int( properties, "frequency" );
-       int16_t *pcm = NULL;
+       void *pcm = NULL;
        int samples = 0;
 
        // AVFormat audio buffer and frame size
@@ -1051,8 +1183,8 @@ static void *consumer_thread( void *arg )
        mlt_image_format img_fmt = mlt_image_yuv422;
 
        // For receiving audio samples back from the fifo
-       int16_t *audio_buf_1 = av_malloc( AUDIO_ENCODE_BUFFER_SIZE );
-       int16_t *audio_buf_2 = NULL;
+       uint8_t *audio_buf_1 = av_malloc( AUDIO_ENCODE_BUFFER_SIZE );
+       uint8_t *audio_buf_2 = NULL;
        int count = 0;
 
        // Allocate the context
@@ -1143,6 +1275,10 @@ static void *consumer_thread( void *arg )
                                acodec = mlt_properties_get( properties, "_acodec" );
                                audio_codec = avcodec_find_encoder_by_name( acodec );
                        }
+                       else if ( !strcmp( acodec, "aac" ) )
+                       {
+                               mlt_properties_set( properties, "astrict", "experimental" );
+                       }
                }
                else
                {
@@ -1190,7 +1326,11 @@ static void *consumer_thread( void *arg )
                                markup[0] = '\0';
                                if ( !strstr( key, ".stream." ) )
 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(43<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+                                       av_dict_set( &oc->metadata, key, mlt_properties_get_value( properties, i ), 0 );
+#else
                                        av_metadata_set2( &oc->metadata, key, mlt_properties_get_value( properties, i ), 0 );
+#endif
 #else
                                        av_metadata_set( &oc->metadata, key, mlt_properties_get_value( properties, i ) );
 #endif
@@ -1231,13 +1371,16 @@ static void *consumer_thread( void *arg )
        frame = mlt_consumer_rt_frame( consumer );
 
        // Set the timecode from the MLT metadata if available.
-       const char *timecode = mlt_properties_get( MLT_FRAME_PROPERTIES(frame), "meta.attr.vitc.markup" );
-       if ( timecode && strcmp( timecode, "" ) )
-       {
-               mlt_properties_set( properties, "timecode", timecode );
-               if ( strchr( timecode, ';' ) )
-                       mlt_properties_set_int( properties, "drop_frame_timecode", 1 );
-       }
+    if ( frame )
+    {
+        const char *timecode = mlt_properties_get( MLT_FRAME_PROPERTIES(frame), "meta.attr.vitc.markup" );
+        if ( timecode && strcmp( timecode, "" ) )
+        {
+            mlt_properties_set( properties, "timecode", timecode );
+            if ( strchr( timecode, ';' ) )
+                mlt_properties_set_int( properties, "drop_frame_timecode", 1 );
+        }
+    }
 
        // Add audio and video streams
        if ( video_codec_id != CODEC_ID_NONE )
@@ -1268,10 +1411,24 @@ static void *consumer_thread( void *arg )
        }
        mlt_properties_set_int( properties, "channels", total_channels );
 
+       // Audio format is determined when adding the audio stream
+       mlt_audio_format aud_fmt = mlt_audio_none;
+       if ( audio_st[0] )
+               aud_fmt = get_mlt_audio_format( audio_st[0]->codec->sample_fmt );
+       int sample_bytes = mlt_audio_format_size( aud_fmt, 1, 1 );
+       sample_bytes = sample_bytes ? sample_bytes : 1; // prevent divide by zero
+
        // Set the parameters (even though we have none...)
-       if ( av_set_parameters(oc, NULL) >= 0 ) 
+#if LIBAVFORMAT_VERSION_INT < ((53<<16)+(2<<8)+0)
+       if ( av_set_parameters(oc, NULL) >= 0 )
+#endif
        {
+#if LIBAVFORMAT_VERSION_MAJOR >= 53
+               if ( mlt_properties_get( properties, "muxpreload" ) && ! mlt_properties_get( properties, "preload" ) )
+                       mlt_properties_set_double( properties, "preload", mlt_properties_get_double( properties, "muxpreload" ) );
+#else
                oc->preload = ( int )( mlt_properties_get_double( properties, "muxpreload" ) * AV_TIME_BASE );
+#endif
                oc->max_delay= ( int )( mlt_properties_get_double( properties, "muxdelay" ) * AV_TIME_BASE );
 
                // Process properties as AVOptions
@@ -1280,14 +1437,14 @@ static void *consumer_thread( void *arg )
                {
                        mlt_properties p = mlt_properties_load( fpre );
                        apply_properties( oc, p, AV_OPT_FLAG_ENCODING_PARAM );
-#if LIBAVFORMAT_VERSION_MAJOR >= 53
+#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(110<<8)+0)
                        if ( oc->oformat && oc->oformat->priv_class && oc->priv_data )
                                apply_properties( oc->priv_data, p, AV_OPT_FLAG_ENCODING_PARAM );
 #endif
                        mlt_properties_close( p );
                }
                apply_properties( oc, properties, AV_OPT_FLAG_ENCODING_PARAM );
-#if LIBAVFORMAT_VERSION_MAJOR >= 53
+#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(110<<8)+0)
                if ( oc->oformat && oc->oformat->priv_class && oc->priv_data )
                        apply_properties( oc->priv_data, properties, AV_OPT_FLAG_ENCODING_PARAM );
 #endif
@@ -1299,7 +1456,17 @@ static void *consumer_thread( void *arg )
                        audio_input_frame_size = open_audio( properties, oc, audio_st[i], audio_outbuf_size,
                                acodec? acodec : NULL );
                        if ( !audio_input_frame_size )
+                       {
+                               // Remove the audio stream from the output context
+                               int j;
+                               for ( j = 0; j < oc->nb_streams; j++ )
+                               {
+                                       if ( oc->streams[j] == audio_st[i] )
+                                               av_freep( &oc->streams[j] );
+                               }
+                               --oc->nb_streams;
                                audio_st[i] = NULL;
+                       }
                }
 
                // Setup custom I/O if redirecting
@@ -1338,19 +1505,27 @@ static void *consumer_thread( void *arg )
 #endif
                        {
                                mlt_log_error( MLT_CONSUMER_SERVICE( consumer ), "Could not open '%s'\n", filename );
-                               mlt_properties_set_int( properties, "running", 0 );
+                               mlt_events_fire( properties, "consumer-fatal-error", NULL );
+                               goto on_fatal_error;
                        }
                }
        
                // Write the stream header.
                if ( mlt_properties_get_int( properties, "running" ) )
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(2<<8)+0)
+                       avformat_write_header( oc, NULL );
+#else
                        av_write_header( oc );
+#endif
        }
+#if LIBAVFORMAT_VERSION_INT < ((53<<16)+(2<<8)+0)
        else
        {
                mlt_log_error( MLT_CONSUMER_SERVICE( consumer ), "Invalid output format parameters\n" );
-               mlt_properties_set_int( properties, "running", 0 );
+               mlt_events_fire( properties, "consumer-fatal-error", NULL );
+               goto on_fatal_error;
        }
+#endif
 
        // Allocate picture
        if ( video_st )
@@ -1358,7 +1533,10 @@ static void *consumer_thread( void *arg )
 
        // Last check - need at least one stream
        if ( !audio_st[0] && !video_st )
-               mlt_properties_set_int( properties, "running", 0 );
+       {
+               mlt_events_fire( properties, "consumer-fatal-error", NULL );
+               goto on_fatal_error;
+       }
 
        // Get the starting time (can ignore the times above)
        gettimeofday( &ante, NULL );
@@ -1387,7 +1565,7 @@ static void *consumer_thread( void *arg )
                        {
                                samples = mlt_sample_calculator( fps, frequency, count ++ );
                                channels = total_channels;
-                               mlt_frame_get_audio( frame, (void**) &pcm, &aud_fmt, &frequency, &channels, &samples );
+                               mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
 
                                // Save the audio channel remap properties for later
                                mlt_properties_pass( frame_meta_properties, frame_properties, "meta.map.audio." );
@@ -1398,15 +1576,16 @@ static void *consumer_thread( void *arg )
                                        fifo = sample_fifo_init( frequency, channels );
                                        mlt_properties_set_data( properties, "sample_fifo", fifo, 0, ( mlt_destructor )sample_fifo_close, NULL );
                                }
+                               if ( pcm )
+                               {
+                                       // Silence if not normal forward speed
+                                       if ( mlt_properties_get_double( frame_properties, "_speed" ) != 1.0 )
+                                               memset( pcm, 0, samples * channels * sample_bytes );
 
-                               // Silence if not normal forward speed
-                               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;
-
+                                       // Append the samples
+                                       sample_fifo_append( fifo, pcm, samples * channels * sample_bytes );
+                                       total_time += ( samples * 1000000 ) / frequency;
+                               }
                                if ( !video_st )
                                        mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
                        }
@@ -1426,15 +1605,15 @@ static void *consumer_thread( void *arg )
                        if ( !video_st || ( video_st && audio_st[0] && audio_pts < video_pts ) )
                        {
                                // Write audio
-                               if ( ( video_st && terminated ) || ( channels * audio_input_frame_size ) < sample_fifo_used( fifo ) )
+                               if ( ( video_st && terminated ) || ( channels * audio_input_frame_size ) < sample_fifo_used( fifo ) / sample_bytes )
                                {
                                        int j = 0; // channel offset into interleaved source buffer
-                                       int n = FFMIN( FFMIN( channels * audio_input_frame_size, sample_fifo_used( fifo ) ), AUDIO_ENCODE_BUFFER_SIZE );
+                                       int n = FFMIN( FFMIN( channels * audio_input_frame_size, sample_fifo_used( fifo ) / sample_bytes ), AUDIO_ENCODE_BUFFER_SIZE );
 
                                        // Get the audio samples
                                        if ( n > 0 )
                                        {
-                                               sample_fifo_fetch( fifo, audio_buf_1, n );
+                                               sample_fifo_fetch( fifo, audio_buf_1, n * sample_bytes );
                                        }
                                        else if ( audio_codec_id == CODEC_ID_VORBIS && terminated )
                                        {
@@ -1461,7 +1640,23 @@ static void *consumer_thread( void *arg )
                                                // Optimized for single track and no channel remap
                                                if ( !audio_st[1] && !mlt_properties_count( frame_meta_properties ) )
                                                {
-                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, audio_buf_1 );
+                                                       void* p = audio_buf_1;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+                                                       if ( codec->sample_fmt == AV_SAMPLE_FMT_FLTP )
+                                                               p = interleaved_to_planar( samples, channels, p, sizeof( float ) );
+                                                       else if ( codec->sample_fmt == AV_SAMPLE_FMT_S16P )
+                                                               p = interleaved_to_planar( samples, channels, p, sizeof( int16_t ) );
+                                                       else if ( codec->sample_fmt == AV_SAMPLE_FMT_S32P )
+                                                               p = interleaved_to_planar( samples, channels, p, sizeof( int32_t ) );
+                                                       else if ( codec->sample_fmt == AV_SAMPLE_FMT_U8P )
+                                                               p = interleaved_to_planar( samples, channels, p, sizeof( uint8_t ) );
+#endif
+                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, p );
+
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+                                                       if ( p != audio_buf_1 )
+                                                               mlt_pool_release( p );
+#endif
                                                }
                                                else
                                                {
@@ -1510,14 +1705,14 @@ static void *consumer_thread( void *arg )
                                                                        // Interleave the audio buffer with the # channels for this stream/mapping.
                                                                        for ( k = 0; k < map_channels; k++, j++, source_offset++, dest_offset++ )
                                                                        {
-                                                                               int16_t *src = audio_buf_1 + source_offset;
-                                                                               int16_t *dest = audio_buf_2 + dest_offset;
+                                                                               void *src = audio_buf_1 + source_offset * sample_bytes;
+                                                                               void *dest = audio_buf_2 + dest_offset * sample_bytes;
                                                                                int s = samples + 1;
 
                                                                                while ( --s ) {
-                                                                                       *dest = *src;
-                                                                                       dest += current_channels;
-                                                                                       src += channels;
+                                                                                       memcpy( dest, src, sample_bytes );
+                                                                                       dest += current_channels * sample_bytes;
+                                                                                       src += channels * sample_bytes;
                                                                                }
                                                                        }
                                                                }
@@ -1528,7 +1723,7 @@ static void *consumer_thread( void *arg )
                                                                        dest_offset += current_channels;
                                                                }
                                                        }
-                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, audio_buf_2 );
+                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, (short*) audio_buf_2 );
                                                }
 
                                                // Write the compressed frame in the media file
@@ -1597,7 +1792,7 @@ static void *consumer_thread( void *arg )
 
                                                // Do the colour space conversion
 #ifdef SWSCALE
-                                               int flags = SWS_BILINEAR;
+                                               int flags = SWS_BICUBIC;
 #ifdef USE_MMX
                                                flags |= SWS_CPU_CAPS_MMX;
 #endif
@@ -1649,6 +1844,15 @@ static void *consumer_thread( void *arg )
                                                AVPacket pkt;
                                                av_init_packet(&pkt);
 
+                                               // Set frame interlace hints
+                                               c->coded_frame->interlaced_frame = !mlt_properties_get_int( frame_properties, "progressive" );
+                                               c->coded_frame->top_field_first = mlt_properties_get_int( frame_properties, "top_field_first" );
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(61<<8)+100)
+                                               if ( mlt_properties_get_int( frame_properties, "progressive" ) )
+                                                       c->field_order = AV_FIELD_PROGRESSIVE;
+                                               else
+                                                       c->field_order = (mlt_properties_get_int( frame_properties, "top_field_first" )) ? AV_FIELD_TT : AV_FIELD_BB;
+#endif
                                                pkt.flags |= PKT_FLAG_KEY;
                                                pkt.stream_index= video_st->index;
                                                pkt.data= (uint8_t *)output;
@@ -1660,7 +1864,7 @@ static void *consumer_thread( void *arg )
                                        else 
                                        {
                                                // Set the quality
-                                               output->quality = video_st->quality;
+                                               output->quality = c->global_quality;
 
                                                // Set frame interlace hints
                                                output->interlaced_frame = !mlt_properties_get_int( frame_properties, "progressive" );
@@ -1726,7 +1930,7 @@ static void *consumer_thread( void *arg )
                        long passed = time_difference( &ante );
                        if ( fifo != NULL )
                        {
-                               long pending = ( ( ( long )sample_fifo_used( fifo ) * 1000 ) / frequency ) * 1000;
+                               long pending = ( ( ( long )sample_fifo_used( fifo ) / sample_bytes * 1000 ) / frequency ) * 1000;
                                passed -= pending;
                        }
                        if ( passed < total_time )
@@ -1750,11 +1954,26 @@ static void *consumer_thread( void *arg )
                        av_init_packet( &pkt );
                        pkt.size = 0;
 
-                       if ( /*( c->capabilities & CODEC_CAP_SMALL_LAST_FRAME ) &&*/
-                               ( channels * audio_input_frame_size < sample_fifo_used( fifo ) ) )
+                       if ( fifo &&
+                               ( channels * audio_input_frame_size < sample_fifo_used( fifo ) / sample_bytes ) )
                        {
-                               sample_fifo_fetch( fifo, audio_buf_1, channels * audio_input_frame_size );
-                               pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, audio_buf_1 );
+                               sample_fifo_fetch( fifo, audio_buf_1, channels * audio_input_frame_size * sample_bytes );
+                               void* p = audio_buf_1;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+                               if ( c->sample_fmt == AV_SAMPLE_FMT_FLTP )
+                                       p = interleaved_to_planar( audio_input_frame_size, channels, p, sizeof( float ) );
+                               else if ( c->sample_fmt == AV_SAMPLE_FMT_S16P )
+                                       p = interleaved_to_planar( audio_input_frame_size, channels, p, sizeof( int16_t ) );
+                               else if ( c->sample_fmt == AV_SAMPLE_FMT_S32P )
+                                       p = interleaved_to_planar( audio_input_frame_size, channels, p, sizeof( int32_t ) );
+                               else if ( c->sample_fmt == AV_SAMPLE_FMT_U8P )
+                                       p = interleaved_to_planar( audio_input_frame_size, channels, p, sizeof( uint8_t ) );
+#endif
+                               pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, p );
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+                               if ( p != audio_buf_1 )
+                                       mlt_pool_release( p );
+#endif
                        }
                        if ( pkt.size <= 0 )
                                pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, NULL );
@@ -1812,7 +2031,8 @@ static void *consumer_thread( void *arg )
 on_fatal_error:
        
        // Write the trailer, if any
-       av_write_trailer( oc );
+       if ( frames )
+               av_write_trailer( oc );
 
        // close each codec
        if ( video_st )
@@ -1825,13 +2045,13 @@ on_fatal_error:
                av_freep( &oc->streams[i] );
 
        // Close the output file
-       if ( !( fmt->flags & AVFMT_NOFILE ) )
+       if ( !( fmt->flags & AVFMT_NOFILE ) &&
+               !mlt_properties_get_int( properties, "redirect" ) )
        {
 #if LIBAVFORMAT_VERSION_MAJOR >= 53
-               if ( !mlt_properties_get_int( properties, "redirect" ) )
-                       avio_close( oc->pb );
+               if ( oc->pb  ) avio_close( oc->pb );
 #elif LIBAVFORMAT_VERSION_MAJOR >= 52
-               url_fclose( oc->pb );
+               if ( oc->pb  ) url_fclose( oc->pb );
 #else
                url_fclose( &oc->pb );
 #endif
@@ -1851,8 +2071,6 @@ on_fatal_error:
        av_free( oc );
 
        // Just in case we terminated on pause
-       mlt_properties_set_int( properties, "running", 0 );
-
        mlt_consumer_stopped( consumer );
        mlt_properties_close( frame_meta_properties );
 
index 7676f868b99479e7cc34cf1690c2000bdf7a8436..ddf05fe0813d2f6f970765800cb82a2bcb270303 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * factory.c -- the factory method interfaces
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Charles Yates <charles.yates@pandora.be>
  *
  * This library is free software; you can redistribute it and/or
@@ -43,51 +43,44 @@ extern mlt_producer producer_avformat_init( mlt_profile profile, const char *ser
 #include <libavcodec/opt.h>
 #endif
 
+#if LIBAVUTIL_VERSION_INT < ((51<<16)+(12<<8)+0)
+#define AV_OPT_TYPE_FLAGS    FF_OPT_TYPE_FLAGS
+#define AV_OPT_TYPE_INT      FF_OPT_TYPE_INT
+#define AV_OPT_TYPE_INT64    FF_OPT_TYPE_INT64
+#define AV_OPT_TYPE_DOUBLE   FF_OPT_TYPE_DOUBLE
+#define AV_OPT_TYPE_FLOAT    FF_OPT_TYPE_FLOAT
+#define AV_OPT_TYPE_STRING   FF_OPT_TYPE_STRING
+#define AV_OPT_TYPE_RATIONAL FF_OPT_TYPE_RATIONAL
+#define AV_OPT_TYPE_BINARY   FF_OPT_TYPE_BINARY
+#define AV_OPT_TYPE_CONST    FF_OPT_TYPE_CONST
+#endif
+
 // 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 )
+static int avformat_lockmgr(void **mutex, enum AVLockOp op)
 {
-       return mlt_pool_alloc( size );
-}
+   pthread_mutex_t** pmutex = (pthread_mutex_t**) mutex;
 
-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
+   switch (op)
+   {
+   case AV_LOCK_CREATE:
+      *pmutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+       pthread_mutex_init(*pmutex, NULL);
+       break;
+   case AV_LOCK_OBTAIN:
+       pthread_mutex_lock(*pmutex);
+       break;
+   case AV_LOCK_RELEASE:
+       pthread_mutex_unlock(*pmutex);
+       break;
+   case AV_LOCK_DESTROY:
+       pthread_mutex_destroy(*pmutex);
+       free(*pmutex);
+       break;
+   }
 
-       // 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 );
+   return 0;
 }
 
 static void avformat_init( )
@@ -96,7 +89,7 @@ static void avformat_init( )
        if ( avformat_initialised == 0 )
        {
                avformat_initialised = 1;
-               pthread_mutex_init( &avformat_mutex, NULL );
+               av_lockmgr_register( &avformat_lockmgr );
                av_register_all( );
 #ifdef AVDEVICE
                avdevice_register_all();
@@ -104,7 +97,6 @@ static void avformat_init( )
 #if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(13<<8))
                avformat_network_init();
 #endif
-               mlt_factory_register_for_clean_up( NULL, avformat_destroy );
                av_log_set_level( mlt_log_get_level() );
        }
 }
@@ -128,8 +120,10 @@ static void *create_service( mlt_profile profile, mlt_service_type type, const c
                return filter_avcolour_space_init( arg );
        if ( !strcmp( id, "avdeinterlace" ) )
                return filter_avdeinterlace_init( arg );
+#if LIBAVCODEC_VERSION_INT < ((54<<16)+(26<<8)+0)
        if ( !strcmp( id, "avresample" ) )
                return filter_avresample_init( arg );
+#endif
 #ifdef SWSCALE
        if ( !strcmp( id, "swscale" ) )
                return filter_swscale_init( profile, arg );
@@ -143,24 +137,28 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
        const AVOption *opt = NULL;
 
        // For each AVOption on the AVClass object
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(12<<8)+0)
+       while ( ( opt = av_opt_next( object, opt ) ) )
+#else
        while ( ( opt = av_next_option( object, opt ) ) )
+#endif
        {
                // If matches flags and not a binary option (not supported by Mlt)
-               if ( !( opt->flags & req_flags ) || ( opt->type == FF_OPT_TYPE_BINARY ) )
+               if ( !( opt->flags & req_flags ) || ( opt->type == AV_OPT_TYPE_BINARY ) )
             continue;
 
                // Ignore constants (keyword values)
-               if ( !unit && opt->type == FF_OPT_TYPE_CONST )
+               if ( !unit && opt->type == AV_OPT_TYPE_CONST )
                        continue;
                // When processing a groups of options (unit)...
                // ...ignore non-constants
-               else if ( unit && opt->type != FF_OPT_TYPE_CONST )
+               else if ( unit && opt->type != AV_OPT_TYPE_CONST )
                        continue;
                // ...ignore constants not in this group
-               else if ( unit && opt->type == FF_OPT_TYPE_CONST && strcmp( unit, opt->unit ) )
+               else if ( unit && opt->type == AV_OPT_TYPE_CONST && strcmp( unit, opt->unit ) )
                        continue;
                // ..add constants to the 'values' sequence
-               else if ( unit && opt->type == FF_OPT_TYPE_CONST )
+               else if ( unit && opt->type == AV_OPT_TYPE_CONST )
                {
                        char key[20];
                        snprintf( key, 20, "%d", mlt_properties_count( params ) );
@@ -195,11 +193,11 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
 
         switch ( opt->type )
                {
-               case FF_OPT_TYPE_FLAGS:
+               case AV_OPT_TYPE_FLAGS:
                        mlt_properties_set( p, "type", "string" );
                        mlt_properties_set( p, "format", "flags" );
                        break;
-               case FF_OPT_TYPE_INT:
+               case AV_OPT_TYPE_INT:
                        if ( !opt->unit )
                        {
                                mlt_properties_set( p, "type", "integer" );
@@ -217,7 +215,7 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
                                mlt_properties_set( p, "format", "integer or keyword" );
                        }
                        break;
-               case FF_OPT_TYPE_INT64:
+               case AV_OPT_TYPE_INT64:
                        mlt_properties_set( p, "type", "integer" );
                        mlt_properties_set( p, "format", "64-bit" );
                        if ( opt->min != INT64_MIN )
@@ -228,7 +226,7 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
                        mlt_properties_set_int64( p, "default", (int64_t) opt->default_val.dbl );
 #endif
                        break;
-               case FF_OPT_TYPE_FLOAT:
+               case AV_OPT_TYPE_FLOAT:
                        mlt_properties_set( p, "type", "float" );
                        if ( opt->min != FLT_MIN && opt->min != -340282346638528859811704183484516925440.0 )
                                mlt_properties_set_double( p, "minimum", opt->min );
@@ -238,7 +236,7 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
                        mlt_properties_set_double( p, "default", opt->default_val.dbl );
 #endif
                        break;
-               case FF_OPT_TYPE_DOUBLE:
+               case AV_OPT_TYPE_DOUBLE:
                        mlt_properties_set( p, "type", "float" );
                        mlt_properties_set( p, "format", "double" );
                        if ( opt->min != DBL_MIN )
@@ -249,24 +247,24 @@ static void add_parameters( mlt_properties params, void *object, int req_flags,
                        mlt_properties_set_double( p, "default", opt->default_val.dbl );
 #endif
                        break;
-               case FF_OPT_TYPE_STRING:
+               case AV_OPT_TYPE_STRING:
                        mlt_properties_set( p, "type", "string" );
 #if LIBAVUTIL_VERSION_MAJOR > 50
                        mlt_properties_set( p, "default", opt->default_val.str );
 #endif
                        break;
-               case FF_OPT_TYPE_RATIONAL:
+               case AV_OPT_TYPE_RATIONAL:
                        mlt_properties_set( p, "type", "string" );
                        mlt_properties_set( p, "format", "numerator:denominator" );
                        break;
-               case FF_OPT_TYPE_CONST:
+               case AV_OPT_TYPE_CONST:
                default:
                        mlt_properties_set( p, "type", "integer" );
                        mlt_properties_set( p, "format", "constant" );
                        break;
         }
                // If the option belongs to a group (unit) and is not a constant (keyword value)
-               if ( opt->unit && opt->type != FF_OPT_TYPE_CONST )
+               if ( opt->unit && opt->type != AV_OPT_TYPE_CONST )
                {
                        // Create a 'values' sequence.
                        mlt_properties values = mlt_properties_new();
@@ -313,7 +311,11 @@ static mlt_properties avformat_metadata( mlt_service_type type, const char *id,
                // Annotate the yaml properties with AVOptions.
                mlt_properties params = (mlt_properties) mlt_properties_get_data( result, "parameters", NULL );
                AVFormatContext *avformat = avformat_alloc_context();
+#if LIBAVCODEC_VERSION_INT > ((53<<16)+(8<<8)+0)
+               AVCodecContext *avcodec = avcodec_alloc_context3( NULL );
+#else
                AVCodecContext *avcodec = avcodec_alloc_context();
+#endif
                int flags = ( type == consumer_type )? AV_OPT_FLAG_ENCODING_PARAM : AV_OPT_FLAG_DECODING_PARAM;
 
                add_parameters( params, avformat, flags, NULL, NULL );
@@ -362,7 +364,9 @@ MLT_REPOSITORY
        MLT_REGISTER( filter_type, "avcolour_space", create_service );
        MLT_REGISTER( filter_type, "avcolor_space", create_service );
        MLT_REGISTER( filter_type, "avdeinterlace", create_service );
+#if LIBAVCODEC_VERSION_INT < ((54<<16)+(26<<8)+0)
        MLT_REGISTER( filter_type, "avresample", create_service );
+#endif
 #ifdef SWSCALE
        MLT_REGISTER( filter_type, "swscale", create_service );
 #endif
index 6396f887c10ad70e016c090d9124f75eaaa7b7e1..44f47858674d2404c170aab663cd8a7337047dbf 100644 (file)
@@ -65,8 +65,9 @@ static int convert_mlt_to_av_cs( mlt_image_format format )
                case mlt_image_yuv420p:
                        value = PIX_FMT_YUV420P;
                        break;
-               case mlt_image_none:
-                       mlt_log_error( NULL, "[filter avcolor_space] Invalid format\n" );
+               default:
+                       mlt_log_error( NULL, "[filter avcolor_space] Invalid format %s\n",
+                               mlt_image_format_name( format ) );
                        break;
        }
 
@@ -117,7 +118,7 @@ static void av_convert_image( uint8_t *out, uint8_t *in, int out_fmt, int in_fmt
        AVPicture input;
        AVPicture output;
 #ifdef SWSCALE
-       int flags = SWS_BILINEAR | SWS_ACCURATE_RND;
+       int flags = SWS_BICUBIC | SWS_ACCURATE_RND;
 
        if ( out_fmt == PIX_FMT_YUYV422 )
                flags |= SWS_FULL_CHR_H_INP;
@@ -169,7 +170,8 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo
 
                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 );
+               int size = FFMAX( avpicture_get_size( out_fmt, width, height ),
+                       mlt_image_format_size( output_format, width, height, NULL ) );
                uint8_t *output = mlt_pool_alloc( size );
 
                if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
@@ -198,7 +200,6 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo
                                                        while ( --n > 0 );
                                }
                                mlt_frame_set_alpha( frame, alpha, len, mlt_pool_release );
-                               frame->get_alpha_mask = NULL;
                        }
                }
 
@@ -303,8 +304,9 @@ static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
        if ( mlt_properties_get_int( properties, "colorspace" ) <= 0 )
                mlt_properties_set_int( properties, "colorspace", mlt_service_profile( MLT_FILTER_SERVICE(filter) )->colorspace );
 
-       frame->convert_image = convert_image;
-    
+       if ( !frame->convert_image )
+               frame->convert_image = convert_image;
+
 //     Not working yet - see comment for get_image() above.
 //     mlt_frame_push_service( frame, mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) );
 //     mlt_frame_push_get_image( frame, get_image );
index b75117453652b3e0427c7435b4452204f7773008..aa1327817b0f866d8744106b14e189d639c97cd7 100644 (file)
@@ -31,7 +31,7 @@
 #include "mmx.h"
 #else
 #define MAX_NEG_CROP 1024
-extern uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP];
+static uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP] = {0,};
 #endif
 
 #ifdef USE_MMX
@@ -346,6 +346,17 @@ static mlt_frame deinterlace_process( mlt_filter filter, mlt_frame frame )
 
 mlt_filter filter_avdeinterlace_init( void *arg )
 {
+#ifndef USE_MMX
+       if ( ff_cropTbl[MAX_NEG_CROP + 1] == 0 )
+       {
+               int i;
+               for(i=0;i<256;i++) ff_cropTbl[i + MAX_NEG_CROP] = i;
+               for(i=0;i<MAX_NEG_CROP;i++) {
+                       ff_cropTbl[i] = 0;
+                       ff_cropTbl[i + MAX_NEG_CROP + 256] = 255;
+               }
+       }
+#endif
        mlt_filter filter = mlt_filter_new( );
        if ( filter != NULL )
                filter->process = deinterlace_process;
index 340d22512350b6e6f905268ff1fddc7c415d0b49..78ea6a57a7025e3c4e7cd418bc97ee8c21b91659 100644 (file)
 
 // ffmpeg Header files
 #include <libavformat/avformat.h>
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(38<<8)+0)
+#  include <libavutil/samplefmt.h>
+#else
+#  define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
+#endif
+
+#if LIBAVCODEC_VERSION_INT < ((54<<16)+(26<<8)+0)
 
 /** Get the audio.
 */
@@ -79,7 +86,7 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                        // Create the resampler
 #if (LIBAVCODEC_VERSION_INT >= ((52<<16)+(15<<8)+0))
                        resample = av_audio_resample_init( *channels, *channels, output_rate, *frequency,
-                               SAMPLE_FMT_S16, SAMPLE_FMT_S16, 16, 10, 0, 0.8 );
+                               AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16, 16, 10, 0, 0.8 );
 #else
                        resample = audio_resample_init( *channels, *channels, output_rate, *frequency );
 #endif
@@ -170,3 +177,5 @@ mlt_filter filter_avresample_init( char *arg )
 
        return filter;
 }
+
+#endif // LIBAVCODEC_VERSION_INT < ((54<<16)+(26<<8)+0)
index ac7840f4368148ff4a760f6437eb41294a53b7d6..8e88f7c623df199df972d45837415bc52b298fd1 100644 (file)
@@ -55,7 +55,7 @@ static inline int convert_mlt_to_av_cs( mlt_image_format format )
                case mlt_image_yuv420p:
                        value = PIX_FMT_YUV420P;
                        break;
-               case mlt_image_none:
+               default:
                        fprintf( stderr, "Invalid format...\n" );
                        break;
        }
index 3098be904870f39e00b05f1146368f574fd94344..df88a92892ef7a4da2739697305c2b3c82af9a87 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * producer_avformat.c -- avformat producer
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Charles Yates <charles.yates@pandora.be>
  * Author: Dan Dennedy <dan@dennedy.org>
  * Much code borrowed from ffmpeg.c: Copyright (c) 2000-2003 Fabrice Bellard
 #ifdef SWSCALE
 #  include <libswscale/swscale.h>
 #endif
-#if LIBAVCODEC_VERSION_MAJOR >= 53
-#include <libavutil/samplefmt.h>
-#elif (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
+
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(38<<8)+0)
+#  include <libavutil/samplefmt.h>
+#else
+#  define AV_SAMPLE_FMT_U8  SAMPLE_FMT_U8
+#  define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
+#  define AV_SAMPLE_FMT_S32 SAMPLE_FMT_S32
+#  define AV_SAMPLE_FMT_FLT SAMPLE_FMT_FLT
+#  if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
 const char *avcodec_get_sample_fmt_name(int sample_fmt);
+#  endif
 #endif
+
 #ifdef VDPAU
 #  include <libavcodec/vdpau.h>
 #endif
 #if (LIBAVUTIL_VERSION_INT > ((50<<16)+(7<<8)+0))
 #  include <libavutil/pixdesc.h>
 #endif
+#if (LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0))
+#  include <libavutil/dict.h>
+#endif
 
 // System header files
 #include <stdlib.h>
@@ -69,12 +80,9 @@ const char *avcodec_get_sample_fmt_name(int sample_fmt);
 #define POSITION_INITIAL (-2)
 #define POSITION_INVALID (-1)
 
-#define MAX_AUDIO_STREAMS (10)
+#define MAX_AUDIO_STREAMS (32)
 #define MAX_VDPAU_SURFACES (10)
 
-void avformat_lock( );
-void avformat_unlock( );
-
 struct producer_avformat_s
 {
        mlt_producer parent;
@@ -84,17 +92,17 @@ struct producer_avformat_s
        AVCodecContext *audio_codec[ MAX_AUDIO_STREAMS ];
        AVCodecContext *video_codec;
        AVFrame *av_frame;
+       AVPacket pkt;
        ReSampleContext *audio_resample[ MAX_AUDIO_STREAMS ];
        mlt_position audio_expected;
        mlt_position video_expected;
        int audio_index;
        int video_index;
-       int first_pts;
+       int64_t first_pts;
        int64_t last_position;
        int seekable;
        int64_t current_position;
        mlt_position nonseek_position;
-       int got_picture;
        int top_field_first;
        uint8_t *audio_buffer[ MAX_AUDIO_STREAMS ];
        size_t audio_buffer_size[ MAX_AUDIO_STREAMS ];
@@ -106,14 +114,19 @@ struct producer_avformat_s
        int max_channel;
        int max_frequency;
        unsigned int invalid_pts_counter;
+       unsigned int invalid_dts_counter;
        double resample_factor;
        mlt_cache image_cache;
        int colorspace;
+       int full_luma;
        pthread_mutex_t video_mutex;
        pthread_mutex_t audio_mutex;
        mlt_deque apackets;
        mlt_deque vpackets;
        pthread_mutex_t packets_mutex;
+       pthread_mutex_t open_mutex;
+       int is_mutex_init;
+       AVRational video_time_base;
 #ifdef VDPAU
        struct
        {
@@ -145,6 +158,7 @@ static void producer_set_up_audio( producer_avformat self, mlt_frame frame );
 static void apply_properties( void *obj, mlt_properties properties, int flags );
 static int video_codec_init( producer_avformat self, int index, mlt_properties properties );
 static void get_audio_streams_info( producer_avformat self );
+static mlt_audio_format pick_audio_format( int sample_fmt );
 
 #ifdef VDPAU
 #include "vdpau.c"
@@ -192,18 +206,24 @@ mlt_producer producer_avformat_init( mlt_profile profile, const char *service, c
                                        // Clean up
                                        mlt_producer_close( producer );
                                        producer = NULL;
+                                       producer_avformat_close( self );
                                }
                                else if ( self->seekable )
                                {
                                        // Close the file to release resources for large playlists - reopen later as needed
-                                       avformat_lock();
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(17<<8)+0)
+                                       if ( self->audio_format )
+                                               avformat_close_input( &self->audio_format );
+                                       if ( self->video_format )
+                                               avformat_close_input( &self->video_format );
+#else
                                        if ( self->audio_format )
                                                av_close_input_file( self->audio_format );
-                                       self->audio_format = NULL;
                                        if ( self->video_format )
                                                av_close_input_file( self->video_format );
+#endif
+                                       self->audio_format = NULL;
                                        self->video_format = NULL;
-                                       avformat_unlock();
                                }
                        }
                        if ( producer )
@@ -259,6 +279,23 @@ int list_components( char* file )
        return skip;
 }
 
+static int first_video_index( producer_avformat self )
+{
+       AVFormatContext *context = self->video_format? self->video_format : self->audio_format;
+       int i = -1; // not found
+
+       if ( context ) {
+               for ( i = 0; i < context->nb_streams; i++ ) {
+                       if ( context->streams[i]->codec &&
+                            context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )
+                               break;
+               }
+               if ( i == context->nb_streams )
+                       i = -1;
+       }
+       return i;
+}
+
 /** Find the default streams.
 */
 
@@ -266,7 +303,11 @@ static mlt_properties find_default_streams( producer_avformat self )
 {
        int i;
        char key[200];
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+       AVDictionaryEntry *tag = NULL;
+#else
        AVMetadataTag *tag = NULL;
+#endif
        AVFormatContext *context = self->video_format;
        mlt_properties meta_media = MLT_PRODUCER_PROPERTIES( self->parent );
 
@@ -311,11 +352,19 @@ static mlt_properties find_default_streams( producer_avformat self )
                                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.width", i );
+                               mlt_properties_set_int( meta_media, key, codec_context->width );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.height", i );
+                               mlt_properties_set_int( meta_media, key, codec_context->height );
                                snprintf( key, sizeof(key), "meta.media.%d.codec.frame_rate", i );
                                mlt_properties_set_double( meta_media, key, (double) codec_context->time_base.den /
                                                                                   ( codec_context->time_base.num == 0 ? 1 : codec_context->time_base.num ) );
                                snprintf( key, sizeof(key), "meta.media.%d.codec.pix_fmt", i );
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(3<<8)+0)
+                               mlt_properties_set( meta_media, key, av_get_pix_fmt_name( codec_context->pix_fmt ) );
+#else
                                mlt_properties_set( meta_media, key, avcodec_get_pix_fmt_name( codec_context->pix_fmt ) );
+#endif
                                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 ) );
 #if LIBAVCODEC_VERSION_INT > ((52<<16)+(28<<8)+0)
@@ -340,11 +389,14 @@ static mlt_properties find_default_streams( producer_avformat self )
 #endif
                                break;
                        case CODEC_TYPE_AUDIO:
+                               if ( !codec_context->channels )
+                                       break;
                                // Use first audio stream
-                               if ( self->audio_index < 0 )
+                               if ( self->audio_index < 0 && pick_audio_format( codec_context->sample_fmt ) != mlt_audio_none )
                                        self->audio_index = i;
+
                                mlt_properties_set( meta_media, key, "audio" );
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(38<<8)+0)
                                snprintf( key, sizeof(key), "meta.media.%d.codec.sample_fmt", i );
                                mlt_properties_set( meta_media, key, av_get_sample_fmt_name( codec_context->sample_fmt ) );
 #elif (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
@@ -378,7 +430,11 @@ static mlt_properties find_default_streams( producer_avformat self )
 
                // Read Metadata
 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+               while ( ( tag = av_dict_get( stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX ) ) )
+#else
                while ( ( tag = av_metadata_get( stream->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX ) ) )
+#endif
                {
                        if ( tag->value && strcmp( tag->value, "" ) && strcmp( tag->value, "und" ) )
                        {
@@ -389,7 +445,11 @@ static mlt_properties find_default_streams( producer_avformat self )
 #endif
        }
 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+       while ( ( tag = av_dict_get( context->metadata, "", tag, AV_DICT_IGNORE_SUFFIX ) ) )
+#else
        while ( ( tag = av_metadata_get( context->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX ) ) )
+#endif
        {
                if ( tag->value && strcmp( tag->value, "" ) && strcmp( tag->value, "und" ) )
                {
@@ -544,11 +604,15 @@ static double get_aspect_ratio( mlt_properties properties, AVStream *stream, AVC
        return aspect_ratio;
 }
 
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **format, AVDictionary **params )
+#else
 static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **format, AVFormatParameters *params )
+#endif
 {
        if ( !URL ) return NULL;
 
-       const char *result = URL;
+       char *result = NULL;
        char *protocol = strdup( URL );
        char *url = strchr( protocol, ':' );
 
@@ -571,6 +635,11 @@ static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **fo
 
                if ( *format )
                {
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+                       // support for legacy width and height parameters
+                       char *width = NULL;
+                       char *height = NULL;
+#else
                        // These are required by video4linux2 (defaults)
                        params->width = profile->width;
                        params->height = profile->height;
@@ -578,6 +647,7 @@ static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **fo
                                params->time_base = (AVRational){ profile->frame_rate_den, profile->frame_rate_num };
                        params->channels = 2;
                        params->sample_rate = 48000;
+#endif
 
                        // Parse out params
                        url = strchr( url, '?' );
@@ -596,6 +666,20 @@ static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **fo
                                        char *t = strchr( value, '&' );
                                        if ( t )
                                                t[0] = 0;
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+                                       // translate old parameters to new av_dict names
+                                       if ( !strcmp( name, "frame_rate" ) )
+                                               av_dict_set( params, "framerate", value, 0 );
+                                       else if ( !strcmp( name, "pix_fmt" ) )
+                                               av_dict_set( params, "pixel_format", value, 0 );
+                                       else if ( !strcmp( name, "width" ) )
+                                               width = strdup( value );
+                                       else if ( !strcmp( name, "height" ) )
+                                               height = strdup( value );
+                                       else
+                                               // generic demux/device option support
+                                               av_dict_set( params, name, value, 0 );
+#else
                                        if ( !strcmp( name, "frame_rate" ) )
                                                params->time_base.den = atoi( value );
                                        else if ( !strcmp( name, "frame_rate_base" ) )
@@ -616,13 +700,32 @@ static char* parse_url( mlt_profile profile, const char* URL, AVInputFormat **fo
                                                params->height = atoi( value );
                                        else if ( !strcmp( name, "standard" ) )
                                                params->standard = strdup( value );
+#endif
                                }
                                free( name );
                                url = strchr( url, '&' );
                        }
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+                       // continued support for legacy width and height parameters
+                       if ( width && height )
+                       {
+                               char *s = malloc( strlen( width ) + strlen( height ) + 2 );
+                               strcpy( s, width );
+                               strcat( s, "x");
+                               strcat( s, height );
+                               av_dict_set( params, "video_size", s, 0 );
+                               free( s );
+                       }
+                       if ( width ) free( width );
+                       if ( height ) free ( height );
+#endif
                }
+               result = strdup( result );
+       }
+       else
+       {
+               result = strdup( URL );
        }
-       result = strdup( result );
        free( protocol );
        return result;
 }
@@ -683,9 +786,15 @@ static int get_basic_info( producer_avformat self, mlt_profile profile, const ch
                self->seekable = av_seek_frame( format, -1, format->start_time, AVSEEK_FLAG_BACKWARD ) >= 0;
                mlt_properties_set_int( properties, "seekable", self->seekable );
                self->dummy_context = format;
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+               self->video_format = NULL;
+               avformat_open_input( &self->video_format, filename, NULL, NULL );
+               avformat_find_stream_info( self->video_format, NULL );
+#else
                av_open_input_file( &self->video_format, filename, NULL, 0, NULL );
+               av_find_stream_info( self->video_format );
+#endif
                format = self->video_format;
-               av_find_stream_info( format );
        }
 
        // Fetch the width, height and aspect ratio
@@ -706,8 +815,11 @@ static int get_basic_info( producer_avformat self, mlt_profile profile, const ch
                                if ( ret >= 0 && pkt.stream_index == self->video_index && pkt.size > 0 )
                                {
                                        get_aspect_ratio( properties, format->streams[ self->video_index ], codec_context, &pkt );
+                                       av_free_packet(&pkt);
                                        break;
                                }
+                               if ( ret >= 0 )
+                                       av_free_packet(&pkt);
                        }
                }
                else
@@ -741,9 +853,14 @@ static int producer_open( producer_avformat self, mlt_profile profile, const cha
        // Lock the service
        if ( take_lock )
        {
-               pthread_mutex_init( &self->audio_mutex, NULL );
-               pthread_mutex_init( &self->video_mutex, NULL );
-               pthread_mutex_init( &self->packets_mutex, NULL );
+               if ( !self->is_mutex_init )
+               {
+                       pthread_mutex_init( &self->audio_mutex, NULL );
+                       pthread_mutex_init( &self->video_mutex, NULL );
+                       pthread_mutex_init( &self->packets_mutex, NULL );
+                       pthread_mutex_init( &self->open_mutex, NULL );
+                       self->is_mutex_init = 1;
+               }
                pthread_mutex_lock( &self->audio_mutex );
                pthread_mutex_lock( &self->video_mutex );
        }
@@ -751,35 +868,54 @@ static int producer_open( producer_avformat self, mlt_profile profile, const cha
 
        // Parse URL
        AVInputFormat *format = NULL;
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+       AVDictionary *params = NULL;
+#else
        AVFormatParameters params;
        memset( &params, 0, sizeof(params) );
+#endif
        char *filename = parse_url( profile, URL, &format, &params );
 
        // Now attempt to open the file or device with filename
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+       error = avformat_open_input( &self->video_format, filename, format, &params ) < 0;
+       if ( error )
+               // If the URL is a network stream URL, then we probably need to open with full URL
+               error = avformat_open_input( &self->video_format, URL, format, &params ) < 0;
+#else
        error = av_open_input_file( &self->video_format, filename, format, 0, &params ) < 0;
        if ( error )
                // If the URL is a network stream URL, then we probably need to open with full URL
                error = av_open_input_file( &self->video_format, URL, format, 0, &params ) < 0;
+#endif
 
        // Set MLT properties onto video AVFormatContext
        if ( !error && self->video_format )
        {
                apply_properties( self->video_format, properties, AV_OPT_FLAG_DECODING_PARAM );
-#if LIBAVFORMAT_VERSION_MAJOR >= 53
+#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(110<<8)+0)
                if ( self->video_format->iformat && self->video_format->iformat->priv_class && self->video_format->priv_data )
                        apply_properties( self->video_format->priv_data, properties, AV_OPT_FLAG_DECODING_PARAM );
 #endif
        }
 
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+       av_dict_free( &params );
+#else
        // Cleanup AVFormatParameters
        if ( params.standard )
                free( (void*) params.standard );
+#endif
 
        // If successful, then try to get additional info
        if ( !error && self->video_format )
        {
                // Get the stream info
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+               error = avformat_find_stream_info( self->video_format, NULL ) < 0;
+#else
                error = av_find_stream_info( self->video_format ) < 0;
+#endif
 
                // Continue if no error
                if ( !error && self->video_format )
@@ -789,7 +925,7 @@ static int producer_open( producer_avformat self, mlt_profile profile, const cha
                        error = get_basic_info( self, profile, filename );
 
                        // Initialize position info
-                       self->first_pts = -1;
+                       self->first_pts = AV_NOPTS_VALUE;
                        self->last_position = POSITION_INITIAL;
 
                        if ( !self->audio_format )
@@ -802,13 +938,21 @@ static int producer_open( producer_avformat self, mlt_profile profile, const cha
                                        if ( self->seekable )
                                        {
                                                // And open again for our audio context
-                                               av_open_input_file( &self->audio_format, filename, NULL, 0, NULL );
+#if LIBAVFORMAT_VERSION_INT > ((53<<16)+(6<<8)+0)
+                                               avformat_open_input( &self->audio_format, filename, NULL, NULL );
                                                apply_properties( self->audio_format, properties, AV_OPT_FLAG_DECODING_PARAM );
-#if LIBAVFORMAT_VERSION_MAJOR >= 53
                                                if ( self->audio_format->iformat && self->audio_format->iformat->priv_class && self->audio_format->priv_data )
                                                        apply_properties( self->audio_format->priv_data, properties, AV_OPT_FLAG_DECODING_PARAM );
+                                               avformat_find_stream_info( self->audio_format, NULL );
+#else
+                                               av_open_input_file( &self->audio_format, filename, NULL, 0, NULL );
+                                               apply_properties( self->audio_format, properties, AV_OPT_FLAG_DECODING_PARAM );
+#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(110<<8)+0)
+                        if ( self->audio_format->iformat && self->audio_format->iformat->priv_class && self->audio_format->priv_data )
+                            apply_properties( self->audio_format->priv_data, properties, AV_OPT_FLAG_DECODING_PARAM );
 #endif
                                                av_find_stream_info( self->audio_format );
+#endif
                                        }
                                        else
                                        {
@@ -841,10 +985,14 @@ static int producer_open( producer_avformat self, mlt_profile profile, const cha
 
        if ( self->dummy_context )
        {
-               avformat_lock();
+               pthread_mutex_lock( &self->open_mutex );
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(17<<8)+0)
+               avformat_close_input( &self->dummy_context );
+#else
                av_close_input_file( self->dummy_context );
-               avformat_unlock();
+#endif
                self->dummy_context = NULL;
+               pthread_mutex_unlock( &self->open_mutex );
        }
 
        // Unlock the service
@@ -863,18 +1011,25 @@ static void reopen_video( producer_avformat self, mlt_producer producer )
        mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
        mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) );
        pthread_mutex_lock( &self->audio_mutex );
+       pthread_mutex_lock( &self->open_mutex );
 
-       avformat_lock();
        if ( self->video_codec )
                avcodec_close( self->video_codec );
        self->video_codec = NULL;
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(17<<8)+0)
+       if ( self->dummy_context )
+               avformat_close_input( &self->dummy_context );
+       if ( self->video_format )
+               avformat_close_input( &self->video_format );
+#else
        if ( self->dummy_context )
                av_close_input_file( self->dummy_context );
-       self->dummy_context = NULL;
        if ( self->video_format )
                av_close_input_file( self->video_format );
+#endif
+       self->dummy_context = NULL;
        self->video_format = NULL;
-       avformat_unlock();
+       pthread_mutex_unlock( &self->open_mutex );
 
        int audio_index = self->audio_index;
        int video_index = self->video_index;
@@ -893,8 +1048,44 @@ static void reopen_video( producer_avformat self, mlt_producer producer )
        mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) );
 }
 
+static int64_t best_pts( producer_avformat self, int64_t pts, int64_t dts )
+{
+       self->invalid_pts_counter += pts == AV_NOPTS_VALUE;
+       self->invalid_dts_counter += dts == AV_NOPTS_VALUE;
+       if ( ( self->invalid_pts_counter <= self->invalid_dts_counter
+                  || dts == AV_NOPTS_VALUE ) && pts != AV_NOPTS_VALUE )
+               return pts;
+       else
+               return dts;
+}
+
+static void find_first_pts( producer_avformat self, int video_index )
+{
+       // find initial PTS
+       AVFormatContext *context = self->video_format? self->video_format : self->audio_format;
+       int ret = 0;
+       int toscan = 500;
+       AVPacket pkt;
+
+       while ( ret >= 0 && toscan-- > 0 )
+       {
+               ret = av_read_frame( context, &pkt );
+               if ( ret >= 0 && pkt.stream_index == video_index && ( pkt.flags & PKT_FLAG_KEY ) )
+               {
+                       mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent),
+                               "first_pts %"PRId64" dts %"PRId64" pts_dts_delta %d\n",
+                               pkt.pts, pkt.dts, (int)(pkt.pts - pkt.dts) );
+                       self->first_pts = best_pts( self, pkt.pts, pkt.dts );
+                       if ( self->first_pts != AV_NOPTS_VALUE )
+                               toscan = 0;
+               }
+               av_free_packet( &pkt );
+       }
+       av_seek_frame( context, -1, 0, AVSEEK_FLAG_BACKWARD );
+}
+
 static int seek_video( producer_avformat self, mlt_position position,
-       int64_t req_position, int must_decode, int use_new_seek, int *ignore )
+       int64_t req_position, int preseek )
 {
        mlt_producer producer = self->parent;
        int paused = 0;
@@ -916,75 +1107,40 @@ static int seek_video( producer_avformat self, mlt_position position,
                double source_fps = mlt_properties_get_double( properties, "meta.media.frame_rate_num" ) /
                        mlt_properties_get_double( properties, "meta.media.frame_rate_den" );
 
+               if ( self->last_position == POSITION_INITIAL )
+                       find_first_pts( self, self->video_index );
+
                if ( self->av_frame && position + 1 == self->video_expected )
                {
                        // We're paused - use last image
                        paused = 1;
                }
-               else if ( !self->seekable && position > self->video_expected && ( position - self->video_expected ) < 250 )
-               {
-                       // Fast forward - seeking is inefficient for small distances - just ignore following frames
-                       *ignore = ( int )( ( position - self->video_expected ) / mlt_producer_get_fps( producer ) * source_fps );
-                       codec_context->skip_loop_filter = AVDISCARD_NONREF;
-               }
                else if ( self->seekable && ( position < self->video_expected || position - self->video_expected >= 12 || self->last_position < 0 ) )
                {
-                       if ( use_new_seek && self->last_position == POSITION_INITIAL )
-                       {
-                               // find first key frame
-                               int ret = 0;
-                               int toscan = 100;
-                               AVPacket pkt;
-
-                               while ( ret >= 0 && toscan-- > 0 )
-                               {
-                                       ret = av_read_frame( context, &pkt );
-                                       if ( ret >= 0 && ( pkt.flags & PKT_FLAG_KEY ) && pkt.stream_index == self->video_index )
-                                       {
-                                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "first_pts %"PRId64" dts %"PRId64" pts_dts_delta %d\n", pkt.pts, pkt.dts, (int)(pkt.pts - pkt.dts) );
-                                               self->first_pts = pkt.pts;
-                                               toscan = 0;
-                                       }
-                                       av_free_packet( &pkt );
-                               }
-                               // Rewind
-                               av_seek_frame( context, -1, 0, AVSEEK_FLAG_BACKWARD );
-                       }
-
                        // Calculate the timestamp for the requested frame
-                       int64_t timestamp;
-                       if ( use_new_seek )
-                       {
-                               timestamp = ( req_position - 0.1 / source_fps ) /
-                                       ( av_q2d( stream->time_base ) * source_fps );
-                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "pos %"PRId64" pts %"PRId64"\n", req_position, timestamp );
-                               if ( self->first_pts > 0 )
-                                       timestamp += self->first_pts;
-                               else if ( context->start_time != AV_NOPTS_VALUE )
-                                       timestamp += context->start_time;
-                       }
-                       else
-                       {
-                               timestamp = ( int64_t )( ( double )req_position / source_fps * AV_TIME_BASE + 0.5 );
-                               if ( context->start_time != AV_NOPTS_VALUE )
-                                       timestamp += context->start_time;
-                       }
-                       if ( must_decode )
-                               timestamp -= AV_TIME_BASE;
+                       int64_t timestamp = req_position / ( av_q2d( self->video_time_base ) * source_fps );
+                       if ( req_position <= 0 )
+                               timestamp = 0;
+                       else if ( self->first_pts != AV_NOPTS_VALUE )
+                               timestamp += self->first_pts;
+                       else if ( context->start_time != AV_NOPTS_VALUE )
+                               timestamp += context->start_time;
+                       if ( preseek && av_q2d( self->video_time_base ) != 0 )
+                               timestamp -= 2 / av_q2d( self->video_time_base );
                        if ( timestamp < 0 )
                                timestamp = 0;
                        mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "seeking timestamp %"PRId64" position %d expected %d last_pos %"PRId64"\n",
                                timestamp, position, self->video_expected, self->last_position );
 
                        // Seek to the timestamp
-                       if ( use_new_seek )
+                       // NOTE: reopen_video is disabled at this time because it is causing trouble with A/V sync.
+                       if ( 1 || req_position > 0 || self->last_position <= 0 )
                        {
                                codec_context->skip_loop_filter = AVDISCARD_NONREF;
                                av_seek_frame( context, self->video_index, timestamp, AVSEEK_FLAG_BACKWARD );
-                       }
-                       else if ( req_position > 0 || self->last_position <= 0 )
-                       {
-                               av_seek_frame( context, -1, timestamp, AVSEEK_FLAG_BACKWARD );
+
+                               // flush any pictures still in decode buffer
+                               avcodec_flush_buffers( codec_context );
                        }
                        else
                        {
@@ -998,12 +1154,6 @@ static int seek_video( producer_avformat self, mlt_position position,
                        self->current_position = POSITION_INVALID;
                        self->last_position = POSITION_INVALID;
                        av_freep( &self->av_frame );
-
-                       if ( use_new_seek )
-                       {
-                               // flush any pictures still in decode buffer
-                               avcodec_flush_buffers( codec_context );
-                       }
                }
        }
        return paused;
@@ -1035,8 +1185,12 @@ static void get_audio_streams_info( producer_avformat self )
                        AVCodec *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( );
+                       pthread_mutex_lock( &self->open_mutex );
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
+                       if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 )
+#else
                        if ( codec && avcodec_open( codec_context, codec ) >= 0 )
+#endif
                        {
                                self->audio_streams++;
                                self->audio_max_stream = i;
@@ -1047,7 +1201,7 @@ static void get_audio_streams_info( producer_avformat self )
                                        self->max_frequency = codec_context->sample_rate;
                                avcodec_close( codec_context );
                        }
-                       avformat_unlock( );
+                       pthread_mutex_unlock( &self->open_mutex );
                }
        }
        mlt_log_verbose( NULL, "[producer avformat] audio: total_streams %d max_stream %d total_channels %d max_channels %d\n",
@@ -1095,7 +1249,7 @@ static void set_luma_transfer( struct SwsContext *context, int colorspace, int u
 #endif
 }
 
-static mlt_image_format pick_format( enum PixelFormat pix_fmt )
+static mlt_image_format pick_pix_format( enum PixelFormat pix_fmt )
 {
        switch ( pix_fmt )
        {
@@ -1121,12 +1275,40 @@ static mlt_image_format pick_format( enum PixelFormat pix_fmt )
        }
 }
 
-static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
-       mlt_image_format *format, int width, int height, int colorspace )
+static mlt_audio_format pick_audio_format( int sample_fmt )
+{
+       switch ( sample_fmt )
+       {
+       // interleaved
+       case AV_SAMPLE_FMT_U8:
+               return mlt_audio_u8;
+       case AV_SAMPLE_FMT_S16:
+               return mlt_audio_s16;
+       case AV_SAMPLE_FMT_S32:
+               return mlt_audio_s32le;
+       case AV_SAMPLE_FMT_FLT:
+               return mlt_audio_f32le;
+       // planar - this producer converts planar to interleaved
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+       case AV_SAMPLE_FMT_U8P:
+               return mlt_audio_u8;
+       case AV_SAMPLE_FMT_S16P:
+               return mlt_audio_s16;
+       case AV_SAMPLE_FMT_S32P:
+               return mlt_audio_s32le;
+       case AV_SAMPLE_FMT_FLTP:
+               return mlt_audio_f32le;
+#endif
+       default:
+               return mlt_audio_none;
+       }
+}
+
+static void convert_image( producer_avformat self, AVFrame *frame, uint8_t *buffer, int pix_fmt,
+       mlt_image_format *format, int width, int height, uint8_t **alpha )
 {
 #ifdef SWSCALE
-       int full_range = -1;
-       int flags = SWS_BILINEAR | SWS_ACCURATE_RND;
+       int flags = SWS_BICUBIC | SWS_ACCURATE_RND;
 
 #ifdef USE_MMX
        flags |= SWS_CPU_CAPS_MMX;
@@ -1135,6 +1317,25 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
        flags |= SWS_CPU_CAPS_MMX2;
 #endif
 
+       // extract alpha from planar formats
+       if ( ( pix_fmt == PIX_FMT_YUVA420P
+#if defined(FFUDIV) && LIBAVUTIL_VERSION_INT >= ((51<<16)+(35<<8)+101)
+                       || pix_fmt == PIX_FMT_YUVA444P
+#endif
+                       ) &&
+               *format != mlt_image_rgb24a && *format != mlt_image_opengl &&
+               frame->data[3] && frame->linesize[3] )
+       {
+               int i;
+               uint8_t *src, *dst;
+
+               dst = *alpha = mlt_pool_alloc( width * height );
+               src = frame->data[3];
+
+               for ( i = 0; i < height; dst += width, src += frame->linesize[3], i++ )
+                       memcpy( dst, src, FFMIN( width, frame->linesize[3] ) );
+       }
+
        if ( *format == mlt_image_yuv420p )
        {
                struct SwsContext *context = sws_getContext( width, height, pix_fmt,
@@ -1146,7 +1347,7 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
                output.linesize[0] = width;
                output.linesize[1] = width >> 1;
                output.linesize[2] = width >> 1;
-               set_luma_transfer( context, colorspace, full_range );
+               set_luma_transfer( context, self->colorspace, -1 );
                sws_scale( context, (const uint8_t* const*) frame->data, frame->linesize, 0, height,
                        output.data, output.linesize);
                sws_freeContext( context );
@@ -1157,7 +1358,7 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
                        width, height, PIX_FMT_RGB24, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
                AVPicture output;
                avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
-               set_luma_transfer( context, colorspace, full_range );
+               set_luma_transfer( context, self->colorspace, self->full_luma );
                sws_scale( context, (const uint8_t* const*) frame->data, frame->linesize, 0, height,
                        output.data, output.linesize);
                sws_freeContext( context );
@@ -1168,7 +1369,7 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
                        width, height, PIX_FMT_RGBA, flags | SWS_FULL_CHR_H_INT, NULL, NULL, NULL);
                AVPicture output;
                avpicture_fill( &output, buffer, PIX_FMT_RGBA, width, height );
-               set_luma_transfer( context, colorspace, full_range );
+               set_luma_transfer( context, self->colorspace, self->full_luma );
                sws_scale( context, (const uint8_t* const*) frame->data, frame->linesize, 0, height,
                        output.data, output.linesize);
                sws_freeContext( context );
@@ -1179,7 +1380,7 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
                        width, height, PIX_FMT_YUYV422, flags | SWS_FULL_CHR_H_INP, NULL, NULL, NULL);
                AVPicture output;
                avpicture_fill( &output, buffer, PIX_FMT_YUYV422, width, height );
-               set_luma_transfer( context, colorspace, full_range );
+               set_luma_transfer( context, self->colorspace, -1 );
                sws_scale( context, (const uint8_t* const*) frame->data, frame->linesize, 0, height,
                        output.data, output.linesize);
                sws_freeContext( context );
@@ -1202,7 +1403,7 @@ static void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt,
                avpicture_fill( &output, buffer, PIX_FMT_RGB24, width, height );
                img_convert( &output, PIX_FMT_RGB24, (AVPicture *)frame, pix_fmt, width, height );
        }
-       else if ( format == mlt_image_rgb24a || format == mlt_image_opengl )
+       else if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl )
        {
                AVPicture output;
                avpicture_fill( &output, buffer, PIX_FMT_RGB32, width, height );
@@ -1226,6 +1427,10 @@ static int allocate_buffer( mlt_frame frame, AVCodecContext *codec_context, uint
 
        if ( codec_context->width == 0 || codec_context->height == 0 )
                return size;
+
+       if ( *format == mlt_image_glsl )
+               *format = pick_pix_format( codec_context->pix_fmt );
+
        *width = codec_context->width;
        *height = codec_context->height;
        size = mlt_image_format_size( *format, *width, *height, NULL );
@@ -1251,7 +1456,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        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" );
+       mlt_position position = mlt_frame_original_position( frame );
 
        // Get the producer properties
        mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
@@ -1267,15 +1472,48 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        // Get codec context
        AVCodecContext *codec_context = stream->codec;
 
+       uint8_t *alpha = NULL;
+       int got_picture = 0;
+       int image_size = 0;
+
        // Get the image cache
-       if ( ! self->image_cache && ! mlt_properties_get_int( properties, "noimagecache" ) )
-               self->image_cache = mlt_cache_init();
+       if ( ! self->image_cache )
+       {
+               // if cache size supplied by environment variable
+               int cache_supplied = getenv( "MLT_AVFORMAT_CACHE" ) != NULL;
+               int cache_size = cache_supplied? atoi( getenv( "MLT_AVFORMAT_CACHE" ) ) : 0;
+
+               // cache size supplied via property
+               if ( mlt_properties_get( properties, "cache" ) )
+               {
+                       cache_supplied = 1;
+                       cache_size = mlt_properties_get_int( properties, "cache" );
+               }
+               if ( mlt_properties_get_int( properties, "noimagecache" ) )
+                       cache_size = 0;
+               // create cache if not disabled
+               if ( !cache_supplied || cache_size > 0 )
+                       self->image_cache = mlt_cache_init();
+               // set cache size if supplied
+               if ( self->image_cache && cache_supplied )
+                       mlt_cache_set_size( self->image_cache, cache_size );
+       }
        if ( self->image_cache )
        {
-               mlt_cache_item item = mlt_cache_get( self->image_cache, (void*) position );
-               uint8_t *original = mlt_cache_item_data( item, (int*) format );
+               mlt_frame original = mlt_cache_get_frame( self->image_cache, position );
                if ( original )
                {
+                       mlt_properties orig_props = MLT_FRAME_PROPERTIES( original );
+                       int size = 0;
+
+                       *buffer = mlt_properties_get_data( orig_props, "alpha", &size );
+                       if (*buffer)
+                               mlt_frame_set_alpha( frame, *buffer, size, NULL );
+                       *buffer = mlt_properties_get_data( orig_props, "image", &size );
+                       mlt_frame_set_image( frame, *buffer, size, NULL );
+                       mlt_properties_set_data( frame_properties, "avformat.image_cache", original, 0, (mlt_destructor) mlt_frame_close, NULL );
+                       *format = mlt_properties_get_int( orig_props, "format" );
+
                        // Set the resolution
                        *width = codec_context->width;
                        *height = codec_context->height;
@@ -1284,34 +1522,11 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                        if ( *height == 1088 && mlt_profile_dar( mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ) ) == 16.0/9.0 )
                                *height = 1080;
 
-                       // Cache hit
-                       int size = mlt_image_format_size( *format, *width, *height, NULL );
-                       if ( writable )
-                       {
-                               *buffer = mlt_pool_alloc( size );
-                               mlt_frame_set_image( frame, *buffer, size, mlt_pool_release );
-                               memcpy( *buffer, original, size );
-                               mlt_cache_item_close( item );
-                       }
-                       else
-                       {
-                               *buffer = original;
-                               mlt_properties_set_data( frame_properties, "avformat.image_cache", item, 0, ( mlt_destructor )mlt_cache_item_close, NULL );
-                               mlt_frame_set_image( frame, *buffer, size, NULL );
-                       }
-                       self->got_picture = 1;
-
+                       got_picture = 1;
                        goto exit_get_image;
                }
        }
        // Cache miss
-       int image_size = 0;
-
-       // Packet
-       AVPacket pkt;
-
-       // 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, "meta.media.frame_rate_num" ) /
@@ -1329,33 +1544,31 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                  strcmp( codec_context->codec->name, "mjpeg" ) &&
                                  strcmp( codec_context->codec->name, "rawvideo" ) );
 
-       // Turn on usage of new seek API and PTS for seeking
-       int use_new_seek = self->seekable &&
-               codec_context->codec_id == CODEC_ID_H264 && !strcmp( context->iformat->name, "mpegts" );
-       if ( mlt_properties_get( properties, "new_seek" ) )
-               use_new_seek = mlt_properties_get_int( properties, "new_seek" );
        double delay = mlt_properties_get_double( properties, "video_delay" );
 
        // Seek if necessary
-       int paused = seek_video( self, position, req_position, must_decode, use_new_seek, &ignore );
+       const char *interp = mlt_properties_get( frame_properties, "rescale.interp" );
+       int preseek = must_decode
+#if defined(FFUDIV) && LIBAVFORMAT_VERSION_INT >= ((53<<16)+(24<<8)+2)
+               && ( interp && strcmp( interp, "nearest" ) )
+#endif
+               && codec_context->has_b_frames;
+       int paused = seek_video( self, position, req_position, preseek );
 
        // Seek might have reopened the file
        context = self->video_format;
        stream = context->streams[ self->video_index ];
        codec_context = stream->codec;
-
        if ( *format == mlt_image_none ||
                        codec_context->pix_fmt == PIX_FMT_ARGB ||
                        codec_context->pix_fmt == PIX_FMT_RGBA ||
                        codec_context->pix_fmt == PIX_FMT_ABGR ||
                        codec_context->pix_fmt == PIX_FMT_BGRA )
-               *format = pick_format( codec_context->pix_fmt );
+               *format = pick_pix_format( codec_context->pix_fmt );
 
        // Duplicate the last image if necessary
-       if ( self->av_frame && self->av_frame->linesize[0] && self->got_picture
-                && ( paused
-                         || self->current_position == req_position
-                         || ( !use_new_seek && self->current_position > req_position ) ) )
+       if ( self->av_frame && self->av_frame->linesize[0]
+                && ( paused || self->current_position >= req_position ) )
        {
                // Duplicate it
                if ( ( image_size = allocate_buffer( frame, codec_context, buffer, format, width, height ) ) )
@@ -1373,25 +1586,21 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                picture.linesize[0] = codec_context->width;
                                picture.linesize[1] = codec_context->width / 2;
                                picture.linesize[2] = codec_context->width / 2;
-                               convert_image( (AVFrame*) &picture, *buffer,
-                                       PIX_FMT_YUV420P, format, *width, *height, self->colorspace );
+                               convert_image( self, (AVFrame*) &picture, *buffer,
+                                       PIX_FMT_YUV420P, format, *width, *height, &alpha );
                        }
                        else
 #endif
-                       convert_image( self->av_frame, *buffer, codec_context->pix_fmt,
-                               format, *width, *height, self->colorspace );
+                       convert_image( self, self->av_frame, *buffer, codec_context->pix_fmt,
+                               format, *width, *height, &alpha );
+                       got_picture = 1;
                }
-               else
-                       mlt_frame_get_image( frame, buffer, format, width, height, writable );
        }
        else
        {
                int ret = 0;
                int64_t int_position = 0;
                int decode_errors = 0;
-               int got_picture = 0;
-
-               av_init_packet( &pkt );
 
                // Construct an AVFrame for YUV422 conversion
                if ( !self->av_frame )
@@ -1400,22 +1609,25 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                while( ret >= 0 && !got_picture )
                {
                        // Read a packet
+                       if ( self->pkt.stream_index == self->video_index )
+                               av_free_packet( &self->pkt );
+                       av_init_packet( &self->pkt );
                        pthread_mutex_lock( &self->packets_mutex );
                        if ( mlt_deque_count( self->vpackets ) )
                        {
                                AVPacket *tmp = (AVPacket*) mlt_deque_pop_front( self->vpackets );
-                               pkt = *tmp;
+                               self->pkt = *tmp;
                                free( tmp );
                        }
                        else
                        {
-                               ret = av_read_frame( context, &pkt );
-                               if ( ret >= 0 && !self->seekable && pkt.stream_index == self->audio_index )
+                               ret = av_read_frame( context, &self->pkt );
+                               if ( ret >= 0 && !self->seekable && self->pkt.stream_index == self->audio_index )
                                {
-                                       if ( !av_dup_packet( &pkt ) )
+                                       if ( !av_dup_packet( &self->pkt ) )
                                        {
                                                AVPacket *tmp = malloc( sizeof(AVPacket) );
-                                               *tmp = pkt;
+                                               *tmp = self->pkt;
                                                mlt_deque_push_back( self->apackets, tmp );
                                        }
                                }
@@ -1423,53 +1635,30 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                        pthread_mutex_unlock( &self->packets_mutex );
 
                        // We only deal with video from the selected video_index
-                       if ( ret >= 0 && pkt.stream_index == self->video_index && pkt.size > 0 )
+                       if ( ret >= 0 && self->pkt.stream_index == self->video_index && self->pkt.size > 0 )
                        {
-                               // Determine time code of the packet
-                               if ( use_new_seek )
+                               int64_t pts = best_pts( self, self->pkt.pts, self->pkt.dts );
+                               if ( pts != AV_NOPTS_VALUE )
                                {
-                                       int64_t pts = pkt.pts;
-                                       if ( self->first_pts > 0 )
+                                       if ( !self->seekable && self->first_pts == AV_NOPTS_VALUE )
+                                               self->first_pts = pts;
+                                       if ( self->first_pts != AV_NOPTS_VALUE )
                                                pts -= self->first_pts;
                                        else if ( context->start_time != AV_NOPTS_VALUE )
                                                pts -= context->start_time;
-                                       int_position = ( int64_t )( ( av_q2d( stream->time_base ) * pts + delay ) * source_fps + 0.1 );
-                                       if ( pkt.pts == AV_NOPTS_VALUE )
-                                       {
-                                               self->invalid_pts_counter++;
-                                               if ( self->invalid_pts_counter > 20 )
-                                               {
-                                                       mlt_log_panic( MLT_PRODUCER_SERVICE(producer), "\ainvalid PTS; DISABLING NEW_SEEK!\n" );
-                                                       mlt_properties_set_int( properties, "new_seek", 0 );
-                                                       int_position = req_position;
-                                                       use_new_seek = 0;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               self->invalid_pts_counter = 0;
-                                       }
-                                       mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "pkt.pts %"PRId64" req_pos %"PRId64" cur_pos %"PRId64" pkt_pos %"PRId64"\n",
-                                               pkt.pts, req_position, self->current_position, int_position );
+                                       int_position = ( int64_t )( ( av_q2d( self->video_time_base ) * pts + delay ) * source_fps + 0.5 );
+                                       if ( int_position == self->last_position )
+                                               int_position = self->last_position + 1;
                                }
-                               else
+                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer),
+                                       "V pkt.pts %"PRId64" pkt.dts %"PRId64" req_pos %"PRId64" cur_pos %"PRId64" pkt_pos %"PRId64"\n",
+                                       self->pkt.pts, self->pkt.dts, req_position, self->current_position, int_position );
+
+                               // Make a dumb assumption on streams that contain wild timestamps
+                               if ( abs( req_position - int_position ) > 999 )
                                {
-                                       if ( pkt.dts != AV_NOPTS_VALUE )
-                                       {
-                                               int_position = ( int64_t )( ( av_q2d( stream->time_base ) * pkt.dts + delay ) * source_fps + 0.5 );
-                                               if ( context->start_time != AV_NOPTS_VALUE )
-                                                       int_position -= ( int64_t )( context->start_time * source_fps / AV_TIME_BASE + 0.5 );
-                                               if ( int_position == self->last_position )
-                                                       int_position = self->last_position + 1;
-                                       }
-                                       mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "pkt.dts %"PRId64" req_pos %"PRId64" cur_pos %"PRId64" pkt_pos %"PRId64"\n",
-                                               pkt.dts, req_position, self->current_position, int_position );
-                                       // Make a dumb assumption on streams that contain wild timestamps
-                                       if ( abs( req_position - int_position ) > 999 )
-                                       {
-                                               int_position = req_position;
-                                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), " WILD TIMESTAMP!" );
-                                       }
+                                       int_position = req_position;
+                                       mlt_log_warning( MLT_PRODUCER_SERVICE(producer), " WILD TIMESTAMP!\n" );
                                }
                                self->last_position = int_position;
 
@@ -1486,13 +1675,13 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                                self->vdpau->is_decoded = 0;
                                        }
 #endif
-                                       codec_context->reordered_opaque = pkt.pts;
+                                       codec_context->reordered_opaque = int_position;
                                        if ( int_position >= req_position )
                                                codec_context->skip_loop_filter = AVDISCARD_NONE;
 #if (LIBAVCODEC_VERSION_INT >= ((52<<16)+(26<<8)+0))
-                                       ret = avcodec_decode_video2( codec_context, self->av_frame, &got_picture, &pkt );
+                                       ret = avcodec_decode_video2( codec_context, self->av_frame, &got_picture, &self->pkt );
 #else
-                                       ret = avcodec_decode_video( codec_context, self->av_frame, &got_picture, pkt.data, pkt.size );
+                                       ret = avcodec_decode_video( codec_context, self->av_frame, &got_picture, self->pkt.data, self->pkt.size );
 #endif
                                        // Note: decode may fail at the beginning of MPEGfile (B-frames referencing before first I-frame), so allow a few errors.
                                        if ( ret < 0 )
@@ -1508,34 +1697,26 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
 
                                if ( got_picture )
                                {
-                                       if ( use_new_seek )
+                                       // Get position of reordered frame
+                                       int_position = self->av_frame->reordered_opaque;
+#if (LIBAVCODEC_VERSION_INT >= ((52<<16)+(106<<8)+0))
+                                       pts = best_pts( self, self->av_frame->pkt_pts, self->av_frame->pkt_dts );
+                                       if ( pts != AV_NOPTS_VALUE )
                                        {
-                                               // Determine time code of the packet
-                                               int64_t pts = self->av_frame->reordered_opaque;
-                                               if ( self->first_pts > 0 )
+                                               if ( self->first_pts != AV_NOPTS_VALUE )
                                                        pts -= self->first_pts;
                                                else if ( context->start_time != AV_NOPTS_VALUE )
                                                        pts -= context->start_time;
-                                               int_position = ( int64_t )( av_q2d( stream->time_base) * pts * source_fps + 0.1 );
-                                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "got frame %"PRId64", key %d\n", int_position, self->av_frame->key_frame );
+                                               int_position = ( int64_t )( ( av_q2d( self->video_time_base ) * pts + delay ) * source_fps + 0.5 );
                                        }
-                                       // Handle ignore
+#endif
+
                                        if ( int_position < req_position )
-                                       {
-                                               ignore = 0;
                                                got_picture = 0;
-                                       }
                                        else if ( int_position >= req_position )
-                                       {
-                                               ignore = 0;
                                                codec_context->skip_loop_filter = AVDISCARD_NONE;
-                                       }
-                                       else if ( ignore -- )
-                                       {
-                                               got_picture = 0;
-                                       }
                                }
-                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), " got_pic %d key %d\n", got_picture, pkt.flags & PKT_FLAG_KEY );
+                               mlt_log_debug( MLT_PRODUCER_SERVICE(producer), " got_pic %d key %d\n", got_picture, self->pkt.flags & PKT_FLAG_KEY );
                        }
 
                        // Now handle the picture if we have one
@@ -1568,8 +1749,8 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                                        VdpStatus status = vdp_surface_get_bits( render->surface, dest_format, planes, pitches );
                                                        if ( status == VDP_STATUS_OK )
                                                        {
-                                                               convert_image( self->av_frame, *buffer, PIX_FMT_YUV420P,
-                                                                       format, *width, *height, self->colorspace );
+                                                               convert_image( self, self->av_frame, *buffer, PIX_FMT_YUV420P,
+                                                                       format, *width, *height, &alpha );
                                                        }
                                                        else
                                                        {
@@ -1585,31 +1766,38 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                        }
                                        else
 #endif
-                                       convert_image( self->av_frame, *buffer, codec_context->pix_fmt,
-                                               format, *width, *height, self->colorspace );
+                                       convert_image( self, self->av_frame, *buffer, codec_context->pix_fmt,
+                                               format, *width, *height, &alpha );
                                        self->top_field_first |= self->av_frame->top_field_first;
                                        self->current_position = int_position;
-                                       self->got_picture = 1;
                                }
                                else
                                {
                                        got_picture = 0;
                                }
                        }
-                       if ( self->seekable || pkt.stream_index != self->audio_index )
-                               av_free_packet( &pkt );
+
+                       // Free packet data if not video and not live audio packet
+                       if ( self->pkt.stream_index != self->video_index &&
+                                !( !self->seekable && self->pkt.stream_index == self->audio_index ) )
+                               av_free_packet( &self->pkt );
                }
        }
 
-       if ( self->got_picture && image_size > 0 && self->image_cache )
+       // set alpha
+       if ( alpha )
+               mlt_frame_set_alpha( frame, alpha, (*width) * (*height), mlt_pool_release );
+
+       if ( image_size > 0 && self->image_cache )
        {
-               // Copy buffer to image cache   
-               uint8_t *image = mlt_pool_alloc( image_size );
-               memcpy( image, *buffer, image_size );
-               mlt_cache_put( self->image_cache, (void*) position, image, *format, mlt_pool_release );
+               mlt_properties_set_int( frame_properties, "format", *format );
+               mlt_cache_put_frame( self->image_cache, frame );
        }
+
        // Try to duplicate last image if there was a decoding failure
-       else if ( !image_size && self->av_frame && self->av_frame->linesize[0] )
+       // TODO: with multithread decoding a partial frame decoding resulting
+       // in failure also resets av_frame making test below fail.
+       if ( !image_size && self->av_frame && self->av_frame->linesize[0] )
        {
                // Duplicate it
                if ( ( image_size = allocate_buffer( frame, codec_context, buffer, format, width, height ) ) )
@@ -1627,17 +1815,15 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                picture.linesize[0] = codec_context->width;
                                picture.linesize[1] = codec_context->width / 2;
                                picture.linesize[2] = codec_context->width / 2;
-                               convert_image( (AVFrame*) &picture, *buffer,
-                                       PIX_FMT_YUV420P, format, *width, *height, self->colorspace );
+                               convert_image( self, (AVFrame*) &picture, *buffer,
+                                       PIX_FMT_YUV420P, format, *width, *height, &alpha );
                        }
                        else
 #endif
-                       convert_image( self->av_frame, *buffer, codec_context->pix_fmt,
-                               format, *width, *height, self->colorspace );
-                       self->got_picture = 1;
+                       convert_image( self, self->av_frame, *buffer, codec_context->pix_fmt,
+                               format, *width, *height, &alpha );
+                       got_picture = 1;
                }
-               else
-                       mlt_frame_get_image( frame, buffer, format, width, height, writable );
        }
 
        // Regardless of speed, we expect to get the next frame (cos we ain't too bright)
@@ -1665,7 +1851,12 @@ exit_get_image:
        mlt_properties_set_int( properties, "meta.media.progressive", mlt_properties_get_int( frame_properties, "progressive" ) );
        mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) );
 
-       return !self->got_picture;
+       // If we already have RGB, then the full range processing either happened already
+       // or does not apply (RGB source).
+       if ( *format == mlt_image_rgb24 || *format == mlt_image_rgb24a || *format == mlt_image_opengl )
+               mlt_properties_set( frame_properties, "force_full_luma", NULL );
+
+       return !got_picture;
 }
 
 /** Process properties as AVOptions and apply to AV context obj
@@ -1678,11 +1869,17 @@ static void apply_properties( void *obj, mlt_properties properties, int flags )
        for ( i = 0; i < count; i++ )
        {
                const char *opt_name = mlt_properties_get_name( properties, i );
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(10<<8)+0)
+               const AVOption *opt = av_opt_find( obj, opt_name, NULL, flags, flags );
+#else
                const AVOption *opt = av_find_opt( obj, opt_name, NULL, flags, flags );
+#endif
                if ( opt_name && mlt_properties_get( properties, opt_name ) )
                {
                        if ( opt )
-#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(12<<8)+0)
+                               av_opt_set( obj, opt_name, mlt_properties_get( properties, opt_name), 0 );
+#elif 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 );
@@ -1734,8 +1931,12 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
                        codec_context->thread_count = thread_count;
 
                // If we don't have a codec and we can't initialise it, we can't do much more...
-               avformat_lock( );
+               pthread_mutex_lock( &self->open_mutex );
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
+               if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 )
+#else
                if ( codec && avcodec_open( codec_context, codec ) >= 0 )
+#endif
                {
                        // Now store the codec with its destructor
                        self->video_codec = codec_context;
@@ -1744,21 +1945,24 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
                {
                        // Remember that we can't use this later
                        self->video_index = -1;
-                       avformat_unlock( );
+                       pthread_mutex_unlock( &self->open_mutex );
                        return 0;
                }
-               avformat_unlock( );
+               pthread_mutex_unlock( &self->open_mutex );
 
                // Process properties as AVOptions
                apply_properties( codec_context, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(122<<8)+0)
                if ( codec->priv_class && codec_context->priv_data )
                        apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
 #endif
 
                // Reset some image properties
-               mlt_properties_set_int( properties, "width", self->video_codec->width );
-               mlt_properties_set_int( properties, "height", self->video_codec->height );
+               if ( self->video_codec )
+               {
+                       mlt_properties_set_int( properties, "width", self->video_codec->width );
+                       mlt_properties_set_int( properties, "height", self->video_codec->height );
+               }
                // For DV, we'll just use the saved aspect ratio
                if ( codec_context->codec_id != CODEC_ID_DVVIDEO )
                        get_aspect_ratio( properties, stream, self->video_codec, NULL );
@@ -1767,14 +1971,6 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
                double source_fps = (double) self->video_codec->time_base.den /
                                                                   ( self->video_codec->time_base.num == 0 ? 1 : self->video_codec->time_base.num );
                
-               if ( mlt_properties_get( properties, "force_fps" ) )
-               {
-                       source_fps = mlt_properties_get_double( properties, "force_fps" );
-                       stream->time_base = av_d2q( source_fps, 1024 );
-                       mlt_properties_set_int( properties, "meta.media.frame_rate_num", stream->time_base.num );
-                       mlt_properties_set_int( properties, "meta.media.frame_rate_den", stream->time_base.den );
-               }
-               else
                {
                        // If the muxer reports a frame rate different than the codec
 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(42<<8)+0)
@@ -1805,7 +2001,6 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
 #endif
                                mlt_properties_set_int( properties, "meta.media.frame_rate_num", frame_rate.num );
                                mlt_properties_set_int( properties, "meta.media.frame_rate_den", frame_rate.den );
-                               source_fps = av_q2d( frame_rate );
                        }
                        else
                        {
@@ -1815,12 +2010,16 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
                                mlt_properties_set_int( properties, "meta.media.frame_rate_den", frame_rate.den );
                        }
                }
-
-               // source_fps is deprecated in favor of meta.media.frame_rate_num and .frame_rate_den
-               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( self->parent ) );
+               self->video_time_base = stream->time_base;
+               if ( mlt_properties_get( properties, "force_fps" ) )
+               {
+                       double source_fps = mlt_properties_get_double( properties, "force_fps" );
+                       AVRational fps = av_d2q( source_fps, 1024 );
+                       self->video_time_base.num *= mlt_properties_get_int( properties, "meta.media.frame_rate_num" ) * fps.den;
+                       self->video_time_base.den *= mlt_properties_get_int( properties, "meta.media.frame_rate_den" ) * fps.num;
+                       mlt_properties_set_int( properties, "meta.media.frame_rate_num", fps.num );
+                       mlt_properties_set_int( properties, "meta.media.frame_rate_den", fps.den );
+               }
 
                // Set the YUV colorspace from override or detect
                self->colorspace = mlt_properties_get_int( properties, "force_colorspace" );
@@ -1848,6 +2047,15 @@ static int video_codec_init( producer_avformat self, int index, mlt_properties p
 #endif
                // Let apps get chosen colorspace
                mlt_properties_set_int( properties, "meta.media.colorspace", self->colorspace );
+
+               self->full_luma = -1;
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(72<<8)+2)
+               mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "color_range %d\n", codec_context->color_range );
+               if ( codec_context->color_range == AVCOL_RANGE_JPEG )
+                       self->full_luma = 1;
+#endif
+               if ( mlt_properties_get( properties, "set.force_full_luma" ) )
+                       self->full_luma = mlt_properties_get_int( properties, "set.force_full_luma" );
        }
        return self->video_codec && self->video_index > -1;
 }
@@ -1898,11 +2106,11 @@ static void producer_set_up_video( producer_avformat self, mlt_frame frame )
        {
                // Reset the video properties if the index changed
                self->video_index = index;
-               avformat_lock();
+               pthread_mutex_lock( &self->open_mutex );
                if ( self->video_codec )
                        avcodec_close( self->video_codec );
                self->video_codec = NULL;
-               avformat_unlock();
+               pthread_mutex_unlock( &self->open_mutex );
        }
 
        // Get the frame properties
@@ -1919,11 +2127,8 @@ static void producer_set_up_video( producer_avformat self, mlt_frame frame )
                // Set the width and height
                mlt_properties_set_int( frame_properties, "width", self->video_codec->width );
                mlt_properties_set_int( frame_properties, "height", self->video_codec->height );
-               // real_width and real_height are deprecated in favor of meta.media.width and .height
                mlt_properties_set_int( properties, "meta.media.width", self->video_codec->width );
                mlt_properties_set_int( properties, "meta.media.height", self->video_codec->height );
-               mlt_properties_set_int( frame_properties, "real_width", self->video_codec->width );
-               mlt_properties_set_int( frame_properties, "real_height", self->video_codec->height );
                mlt_properties_set_double( frame_properties, "aspect_ratio", aspect_ratio );
                mlt_properties_set_int( frame_properties, "colorspace", self->colorspace );
 
@@ -1931,7 +2136,6 @@ static void producer_set_up_video( producer_avformat self, mlt_frame frame )
                if ( self->video_codec->height == 1088 && mlt_profile_dar( mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ) ) == 16.0/9.0 )
                {
                        mlt_properties_set_int( properties, "meta.media.height", 1080 );
-                       mlt_properties_set_int( frame_properties, "real_height", 1080 );
                }
 
                // Add our image operation
@@ -1945,23 +2149,27 @@ static void producer_set_up_video( producer_avformat self, mlt_frame frame )
        }
 }
 
-static int seek_audio( producer_avformat self, mlt_position position, double timecode, int *ignore )
+static int seek_audio( producer_avformat self, mlt_position position, double timecode )
 {
        int paused = 0;
 
        // Seek if necessary
-       if ( self->seekable && position != self->audio_expected )
+       if ( self->seekable && ( position != self->audio_expected || self->last_position < 0 ) )
        {
+               if ( self->last_position == POSITION_INITIAL )
+               {
+                       int video_index = self->video_index;
+                       if ( video_index == -1 )
+                               video_index = first_video_index( self );
+                       if ( video_index >= 0 )
+                               find_first_pts( self, video_index );
+               }
+
                if ( position + 1 == self->audio_expected )
                {
                        // We're paused - silence required
                        paused = 1;
                }
-               else if ( !self->seekable && position > self->audio_expected && ( position - self->audio_expected ) < 250 )
-               {
-                       // Fast forward - seeking is inefficient for small distances - just ignore following frames
-                       *ignore = position - self->audio_expected;
-               }
                else if ( position < self->audio_expected || position - self->audio_expected >= 12 )
                {
                        AVFormatContext *context = self->audio_format;
@@ -1986,13 +2194,28 @@ static int seek_audio( producer_avformat self, mlt_position position, double tim
 
 static int sample_bytes( AVCodecContext *context )
 {
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(8<<8)+0)
+       return av_get_bytes_per_sample( context->sample_fmt );
+#elif LIBAVCODEC_VERSION_MAJOR >= 53
        return av_get_bits_per_sample_fmt( context->sample_fmt ) / 8;
 #else
        return av_get_bits_per_sample_format( context->sample_fmt ) / 8;
 #endif
 }
 
+static void planar_to_interleaved( uint8_t *dest, uint8_t *src, int samples, int channels, int bytes_per_sample )
+{
+       int s, c;
+       for ( s = 0; s < samples; s++ )
+       {
+               for ( c = 0; c < channels; c++ )
+               {
+                       memcpy( dest, src + ( c * samples + s ) * bytes_per_sample, bytes_per_sample );
+                       dest += bytes_per_sample;
+               }
+       }
+}
+
 static int decode_audio( producer_avformat self, int *ignore, AVPacket pkt, int channels, int samples, double timecode, double fps )
 {
        // Fetch the audio_format
@@ -2060,8 +2283,22 @@ static int decode_audio( producer_avformat self, int *ignore, AVPacket pkt, int
                        }
                        else
                        {
-                               // Straight copy to audio buffer
-                               memcpy( &audio_buffer[ audio_used * codec_context->channels * sizeof_sample ], decode_buffer, data_size );
+                               uint8_t *source = decode_buffer;
+                               uint8_t *dest = &audio_buffer[ audio_used * codec_context->channels * sizeof_sample ];
+                               switch ( codec_context->sample_fmt )
+                               {
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+                               case AV_SAMPLE_FMT_U8P:
+                               case AV_SAMPLE_FMT_S16P:
+                               case AV_SAMPLE_FMT_S32P:
+                               case AV_SAMPLE_FMT_FLTP:
+                                       planar_to_interleaved( dest, source, convert_samples, codec_context->channels, sizeof_sample );
+                                       break;
+#endif
+                               default:
+                                       // Straight copy to audio buffer
+                                       memcpy( dest, decode_buffer, data_size );
+                               }
                                audio_used += convert_samples;
                        }
 
@@ -2080,11 +2317,18 @@ static int decode_audio( producer_avformat self, int *ignore, AVPacket pkt, int
        // Skip this on non-seekable, audio-only inputs.
        if ( pkt.pts >= 0 && ( self->seekable || self->video_format ) && *ignore == 0 && audio_used > samples / 2 )
        {
-               double current_pts = av_q2d( context->streams[ index ]->time_base ) * pkt.pts;
+               int64_t pts = pkt.pts;
+               if ( self->first_pts != AV_NOPTS_VALUE )
+                       pts -= self->first_pts;
+               else if ( context->start_time != AV_NOPTS_VALUE )
+                       pts -= context->start_time;
+               double timebase = av_q2d( context->streams[ index ]->time_base );
+               int64_t int_position = ( int64_t )( timebase * pts * fps + 0.5 );
                int64_t req_position = ( int64_t )( timecode * fps + 0.5 );
-               int64_t int_position = ( int64_t )( current_pts * fps + 0.5 );
-               if ( context->start_time != AV_NOPTS_VALUE )
-                       int_position -= ( int64_t )( fps * context->start_time / AV_TIME_BASE + 0.5 );
+
+               mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent),
+                       "A pkt.pts %"PRId64" pkt.dts %"PRId64" req_pos %"PRId64" cur_pos %"PRId64" pkt_pos %"PRId64"\n",
+                       pkt.pts, pkt.dts, req_position, self->current_position, int_position );
 
                if ( int_position > 0 )
                {
@@ -2093,8 +2337,11 @@ static int decode_audio( producer_avformat self, int *ignore, AVPacket pkt, int
                                *ignore = req_position - int_position;
                        else if ( self->audio_index != INT_MAX && int_position > req_position + 2 )
                                // We are ahead, so seek backwards some more
-                               seek_audio( self, req_position, timecode - 1.0, ignore );
+                               seek_audio( self, req_position, timecode - 1.0 );
                }
+               // Cancel the find_first_pts() in seek_audio()
+               if ( self->video_index == -1 && self->last_position == POSITION_INITIAL )
+                       self->last_position = int_position;
        }
 
        self->audio_used[ index ] = audio_used;
@@ -2112,7 +2359,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        pthread_mutex_lock( &self->audio_mutex );
        
        // Obtain the frame number of this frame
-       mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), "avformat_position" );
+       mlt_position position = mlt_frame_original_position( frame );
 
        // Calculate the real time code
        double real_timecode = producer_time_of_frame( self->parent, position );
@@ -2124,7 +2371,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        int ignore[ MAX_AUDIO_STREAMS ] = { 0 };
 
        // Flag for paused (silence)
-       int paused = seek_audio( self, position, real_timecode, &ignore[0] );
+       int paused = seek_audio( self, position, real_timecode );
 
        // Initialize ignore for all streams from the seek return value
        int i = MAX_AUDIO_STREAMS;
@@ -2142,20 +2389,21 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        if ( self->audio_index == INT_MAX )
        {
                index = 0;
-               index_max = context->nb_streams;
+               index_max = FFMIN( MAX_AUDIO_STREAMS, context->nb_streams );
                *channels = self->total_channels;
                *samples = *samples * FFMAX( self->max_frequency, *frequency ) / *frequency;
                *frequency = FFMAX( self->max_frequency, *frequency );
        }
 
        // Initialize the resamplers and buffers
-       for ( ; index < index_max; index++ )
+       for ( ; index < index_max && index < MAX_AUDIO_STREAMS; index++ )
        {
                // Get codec context
                AVCodecContext *codec_context = self->audio_codec[ index ];
 
                if ( codec_context && !self->audio_buffer[ index ] )
                {
+#if LIBAVCODEC_VERSION_INT < ((54<<16)+(26<<8)+0)
                        // Check for resample and create if necessary
                        if ( codec_context->channels <= 2 )
                        {
@@ -2170,7 +2418,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                                self->audio_resample[ index ] = av_audio_resample_init(
                                        self->audio_index == INT_MAX ? codec_context->channels : *channels,
                                        codec_context->channels, *frequency, codec_context->sample_rate,
-                                       SAMPLE_FMT_S16, codec_context->sample_fmt, 16, 10, 0, 0.8 );
+                                       AV_SAMPLE_FMT_S16, codec_context->sample_fmt, 16, 10, 0, 0.8 );
 #else
                                self->audio_resample[ index ] = audio_resample_init(
                                        self->audio_index == INT_MAX ? codec_context->channels : *channels,
@@ -2178,6 +2426,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
 #endif
                        }
                        else
+#endif
                        {
                                codec_context->request_channels = self->audio_index == INT_MAX ? codec_context->channels : *channels;
                                sizeof_sample = sample_bytes( codec_context );
@@ -2193,7 +2442,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        }
 
        // Get the audio if required
-       if ( !paused )
+       if ( !paused && *frequency > 0 )
        {
                int ret = 0;
                int got_audio = 0;
@@ -2221,7 +2470,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                        {
                                // Check if there is enough audio for all streams
                                got_audio = 1;
-                               for ( index = 0; got_audio && index < context->nb_streams; index++ )
+                               for ( index = 0; got_audio && index < index_max; index++ )
                                        if ( ( self->audio_codec[ index ] && self->audio_used[ index ] < *samples ) || ignore[ index ] )
                                                got_audio = 0;
                                if ( got_audio )
@@ -2253,7 +2502,7 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
 
                        // We only deal with audio from the selected audio index
                        index = pkt.stream_index;
-                       if ( ret >= 0 && pkt.data && pkt.size > 0 && ( index == self->audio_index ||
+                       if ( index < MAX_AUDIO_STREAMS && ret >= 0 && pkt.data && pkt.size > 0 && ( index == self->audio_index ||
                                 ( self->audio_index == INT_MAX && context->streams[ index ]->codec->codec_type == CODEC_TYPE_AUDIO ) ) )
                        {
                                int channels2 = ( self->audio_index == INT_MAX || !self->audio_resample[index] ) ?
@@ -2273,20 +2522,16 @@ static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                        index = self->audio_index;
                        *channels = self->audio_codec[ index ]->channels;
                        *frequency = self->audio_codec[ index ]->sample_rate;
-                       *format = self->audio_codec[ index ]->sample_fmt == SAMPLE_FMT_S32 ? mlt_audio_s32le
-                               : self->audio_codec[ index ]->sample_fmt == SAMPLE_FMT_FLT ? mlt_audio_f32le
-                               : mlt_audio_s16;
+                       *format = pick_audio_format( self->audio_codec[ index ]->sample_fmt );
                        sizeof_sample = sample_bytes( self->audio_codec[ index ] );
                }
                else if ( self->audio_index == INT_MAX )
                {
-                       // This only works if all audio tracks have the same sample format.
                        for ( index = 0; index < index_max; index++ )
                                if ( self->audio_codec[ index ] && !self->audio_resample[ index ] )
                                {
-                                       *format = self->audio_codec[ index ]->sample_fmt == SAMPLE_FMT_S32 ? mlt_audio_s32le
-                                               : self->audio_codec[ index ]->sample_fmt == SAMPLE_FMT_FLT ? mlt_audio_f32le
-                                               : mlt_audio_s16;
+                                       // XXX: This only works if all audio tracks have the same sample format.
+                                       *format = pick_audio_format( self->audio_codec[ index ]->sample_fmt );
                                        sizeof_sample = sample_bytes( self->audio_codec[ index ] );
                                        break;
                                }
@@ -2378,8 +2623,12 @@ static int audio_codec_init( producer_avformat self, int index, mlt_properties p
                AVCodec *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( );
+               pthread_mutex_lock( &self->open_mutex );
+#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
+               if ( codec && avcodec_open2( codec_context, codec, NULL ) >= 0 )
+#else
                if ( codec && avcodec_open( codec_context, codec ) >= 0 )
+#endif
                {
                        // Now store the codec with its destructor
                        if ( self->audio_codec[ index ] )
@@ -2391,11 +2640,11 @@ static int audio_codec_init( producer_avformat self, int index, mlt_properties p
                        // Remember that we can't use self later
                        self->audio_index = -1;
                }
-               avformat_unlock( );
+               pthread_mutex_unlock( &self->open_mutex );
 
                // Process properties as AVOptions
                apply_properties( codec_context, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
-#if LIBAVCODEC_VERSION_MAJOR >= 53
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(122<<8)+0)
                if ( codec && codec->priv_class && codec_context->priv_data )
                        apply_properties( codec_context->priv_data, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
 #endif
@@ -2450,15 +2699,20 @@ static void producer_set_up_audio( producer_avformat self, mlt_frame frame )
                index = self->audio_index;
                mlt_properties_set_int( properties, "audio_index", index );
        }
+       if ( context && index > -1 && index < INT_MAX &&
+                pick_audio_format( context->streams[ index ]->codec->sample_fmt ) == mlt_audio_none )
+       {
+               index = -1;
+       }
 
        // Update the audio properties if the index changed
        if ( context && index > -1 && index != self->audio_index )
        {
-               avformat_lock();
+               pthread_mutex_lock( &self->open_mutex );
                if ( self->audio_codec[ self->audio_index ] )
                        avcodec_close( self->audio_codec[ self->audio_index ] );
                self->audio_codec[ self->audio_index ] = NULL;
-               avformat_unlock();
+               pthread_mutex_unlock( &self->open_mutex );
        }
        if ( self->audio_index != -1 )
                self->audio_index = index;
@@ -2479,10 +2733,10 @@ static void producer_set_up_audio( producer_avformat self, mlt_frame frame )
        else if ( context && index > -1 && audio_codec_init( self, index, properties ) )
        {
                // Set the frame properties
-               if ( index < INT_MAX )
+               if ( index < MAX_AUDIO_STREAMS )
                {
-                       mlt_properties_set_int( frame_properties, "frequency", self->audio_codec[ index ]->sample_rate );
-                       mlt_properties_set_int( frame_properties, "channels", self->audio_codec[ index ]->channels );
+                       mlt_properties_set_int( frame_properties, "audio_frequency", self->audio_codec[ index ]->sample_rate );
+                       mlt_properties_set_int( frame_properties, "audio_channels", self->audio_codec[ index ]->channels );
                }
        }
        if ( context && index > -1 )
@@ -2537,7 +2791,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
        // Set the position of this producer
        mlt_position position = self->seekable ? mlt_producer_frame( producer ) : self->nonseek_position++;
-       mlt_properties_set_position( MLT_FRAME_PROPERTIES( *frame ), "avformat_position", position );
+       mlt_properties_set_position( MLT_FRAME_PROPERTIES( *frame ), "original_position", position );
 
        // Calculate the next timecode
        mlt_producer_prepare_next( producer );
@@ -2550,8 +2804,9 @@ static void producer_avformat_close( producer_avformat self )
        mlt_log_debug( NULL, "producer_avformat_close\n" );
 
        // Cleanup av contexts
+       av_free_packet( &self->pkt );
        av_free( self->av_frame );
-       avformat_lock();
+       pthread_mutex_lock( &self->open_mutex );
        int i;
        for ( i = 0; i < MAX_AUDIO_STREAMS; i++ )
        {
@@ -2567,13 +2822,22 @@ static void producer_avformat_close( producer_avformat self )
                avcodec_close( self->video_codec );
        self->video_codec = NULL;
        // Close the file
+#if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(17<<8)+0)
+       if ( self->dummy_context )
+               avformat_close_input( &self->dummy_context );
+       if ( self->seekable && self->audio_format )
+               avformat_close_input( &self->audio_format );
+       if ( self->video_format )
+               avformat_close_input( &self->video_format );
+#else
        if ( self->dummy_context )
                av_close_input_file( self->dummy_context );
        if ( self->seekable && self->audio_format )
                av_close_input_file( self->audio_format );
        if ( self->video_format )
                av_close_input_file( self->video_format );
-       avformat_unlock();
+#endif
+       pthread_mutex_unlock( &self->open_mutex );
 #ifdef VDPAU
        vdpau_producer_close( self );
 #endif
@@ -2581,9 +2845,13 @@ static void producer_avformat_close( producer_avformat self )
                mlt_cache_close( self->image_cache );
 
        // Cleanup the mutexes
-       pthread_mutex_destroy( &self->audio_mutex );
-       pthread_mutex_destroy( &self->video_mutex );
-       pthread_mutex_destroy( &self->packets_mutex );
+       if ( self->is_mutex_init )
+       {
+               pthread_mutex_destroy( &self->audio_mutex );
+               pthread_mutex_destroy( &self->video_mutex );
+               pthread_mutex_destroy( &self->packets_mutex );
+               pthread_mutex_destroy( &self->open_mutex );
+       }
 
        // Cleanup the packet queues
        AVPacket *pkt;
index 459a590074abd917d1bab96f025c862e46d9205d..f789835397291f9bcb21661447b27eee754962d9 100644 (file)
@@ -2,7 +2,7 @@ schema_version: 0.1
 type: producer
 identifier: avformat
 title: FFmpeg Reader
-version: 1
+version: 2
 copyright: Copyright (C) 2003-2011 Ushodaya Enterprises Limited
 license: LGPL
 language: en
@@ -119,15 +119,19 @@ parameters:
     default: 0
     widget: checkbox
 
-  - identifier: new_seek
-    title: Use new seeking
-    description: >
-      When this is not provided (recommended), it is enabled only for H.264 in
-      MPEG-2 Transport Streams.
+  - identifier: cache
+    title: Number of images cache
     type: integer
-    minimum: 0
-    maximum: 1
-    widget: checkbox
+    description: >
+      By default, this producer caches images to facilitate YADIF deinterlace,
+      which needs previous and next frames. Also, caching helps with frame-
+      stepping within a player. The default number of images cached is supplied
+      by the MLT framework, which is currently 4, but you can override it
+      with this property. You can also disable caching by setting it to 0.
+      If you are using parallel processing with YADIF deinterlacing, then
+      you might need to increase caching to prevent inadvertent backward seeks.
+      One can also set this value globally for all instances of avformat by
+      setting the environment variable MLT_AVFORMAT_CACHE.
 
   - identifier: force_progressive
     title: Force progressive
index b5710b382227c7c97e55c6561e0893133f319a47..a98b1769262d6bec1977eefc040e5465ccafcee9 100644 (file)
@@ -37,7 +37,9 @@ static VdpDecoderCreate        *vdp_decoder_create;
 static VdpDecoderDestroy       *vdp_decoder_destroy;
 static VdpDecoderRender        *vdp_decoder_render;
 
+// TODO: Shouldn't these be protected by a mutex?
 static int vdpau_init_done = 0;
+static int vdpau_supported = 1;
 
 /** VDPAUD functions
 */
@@ -57,6 +59,8 @@ static void vdpau_fini( producer_avformat self )
 
 static int vdpau_init( producer_avformat self )
 {
+       if ( !vdpau_supported )
+               return 0;
        mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_init\n" );
        int success = 0;
        mlt_properties properties = MLT_PRODUCER_PROPERTIES( self->parent );
@@ -70,9 +74,16 @@ static int vdpau_init( producer_avformat self )
        if ( !vdpau_init_done )
        {
                int flags = RTLD_NOW;
-               object = dlopen( "/usr/lib64/libvdpau.so", flags );
+               object = dlopen( "/usr/lib/libvdpau.so", flags );
+#ifdef ARCH_X86_64
                if ( !object )
-                       object = dlopen( "/usr/lib/libvdpau.so", flags );
+                       object = dlopen( "/usr/lib64/libvdpau.so", flags );
+               if ( !object )
+                       object = dlopen( "/usr/lib/x86_64-linux-gnu/libvdpau.so.1", flags );
+#elif ARCH_X86
+               if ( !object )
+                       object = dlopen( "/usr/lib/i386-linux-gnu/libvdpau.so.1", flags );
+#endif
                if ( !object )
                        object = dlopen( "/usr/local/lib/libvdpau.so", flags );
                if ( object )
@@ -80,6 +91,8 @@ static int vdpau_init( producer_avformat self )
                else
                {
                        mlt_log( MLT_PRODUCER_SERVICE(self->parent), MLT_LOG_WARNING, "%s: failed to dlopen libvdpau.so\n  (%s)\n", __FUNCTION__, dlerror() );
+                       // Don't try again.
+                       vdpau_supported = 0;
                        return success;
                }
        }
@@ -152,14 +165,12 @@ static int vdpau_get_buffer( AVCodecContext *codec_context, AVFrame *frame )
                        frame->reordered_opaque = codec_context->reordered_opaque;
                        if ( frame->reference )
                        {
-                               frame->age = self->vdpau->ip_age[0];
                                self->vdpau->ip_age[0] = self->vdpau->ip_age[1] + 1;
                                self->vdpau->ip_age[1] = 1;
                                self->vdpau->b_age++;
                        }
                        else
                        {
-                               frame->age = self->vdpau->b_age;
                                self->vdpau->ip_age[0] ++;
                                self->vdpau->ip_age[1] ++;
                                self->vdpau->b_age = 1;
diff --git a/src/modules/avsync/Makefile b/src/modules/avsync/Makefile
new file mode 100644 (file)
index 0000000..c036290
--- /dev/null
@@ -0,0 +1,38 @@
+CFLAGS += -I../..
+
+LDFLAGS += -L../../framework -lmlt -lm -lpthread
+
+include ../../../config.mak
+
+TARGET = ../libmltavsync$(LIBSUF)
+
+OBJS = factory.o \
+          producer_blipflash.o \
+          consumer_blipflash.o
+
+ASM_OBJS = 
+
+SRCS := $(OBJS:.o=.c)
+
+all:   $(TARGET)
+
+$(TARGET): $(OBJS) $(ASM_OBJS)
+               $(CC) $(SHFLAGS) -o $@ $(OBJS) $(ASM_OBJS) $(LDFLAGS)
+
+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)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/avsync"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/avsync"
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/src/modules/avsync/consumer_blipflash.c b/src/modules/avsync/consumer_blipflash.c
new file mode 100644 (file)
index 0000000..5de8a55
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * consumer_blipflash.c -- a consumer to measure A/V sync from a blip/flash
+ *                         source
+ * Copyright (C) 2013 Brian Matherly
+ * Author: Brian Matherly <pez4brian@yahoo.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
+ */
+
+// mlt Header files
+#include <framework/mlt_consumer.h>
+#include <framework/mlt_frame.h>
+#include <framework/mlt_deque.h>
+
+// System header files
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+// Private constants
+#define SAMPLE_FREQ 48000
+#define FLASH_LUMA_THRESHOLD 150
+#define BLIP_THRESHOLD 0.5
+
+// Private types
+typedef struct
+{
+       int64_t flash_history[2];
+       int flash_history_count;
+       int64_t blip_history[2];
+       int blip_history_count;
+       int blip_in_progress;
+       int samples_since_blip;
+       int blip;
+       int flash;
+       int sample_offset;
+       FILE* out_file;
+       int report_frames;
+} avsync_stats;
+
+// Forward references.
+static int consumer_start( mlt_consumer consumer );
+static int consumer_stop( mlt_consumer consumer );
+static int consumer_is_stopped( mlt_consumer consumer );
+static void *consumer_thread( void *arg );
+static void consumer_close( mlt_consumer consumer );
+
+/** Initialize the consumer.
+*/
+
+mlt_consumer consumer_blipflash_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       // Allocate the consumer
+       mlt_consumer consumer = mlt_consumer_new( profile );
+       mlt_properties consumer_properties = MLT_CONSUMER_PROPERTIES( consumer );
+       avsync_stats* stats = NULL;
+
+       // If memory allocated and initializes without error
+       if ( consumer != NULL )
+       {
+               // Set up start/stop/terminated callbacks
+               consumer->close = consumer_close;
+               consumer->start = consumer_start;
+               consumer->stop = consumer_stop;
+               consumer->is_stopped = consumer_is_stopped;
+
+               stats = mlt_pool_alloc( sizeof( avsync_stats ) );
+               stats->flash_history_count = 0;
+               stats->blip_history_count = 0;
+               stats->blip_in_progress = 0;
+               stats->samples_since_blip = 0;
+               stats->blip = 0;
+               stats->flash = 0;
+               stats->sample_offset = INT_MAX;
+               stats->report_frames = 0;
+               stats->out_file = stdout;
+               if ( arg != NULL )
+               {
+                       FILE* out_file = fopen( arg, "w" );
+                       if ( out_file != NULL )
+                               stats->out_file = out_file;
+               }
+               mlt_properties_set_data( consumer_properties, "_stats", stats, 0, NULL, NULL );
+
+               mlt_properties_set( consumer_properties, "report", "blip" );
+       }
+
+       // Return this
+       return consumer;
+}
+
+/** Start the consumer.
+*/
+
+static int consumer_start( mlt_consumer consumer )
+{
+       // Get the properties
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+
+       // 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, consumer );
+       }
+       return 0;
+}
+
+/** Stop the consumer.
+*/
+
+static int consumer_stop( mlt_consumer consumer )
+{
+       // Get the properties
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+
+       // 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
+               if ( thread )
+                       pthread_join( *thread, NULL );
+       }
+
+       return 0;
+}
+
+/** Determine if the consumer is stopped.
+*/
+
+static int consumer_is_stopped( mlt_consumer consumer )
+{
+       // Get the properties
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+       return !mlt_properties_get_int( properties, "_running" );
+}
+
+static void detect_flash( mlt_frame frame, mlt_position pos, double fps, avsync_stats* stats )
+{
+       int width = 0;
+       int height = 0;
+       mlt_image_format format = mlt_image_yuv422;
+       uint8_t* image = NULL;
+       int error = mlt_frame_get_image( frame, &image, &format, &width, &height, 0 );
+
+       if ( !error && format == mlt_image_yuv422 && image != NULL )
+       {
+               int i, j = 0;
+               int y_accumulator = 0;
+
+               // Add up the luma values from 4 samples in 4 different quadrants.
+               for( i = 1; i < 3; i++ )
+               {
+                       int x = ( width / 3 ) * i;
+                       x = x - x % 2; // Make sure this is a luma sample
+                       for( j = 1; j < 3; j++ )
+                       {
+                               int y = ( height / 3 ) * j;
+                               y_accumulator += image[ y * height * 2 + x * 2 ];
+                       }
+               }
+               // If the average luma value is > 150, assume it is a flash.
+               stats->flash = ( y_accumulator / 4 ) > FLASH_LUMA_THRESHOLD;
+       }
+
+       if( stats->flash )
+       {
+               stats->flash_history[1] = stats->flash_history[0];
+               stats->flash_history[0] = mlt_sample_calculator_to_now( fps, SAMPLE_FREQ, pos );
+               if( stats->flash_history_count < 2 )
+               {
+                       stats->flash_history_count++;
+               }
+       }
+}
+
+static void detect_blip( mlt_frame frame, mlt_position pos, double fps, avsync_stats* stats )
+{
+       int frequency = SAMPLE_FREQ;
+       int channels = 1;
+       int samples = mlt_sample_calculator( fps, frequency, pos );
+       mlt_audio_format format = mlt_audio_float;
+       float* buffer = NULL;
+       int error = mlt_frame_get_audio( frame, (void**) &buffer, &format, &frequency, &channels, &samples );
+
+       if ( !error && format == mlt_audio_float && buffer != NULL )
+       {
+               int i = 0;
+
+               for( i = 0; i < samples; i++ )
+               {
+                       if( !stats->blip_in_progress )
+                       {
+                               if( buffer[i] > BLIP_THRESHOLD || buffer[i] < -BLIP_THRESHOLD )
+                               {
+                                       // This sample must start a blip
+                                       stats->blip_in_progress = 1;
+                                       stats->samples_since_blip = 0;
+
+                                       stats->blip_history[1] = stats->blip_history[0];
+                                       stats->blip_history[0] = mlt_sample_calculator_to_now( fps, SAMPLE_FREQ, pos );
+                                       stats->blip_history[0] += i;
+                                       if( stats->blip_history_count < 2 )
+                                       {
+                                               stats->blip_history_count++;
+                                       }
+                                       stats->blip = 1;
+                               }
+                       }
+                       else
+                       {
+                               if( buffer[i] > -BLIP_THRESHOLD && buffer[i] < BLIP_THRESHOLD )
+                               {
+                                       if( ++stats->samples_since_blip > frequency / 1000 )
+                                       {
+                                               // One ms of silence means the blip is over
+                                               stats->blip_in_progress = 0;
+                                               stats->samples_since_blip = 0;
+                                       }
+                               }
+                               else
+                               {
+                                       stats->samples_since_blip = 0;
+                               }
+                       }
+               }
+       }
+}
+
+static void calculate_sync( avsync_stats* stats )
+{
+       if( stats->blip || stats->flash )
+       {
+               if( stats->flash_history_count > 0 &&
+                       stats->blip_history_count > 0 &&
+                       stats->blip_history[0] == stats->flash_history[0] )
+               {
+                       // The flash and blip occurred at the same time.
+                       stats->sample_offset = 0;
+               }
+               if( stats->flash_history_count > 1 &&
+                       stats->blip_history_count > 0 &&
+                       stats->blip_history[0] <= stats->flash_history[0] &&
+                       stats->blip_history[0] >= stats->flash_history[1] )
+               {
+                       // The latest blip occurred between two flashes
+                       if( stats->flash_history[0] - stats->blip_history[0] >
+                           stats->blip_history[0] - stats->flash_history[1] )
+                       {
+                               // Blip is closer to the previous flash.
+                               // F1---B0--------F0
+                               // ^----^
+                               // Video leads audio (negative number).
+                               stats->sample_offset = (int)(stats->flash_history[1] - stats->blip_history[0] );
+                       }
+                       else
+                       {
+                               // Blip is closer to the current flash.
+                               // F1--------B0---F0
+                               //           ^----^
+                               // Audio leads video (positive number).
+                               stats->sample_offset = (int)(stats->flash_history[0] - stats->blip_history[0]);
+                       }
+               }
+               else if( stats->blip_history_count > 1 &&
+                                stats->flash_history_count > 0 &&
+                                stats->flash_history[0] <= stats->blip_history[0] &&
+                                stats->flash_history[0] >= stats->blip_history[1] )
+               {
+                       // The latest flash occurred between two blips
+                       if( stats->blip_history[0] - stats->flash_history[0] >
+                           stats->flash_history[0] - stats->blip_history[1] )
+                       {
+                               // Flash is closer to the previous blip.
+                               // B1---F0--------B0
+                               // ^----^
+                               // Audio leads video (positive number).
+                               stats->sample_offset = (int)(stats->flash_history[0] - stats->blip_history[1]);
+                       }
+                       else
+                       {
+                               // Flash is closer to the latest blip.
+                               // B1--------F0---B0
+                               //           ^----^
+                               // Video leads audio (negative number).
+                               stats->sample_offset = (int)(stats->flash_history[0] - stats->blip_history[0] );
+                       }
+               }
+       }
+}
+
+static void report_results( avsync_stats* stats, mlt_position pos )
+{
+       if( stats->report_frames || stats->blip )
+       {
+               if( stats->sample_offset == INT_MAX )
+               {
+                       fprintf( stats->out_file, "%d\t??\n", pos );
+               }
+               else
+               {
+                       // Convert to milliseconds.
+                       double ms_offset = (double)stats->sample_offset * 1000.0 / (double)SAMPLE_FREQ;
+                       fprintf( stats->out_file, "%d\t%02.02f\n", pos, ms_offset );
+               }
+       }
+       stats->blip = 0;
+       stats->flash = 0;
+}
+
+/** The main thread - the argument is simply the consumer.
+*/
+
+static void *consumer_thread( void *arg )
+{
+       // Map the argument to the object
+       mlt_consumer consumer = arg;
+
+       // Get the properties
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+
+       // 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( consumer );
+
+               // 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 )
+               {
+                       avsync_stats* stats = mlt_properties_get_data( properties, "_stats", NULL );
+                       double fps = mlt_properties_get_double( properties, "fps" );
+                       mlt_position pos = mlt_frame_get_position( frame );
+
+                        if( !strcmp( mlt_properties_get( properties, "report" ), "frame" ) )
+                        {
+                                stats->report_frames = 1;
+                        }
+                        else
+                        {
+                                stats->report_frames = 0;
+                        }
+
+                       detect_flash( frame, pos, fps, stats );
+                       detect_blip( frame, pos, fps, stats );
+                       calculate_sync( stats );
+                       report_results( stats, pos );
+
+                       // 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( consumer );
+
+       return NULL;
+}
+
+/** Close the consumer.
+*/
+
+static void consumer_close( mlt_consumer consumer )
+{
+       mlt_properties consumer_properties = MLT_CONSUMER_PROPERTIES( consumer );
+       avsync_stats* stats = mlt_properties_get_data( consumer_properties, "_stats", NULL );
+
+       // Stop the consumer
+       mlt_consumer_stop( consumer );
+
+       // Close the file
+       if( stats->out_file != stdout )
+       {
+               fclose( stats->out_file );
+       }
+
+       // Clean up memory
+       mlt_pool_release( stats );
+
+       // Close the parent
+       mlt_consumer_close( consumer );
+
+       // Free the memory
+       free( consumer );
+}
diff --git a/src/modules/avsync/consumer_blipflash.yml b/src/modules/avsync/consumer_blipflash.yml
new file mode 100644 (file)
index 0000000..5c8f40e
--- /dev/null
@@ -0,0 +1,34 @@
+schema_version: 0.1
+type: consumer
+identifier: blipflash
+title: Blip Flash
+version: 1
+copyright: Brian Matherly
+creator: Brian Matherly
+license: LGPLv2.1
+language: en
+tags:
+  - Video
+  - Audio
+description: >
+  Calculate the A/V sync for a blip flash source. 
+  Sync can be recalculated whenever a blip or a flash is detected.
+parameters:
+  - identifier: argument
+    title: Report File
+    type: string
+    description: >
+      The file to report the results to. If empty, the results will be reported to standard out.
+    required: no
+    widget: filesave
+  - identifier: report
+    title: Report Style
+    type: string
+    description: >
+      When to report sync - every frame or only when blips occur.
+    default: blip
+    values:
+      - blip
+      - frame
+    mutable: yes
+    widget: combo
diff --git a/src/modules/avsync/factory.c b/src/modules/avsync/factory.c
new file mode 100644 (file)
index 0000000..79687fe
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * factory.c -- the factory method interfaces
+ * Copyright (C) 2013 Brian Matherly
+ * Author: Brian Matherly <pez4brian@yahoo.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 <string.h>
+#include <limits.h>
+
+extern mlt_consumer consumer_blipflash_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_producer producer_blipflash_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+
+static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
+{
+       char file[ PATH_MAX ];
+       snprintf( file, PATH_MAX, "%s/avsync/%s", mlt_environment( "MLT_DATA" ), (char*) data );
+       return mlt_properties_parse_yaml( file );
+}
+
+MLT_REPOSITORY
+{
+       MLT_REGISTER( consumer_type, "blipflash", consumer_blipflash_init );
+       MLT_REGISTER( producer_type, "blipflash", producer_blipflash_init );
+
+       MLT_REGISTER_METADATA( consumer_type, "blipflash", metadata, "consumer_blipflash.yml" );
+       MLT_REGISTER_METADATA( producer_type, "blipflash", metadata, "producer_blipflash.yml" );
+}
diff --git a/src/modules/avsync/producer_blipflash.c b/src/modules/avsync/producer_blipflash.c
new file mode 100644 (file)
index 0000000..612f4d1
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * producer_blipflash.c -- blip/flash generating producer
+ * Copyright (C) 2013 Brian Matherly
+ * Author: Brian Matherly <pez4brian@yahoo.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 <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/** Fill an audio buffer with 1kHz "blip" samples.
+*/
+
+static void fill_blip( mlt_properties producer_properties, float* buffer, int frequency, int channels, int samples )
+{
+       int new_size = samples * channels * sizeof( float );
+       int old_size = 0;
+       float* blip = mlt_properties_get_data( producer_properties, "_blip", &old_size );
+
+       if( !blip || new_size > old_size )
+       {
+               blip = mlt_pool_alloc( new_size );
+
+               // Fill the blip buffer
+               if ( blip != NULL )
+               {
+                       int s = 0;
+                       int c = 0;
+
+                       for( s = 0; s < samples; s++ )
+                       {
+                               float f = 1000.0;
+                               float t = (float)s/(float)frequency;
+                               // Add 90 deg so the blip always starts at 1 for easy detection.
+                               float phase = M_PI / 2;
+                               float value = sin( 2*M_PI*f*t + phase );
+
+                               for( c = 0; c < channels; c++ )
+                               {
+                                       float* sample_ptr = ((float*) blip) + (c * samples) + s;
+                                       *sample_ptr = value;
+                               }
+                       }
+               }
+               // Cache the audio blip to save from regenerating it with every blip.
+               mlt_properties_set_data( producer_properties, "_blip", blip, new_size, mlt_pool_release, NULL );
+       };
+
+       memcpy( buffer, blip, new_size );
+}
+
+static int producer_get_audio( mlt_frame frame, int16_t** buffer, mlt_audio_format* format, int* frequency, int* channels, int* samples )
+{
+       mlt_producer producer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer_blipflash", NULL );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       int size = *samples * *channels * sizeof( float );
+       double fps = mlt_producer_get_fps( producer );
+       int frames = mlt_frame_get_position( frame )  + mlt_properties_get_int( producer_properties, "offset" );
+       int seconds = frames / fps;
+
+       // Correct the returns if necessary
+       *format = mlt_audio_float;
+       *frequency = *frequency <= 0 ? 48000 : *frequency;
+       *channels = *channels <= 0 ? 2 : *channels;
+       *samples = *samples <= 0 ? mlt_sample_calculator( fps, *frequency, frames ) : *samples;
+
+       // Allocate the buffer
+       *buffer = mlt_pool_alloc( size );
+
+       // Determine if this should be a blip or silence.
+       frames = frames % lrint( fps );
+       seconds = seconds % mlt_properties_get_int( producer_properties, "period" );
+       if( seconds == 0 && frames == 0 )
+       {
+               fill_blip( producer_properties, (float*)*buffer, *frequency, *channels, *samples );
+       }
+       else
+       {
+               // Fill silence.
+               memset( *buffer, 0, size );
+       }
+
+       // Set the buffer for destruction
+       mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
+
+       return 0;
+}
+
+/** Fill an image buffer with either white (flash) or black as requested.
+*/
+
+static void fill_image( mlt_properties producer_properties, char* color, uint8_t* buffer, mlt_image_format format, int width, int height )
+{
+
+       int new_size = mlt_image_format_size( format, width, height, NULL );
+       int old_size = 0;
+       uint8_t* image = image = mlt_properties_get_data( producer_properties, color, &old_size );
+
+       if( !image || new_size > old_size )
+       {
+               // Need to create a new cached image.
+               image = mlt_pool_alloc( new_size );
+
+               if ( image != NULL )
+               {
+                       uint8_t r, g, b;
+                       uint8_t* p = image;
+
+                       if( !strcmp( color, "_flash" ) )
+                       {
+                               r = g = b = 255; // White
+                       }
+                       else
+                       {
+                               r = g = b = 0; // Black
+                       }
+
+                       switch( format )
+                       {
+                               default:
+                               case mlt_image_yuv422:
+                               {
+                                       int uneven = width % 2;
+                                       int count = ( width - uneven ) / 2 + 1;
+                                       uint8_t y, u, v;
+
+                                       RGB2YUV_601_SCALED( r, g, b, y, u, v );
+                                       int i = height + 1;
+                                       while ( --i )
+                                       {
+                                               int j = count;
+                                               while ( --j )
+                                               {
+                                                       *p ++ = y;
+                                                       *p ++ = u;
+                                                       *p ++ = y;
+                                                       *p ++ = v;
+                                               }
+                                               if ( uneven )
+                                               {
+                                                       *p ++ = y;
+                                                       *p ++ = u;
+                                               }
+                                       }
+                                       break;
+                               }
+                               case mlt_image_rgb24:
+                               {
+                                       int i = width * height + 1;
+                                       while ( --i )
+                                       {
+                                               *p ++ = r;
+                                               *p ++ = g;
+                                               *p ++ = b;
+                                       }
+                                       break;
+                               }
+                               case mlt_image_rgb24a:
+                               {
+                                       int i = width * height + 1;
+                                       while ( --i )
+                                       {
+                                               *p ++ = r;
+                                               *p ++ = g;
+                                               *p ++ = b;
+                                               *p ++ = 255; // alpha
+                                       }
+                                       break;
+                               }
+                       }
+                       // Cache the image to save from regenerating it with every frame.
+                       mlt_properties_set_data( producer_properties, color, image, new_size, mlt_pool_release, NULL );
+               }
+       }
+
+       memcpy( buffer, image, new_size );
+}
+
+static int producer_get_image( mlt_frame frame, uint8_t** buffer, mlt_image_format* format, int* width, int* height, int writable )
+{
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_producer producer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer_blipflash", NULL );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       int size = 0;
+       double fps = mlt_producer_get_fps( producer );
+       int frames = mlt_frame_get_position( frame );
+       int seconds = frames / fps;
+
+       mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) );
+
+       // Correct the returns if necessary
+       if( *format != mlt_image_yuv422 && *format != mlt_image_rgb24 && *format != mlt_image_rgb24a )
+               *format = mlt_image_yuv422;
+       if( *width <= 0 )
+               *width = mlt_service_profile( MLT_PRODUCER_SERVICE(producer) )->width;
+       if ( *height <= 0 )
+               *height = mlt_service_profile( MLT_PRODUCER_SERVICE(producer) )->height;
+
+       // Allocate the buffer
+       size = mlt_image_format_size( *format, *width, *height, NULL );
+       *buffer = mlt_pool_alloc( size );
+
+       // Determine if this should be a flash or black.
+       frames = frames % lrint( fps );
+       seconds = seconds % mlt_properties_get_int( producer_properties, "period" );
+       if( seconds == 0 && frames == 0 )
+       {
+               fill_image( producer_properties, "_flash", *buffer, *format, *width, *height );
+       }
+       else
+       {
+               fill_image( producer_properties, "_black", *buffer, *format, *width, *height );
+       }
+
+       mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) );
+
+       // Create the alpha channel
+       int alpha_size = *width * *height;
+       uint8_t *alpha = mlt_pool_alloc( alpha_size );
+       if ( alpha )
+               memset( alpha, 255, alpha_size );
+
+       // Update the frame
+       mlt_frame_set_image( frame, *buffer, size, mlt_pool_release );
+       mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release );
+       mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_properties, "aspect_ratio" ) );
+       mlt_properties_set_int( properties, "progressive", 1 );
+       mlt_properties_set_int( properties, "meta.media.width", *width );
+       mlt_properties_set_int( properties, "meta.media.height", *height );
+
+       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
+               mlt_properties frame_properties = MLT_FRAME_PROPERTIES( *frame );
+
+               // Save the producer to be used later
+               mlt_properties_set_data( frame_properties, "_producer_blipflash", producer, 0, NULL, NULL );
+
+               // Update time code on the frame
+               mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
+
+               // Configure callbacks
+               mlt_frame_push_get_image( *frame, producer_get_image );
+               mlt_frame_push_audio( *frame, producer_get_audio );
+       }
+
+       // Calculate the next time code
+       mlt_producer_prepare_next( producer );
+
+       return 0;
+}
+
+static void producer_close( mlt_producer this )
+{
+       this->close = NULL;
+       mlt_producer_close( this );
+       free( this );
+}
+
+/** Initialize.
+*/
+
+mlt_producer producer_blipflash_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       // Create a new producer object
+       mlt_producer producer = mlt_producer_new( profile );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+
+       // Initialize the producer
+       if ( producer )
+       {
+               mlt_properties_set_int( producer_properties, "period", 1 );
+               mlt_properties_set_int( producer_properties, "offset", 0 );
+
+               // Callback registration
+               producer->get_frame = producer_get_frame;
+               producer->close = ( mlt_destructor )producer_close;
+       }
+
+       return producer;
+}
diff --git a/src/modules/avsync/producer_blipflash.yml b/src/modules/avsync/producer_blipflash.yml
new file mode 100644 (file)
index 0000000..8bec5a3
--- /dev/null
@@ -0,0 +1,36 @@
+schema_version: 0.1
+type: producer
+identifier: blipflash
+title: Blip Flash
+version: 1
+copyright: Brian Matherly
+creator: Brian Matherly
+license: LGPLv2.1
+language: en
+tags:
+  - Audio
+  - Video
+description: >
+  Generate periodic synchronized audio blips and video flashes. 
+  Blips are a 1kHz tone and last the duration of the flash frame.
+parameters:
+  - identifier: period
+    title: Flash Period
+    type: integer
+    description: >
+      The period between flashes in seconds.
+    default: 1
+    readonly: no
+    mutable: yes
+    widget: spinner
+  - identifier: offset
+    title: Audio Offset
+    type: integer
+    description: >
+      The number of frames to offset the audio. 
+      A positive number results in audio earlier than video. 
+      An negative number results in audio later than video. 
+    default: 0
+    readonly: no
+    mutable: yes
+    widget: spinner
index b86c7f1c611427caeef9331d61cb1b97fc209faa..b7981f4a971e0e31da82a358027ad35aa9173ef6 100644 (file)
@@ -43,6 +43,12 @@ OBJS = factory.o \
           consumer_multi.o \
           consumer_null.o
 
+ifdef SSE2_FLAGS
+ifdef ARCH_X86_64
+OBJS += composite_line_yuv_sse2_simple.o
+endif
+endif
+
 ASM_OBJS = 
 
 SRCS := $(OBJS:.o=.c)
@@ -71,12 +77,12 @@ clean:
                rm -f $(OBJS) $(ASM_OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/core"
-       install -m 644 data_fx.properties "$(DESTDIR)$(datadir)/mlt/core"
-       install -m 644 loader.dict "$(DESTDIR)$(datadir)/mlt/core"
-       install -m 644 loader.ini "$(DESTDIR)$(datadir)/mlt/core"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/core"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/core"
+       install -m 644 data_fx.properties "$(DESTDIR)$(mltdatadir)/core"
+       install -m 644 loader.dict "$(DESTDIR)$(mltdatadir)/core"
+       install -m 644 loader.ini "$(DESTDIR)$(mltdatadir)/core"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/core"
 
 ifneq ($(wildcard .depend),)
 include .depend
diff --git a/src/modules/core/composite_line_yuv_sse2_simple.c b/src/modules/core/composite_line_yuv_sse2_simple.c
new file mode 100644 (file)
index 0000000..f581fac
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * composite_line_yuv_sse2_simple.c
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Maksym Veremeyenko <verem@m1stereo.tv>
+ *
+ * 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 <inttypes.h>
+void composite_line_yuv_sse2_simple(uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight)
+{
+    const static unsigned char const1[] =
+    {
+        0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00
+    };
+
+    __asm__ volatile
+    (
+        "pxor           %%xmm0, %%xmm0          \n\t"   /* clear zero register */
+        "movdqu         (%4), %%xmm9            \n\t"   /* load const1 */
+        "movd           %0, %%xmm1              \n\t"   /* load weight and decompose */
+        "movlhps        %%xmm1, %%xmm1          \n\t"
+        "pshuflw        $0, %%xmm1, %%xmm1      \n\t"
+        "pshufhw        $0, %%xmm1, %%xmm1      \n\t"
+
+        /*
+            xmm1 (weight)
+
+                    00  W 00  W 00  W 00  W 00  W 00  W 00  W 00  W
+        */
+        "loop_start:                            \n\t"
+        "movq           (%1), %%xmm2            \n\t"   /* load source alpha */
+        "punpcklbw      %%xmm0, %%xmm2          \n\t"   /* unpack alpha 8 8-bits alphas to 8 16-bits values */
+
+        /*
+            xmm2 (src alpha)
+            xmm3 (dst alpha)
+
+                    00 A8 00 A7 00 A6 00 A5 00 A4 00 A3 00 A2 00 A1
+        */
+        "pmullw         %%xmm1, %%xmm2          \n\t"   /* premultiply source alpha */
+        "psrlw          $8, %%xmm2              \n\t"
+
+        /*
+            xmm2 (premultiplied)
+
+                    00 A8 00 A7 00 A6 00 A5 00 A4 00 A3 00 A2 00 A1
+        */
+
+
+        /*
+            DSTa = DSTa + (SRCa * (0xFF - DSTa)) >> 8
+        */
+        "movq           (%5), %%xmm3            \n\t"   /* load dst alpha */
+        "punpcklbw      %%xmm0, %%xmm3          \n\t"   /* unpack dst 8 8-bits alphas to 8 16-bits values */
+        "movdqa         %%xmm9, %%xmm4          \n\t"
+        "psubw          %%xmm3, %%xmm4          \n\t"
+        "pmullw         %%xmm2, %%xmm4          \n\t"
+        "psrlw          $8, %%xmm4              \n\t"
+        "paddw          %%xmm4, %%xmm3          \n\t"
+        "packuswb       %%xmm0, %%xmm3          \n\t"
+        "movq           %%xmm3, (%5)            \n\t"   /* save dst alpha */
+
+        "movdqu         (%2), %%xmm3            \n\t"   /* load src */
+        "movdqu         (%3), %%xmm4            \n\t"   /* load dst */
+        "movdqa         %%xmm3, %%xmm5          \n\t"   /* dub src */
+        "movdqa         %%xmm4, %%xmm6          \n\t"   /* dub dst */
+
+        /*
+            xmm3 (src)
+            xmm4 (dst)
+            xmm5 (src)
+            xmm6 (dst)
+
+                    U8 V8 U7 V7 U6 V6 U5 V5 U4 V4 U3 V3 U2 V2 U1 V1
+        */
+
+        "punpcklbw      %%xmm0, %%xmm5          \n\t"   /* unpack src low */
+        "punpcklbw      %%xmm0, %%xmm6          \n\t"   /* unpack dst low */
+        "punpckhbw      %%xmm0, %%xmm3          \n\t"   /* unpack src high */
+        "punpckhbw      %%xmm0, %%xmm4          \n\t"   /* unpack dst high */
+
+        /*
+            xmm5 (src_l)
+            xmm6 (dst_l)
+
+                    00 U4 00 V4 00 U3 00 V3 00 U2 00 V2 00 U1 00 V1
+
+            xmm3 (src_u)
+            xmm4 (dst_u)
+
+                    00 U8 00 V8 00 U7 00 V7 00 U6 00 V6 00 U5 00 V5
+        */
+
+        "movdqa         %%xmm2, %%xmm7          \n\t"   /* dub alpha */
+        "movdqa         %%xmm2, %%xmm8          \n\t"   /* dub alpha */
+        "movlhps        %%xmm7, %%xmm7          \n\t"   /* dub low */
+        "movhlps        %%xmm8, %%xmm8          \n\t"   /* dub high */
+
+        /*
+            xmm7 (src alpha)
+
+                    00 A4 00 A3 00 A2 00 A1 00 A4 00 A3 00 A2 00 A1
+            xmm8 (src alpha)
+
+                    00 A8 00 A7 00 A6 00 A5 00 A8 00 A7 00 A6 00 A5
+        */
+
+        "pshuflw        $0x50, %%xmm7, %%xmm7     \n\t"
+        "pshuflw        $0x50, %%xmm8, %%xmm8     \n\t"
+        "pshufhw        $0xFA, %%xmm7, %%xmm7     \n\t"
+        "pshufhw        $0xFA, %%xmm8, %%xmm8     \n\t"
+
+        /*
+            xmm7 (src alpha lower)
+
+                    00 A4 00 A4 00 A3 00 A3 00 A2 00 A2 00 A1 00 A1
+
+            xmm8 (src alpha upper)
+                    00 A8 00 A8 00 A7 00 A7 00 A6 00 A6 00 A5 00 A5
+        */
+
+
+        /*
+            DST = SRC * ALPHA + DST * (0xFF - ALPHA)
+                SRC * ALPHA + DST * 0xFF - DST * ALPHA
+                (SRC - DST) * ALPHA + DST * 0xFF
+
+        */
+        "psubw          %%xmm4, %%xmm3          \n\t"   /* src = src - dst */
+        "psubw          %%xmm6, %%xmm5          \n\t"
+        "pmullw         %%xmm8, %%xmm3          \n\t"   /* src = src * alpha */
+        "pmullw         %%xmm7, %%xmm5          \n\t"
+        "pmullw         %%xmm9, %%xmm4          \n\t"   /* dst = dst * 0xFF */
+        "pmullw         %%xmm9, %%xmm6          \n\t"
+        "paddw          %%xmm3, %%xmm4          \n\t"   /* dst = dst + src */
+        "paddw          %%xmm5, %%xmm6          \n\t"
+        "psrlw          $8, %%xmm4              \n\t"   /* dst = dst >> 8 */
+        "psrlw          $8, %%xmm6              \n\t"
+//        "pminsw         %%xmm9, %%xmm4          \n\t"   /* clamp values */
+//        "pminsw         %%xmm9, %%xmm6          \n\t"
+
+        /*
+            xmm6 (dst_l)
+
+                    00 U4 00 V4 00 U3 00 V3 00 U2 00 V2 00 U1 00 V1
+
+            xmm4 (dst_u)
+
+                    00 U8 00 V8 00 U7 00 V7 00 U6 00 V6 00 U5 00 V5
+        */
+        "packuswb       %%xmm4, %%xmm6          \n\t"
+
+        /*
+            xmm6 (dst)
+
+                    U8 V8 U7 V7 U6 V6 U5 V5 U4 V4 U3 V3 U2 V2 U1 V1
+        */
+        "movdqu         %%xmm6, (%3)            \n\t"   /* store dst */
+
+        /*
+            increment pointers
+        */
+        "add            $0x08, %1               \n\t"
+        "add            $0x08, %5               \n\t"
+        "add            $0x10, %2               \n\t"
+        "add            $0x10, %3               \n\t"
+
+        "dec            %6                      \n\t"
+        "jnz            loop_start              \n\t"
+
+        :
+        : "r" (weight >> 8), "r" (alpha_b), "r" (src), "r" (dest), "r" (const1) , "r" (alpha_a), "r" (width / 8)
+        //: "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9", "memory"
+    );
+};
index 948bf4a9fe9c2325e8bdae445272068a6bf4b644..1781746a419fec89f9c0b2d5f6b13eebbbb00576 100644 (file)
@@ -85,15 +85,19 @@ static void create_filter( mlt_profile profile, mlt_service service, char *effec
 
        // The swscale and avcolor_space filters require resolution as arg to test compatibility
        if ( strncmp( effect, "swscale", 7 ) == 0 || strncmp( effect, "avcolo", 6 ) == 0 )
-               arg = (char*) mlt_properties_get_int( MLT_SERVICE_PROPERTIES( service ), "_real_width" );
+               arg = (char*) mlt_properties_get_int( MLT_SERVICE_PROPERTIES( service ), "meta.media.width" );
 
-       mlt_filter filter = mlt_factory_filter( profile, id, arg );
-       if ( filter != NULL )
+       // We cannot use GLSL-based filters here.
+       if ( strncmp( effect, "movit.", 6 ) && strncmp( effect, "glsl.", 5 ) )
        {
-               mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_loader", 1 );
-               mlt_service_attach( service, filter );
-               mlt_filter_close( filter );
-               *created = 1;
+               mlt_filter filter = mlt_factory_filter( profile, id, arg );
+               if ( filter != NULL )
+               {
+                       mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_loader", 1 );
+                       mlt_service_attach( service, filter );
+                       mlt_filter_close( filter );
+                       *created = 1;
+               }
        }
        free( id );
 }
@@ -131,12 +135,27 @@ static void attach_normalisers( mlt_profile profile, mlt_service service )
 
        // Attach the audio and video format converters
        int created = 0;
+       // movit.convert skips setting the frame->convert_image pointer if GLSL cannot be used.
+       mlt_filter filter = mlt_factory_filter( profile, "movit.convert", NULL );
+       if ( filter != NULL )
+       {
+               mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_loader", 1 );
+               mlt_service_attach( service, filter );
+               mlt_filter_close( filter );
+               created = 1;
+       }
+       // avcolor_space and imageconvert only set frame->convert_image if it has not been set.
        create_filter( profile, service, "avcolor_space", &created );
        if ( !created )
                create_filter( profile, service, "imageconvert", &created );
        create_filter( profile, service, "audioconvert", &created );
 }
 
+static void on_frame_show( void *dummy, mlt_properties properties, mlt_frame frame )
+{
+       mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
+}
+
 static mlt_consumer generate_consumer( mlt_consumer consumer, mlt_properties props, int index )
 {
        mlt_profile profile = NULL;
@@ -166,6 +185,14 @@ static mlt_consumer generate_consumer( mlt_consumer consumer, mlt_properties pro
                mlt_properties_inherit( nested_props, props );
 
                attach_normalisers( profile, MLT_CONSUMER_SERVICE(nested) );
+
+               // Relay the first available consumer-frame-show event
+               mlt_event event = mlt_properties_get_data( properties, "frame-show-event", NULL );
+               if ( !event )
+               {
+                       event = mlt_events_listen( nested_props, properties, "consumer-frame-show", (mlt_listener) on_frame_show );
+                       mlt_properties_set_data( properties, "frame-show-event", event, 0, /*mlt_event_close*/ NULL, NULL );
+               }
        }
        else
        {
@@ -328,7 +355,8 @@ static void foreach_consumer_put( mlt_consumer consumer, mlt_frame frame )
                        while ( nested_time <= self_time )
                        {
                                // put ideal number of samples into cloned frame
-                               mlt_frame clone_frame = mlt_frame_clone( frame, 0 );
+                               int deeply = index > 1 ? 1 : 0;
+                               mlt_frame clone_frame = mlt_frame_clone( frame, deeply );
                                int nested_samples = mlt_sample_calculator( nested_fps, frequency, nested_pos );
                                // -10 is an optimization to avoid tiny amounts of leftover samples
                                nested_samples = nested_samples > current_samples - 10 ? current_samples : nested_samples;
@@ -504,7 +532,6 @@ static void *consumer_thread( void *arg )
                                if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES(frame), "_speed" ) == 0 )
                                        foreach_consumer_refresh( consumer );
                                foreach_consumer_put( consumer, frame );
-                               mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
                        }
                        else
                        {
@@ -520,7 +547,6 @@ static void *consumer_thread( void *arg )
                        {
                                // Send this termination frame to nested consumers for their cancellation
                                foreach_consumer_put( consumer, frame );
-                               mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
                        }
                        if ( frame )
                                mlt_frame_close( frame );
index 34246ed2be79cab250452de876aa06837afbbfb4..7adb8fcc6385592035ae7afe0b166643aa787208 100644 (file)
@@ -75,8 +75,8 @@ MLT_REPOSITORY
        MLT_REGISTER( filter_type, "audiowave", filter_audiowave_init );
        MLT_REGISTER( filter_type, "brightness", filter_brightness_init );
        MLT_REGISTER( filter_type, "channelcopy", filter_channelcopy_init );
-    MLT_REGISTER( filter_type, "channelswap", filter_channelcopy_init );
-    MLT_REGISTER( filter_type, "crop", filter_crop_init );
+       MLT_REGISTER( filter_type, "channelswap", 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, "fieldorder", filter_fieldorder_init );
index 20e839bfebf9c6d176ccc2e6391bb136c153a15e..ba8a85b27fe939935fa0cf9f160d8ddd50b0d078 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_audiochannels.c -- convert from one audio format to another
- * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -46,14 +46,40 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        {
                                for ( j = 0; j < *channels; j++ )
                                {
-                                       new_buffer[ ( i * *channels ) + j ]     = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       k = ( k + 1 ) % channels_avail;
+                               }
+                       }
+               }
+               else if ( *format == mlt_audio_s32le || *format == mlt_audio_f32le )
+               {
+                       int32_t *p = (int32_t*) new_buffer;
+                       int i, j, k = 0;
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               for ( j = 0; j < *channels; j++ )
+                               {
+                                       p[ ( i * *channels ) + j ] = ((int32_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       k = ( k + 1 ) % channels_avail;
+                               }
+                       }
+               }
+               else if ( *format == mlt_audio_u8 )
+               {
+                       uint8_t *p = (uint8_t*) new_buffer;
+                       int i, j, k = 0;
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               for ( j = 0; j < *channels; j++ )
+                               {
+                                       p[ ( i * *channels ) + j ] = ((uint8_t*)(*buffer))[ ( i * channels_avail ) + k ];
                                        k = ( k + 1 ) % channels_avail;
                                }
                        }
                }
                else
                {
-                       // non-interleaved
+                       // non-interleaved - s32 or float
                        int size_avail = mlt_audio_format_size( *format, *samples, channels_avail );
                        int32_t *p = (int32_t*) new_buffer;
                        int i = *channels / channels_avail;
index 6e930d7e0136ed6d8ae8d796de061765336ddd94..a38219286f7c10968b2589296f240b3e0d91d398 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_audioconvert.c -- convert from one audio format to another
- * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -81,6 +81,46 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (int32_t) *q++ << 16;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = (float)( *q++ ) / 32768.0;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( *q++ >> 8 ) + 128;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -113,6 +153,49 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = (float)( *( q + c * samples + s ) ) / 2147483648.0;
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = f;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = ( q[c * samples + s] >> 24 ) + 128;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -153,6 +236,53 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = ( 127 * f ) + 128;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -210,6 +340,30 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (float)( *q++ ) / 2147483648.0;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( *q++ >> 24 ) + 128;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -273,6 +427,123 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = ( 127 * f ) + 128;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+                       break;
+               case mlt_audio_u8:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s32:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       uint8_t *q = (uint8_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = ( (int32_t) *q - 128 ) << 24;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       uint8_t *q = (uint8_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = ( (float) *q - 128 ) / 256.0f;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s16:
+                       {
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( (int16_t) *q++ - 128 ) << 8;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( (int32_t) *q++ - 128 ) << 24;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = ( (float) *q++ - 128 ) / 256.0f;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -303,7 +574,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+       mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( mlt_filter_init( this, this ) == 0 )
                this->process = filter_process;
        return this;
index cbfb709b6005b2bf111d7719ce95aa3734cfec92..dc971f9128ab00e9a723126c98ab914c2347e8a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_channelcopy.c -- copy one audio channel to another
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -48,6 +48,25 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
        if ( from != to)
        switch ( *format )
        {
+               case mlt_audio_u8:
+               {
+                       uint8_t *f = (uint8_t*) *buffer + from;
+                       uint8_t *t = (uint8_t*) *buffer + to;
+                       uint8_t x;
+                       int i;
+
+                       if ( swap )
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                               {
+                                       x = *t;
+                                       *t = *f;
+                                       *f = x;
+                               }
+                       else
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                                       *t = *f;
+                       break;
+               }
                case mlt_audio_s16:
                {
                        int16_t *f = (int16_t*) *buffer + from;
@@ -86,6 +105,26 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        }
                        break;
                }
+               case mlt_audio_s32le:
+               case mlt_audio_f32le:
+               {
+                       int32_t *f = (int32_t*) *buffer + from;
+                       int32_t *t = (int32_t*) *buffer + to;
+                       int32_t x;
+                       int i;
+
+                       if ( swap )
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                               {
+                                       x = *t;
+                                       *t = *f;
+                                       *f = x;
+                               }
+                       else
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                                       *t = *f;
+                       break;
+               }
                case mlt_audio_float:
                {
                        float *f = (float*) *buffer + from * *samples;
index 3c45e24d03e1df6575d8650294f2fb278c341b78..8f3b7765042315e8e4f13afbc2329c428b63d3f5 100644 (file)
@@ -46,18 +46,19 @@ static void crop( uint8_t *src, uint8_t *dest, int bpp, int width, int height, i
 /** Do it :-).
 */
 
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
        int error = 0;
+       mlt_profile profile = mlt_frame_pop_service( frame );
 
        // Get the properties from the frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        // 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" );
+               *width  = profile->width;
+               *height = profile->height;
        }
 
        int left    = mlt_properties_get_int( properties, "crop.left" );
@@ -73,7 +74,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        }
 
        // Now get the image
-       error = mlt_frame_get_image( this, image, format, width, height, writable );
+       error = mlt_frame_get_image( frame, image, format, width, height, writable );
 
        int owidth  = *width - left - right;
        int oheight = *height - top - bottom;
@@ -86,22 +87,15 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                int bpp;
 
                // Subsampled YUV is messy and less precise.
-               if ( *format == mlt_image_yuv422 && this->convert_image )
+               if ( *format == mlt_image_yuv422 && frame->convert_image )
                {
                        mlt_image_format requested_format = mlt_image_rgb24;
-                       this->convert_image( this, image, format, requested_format );
+                       frame->convert_image( frame, image, format, requested_format );
                }
        
                mlt_log_debug( NULL, "[filter crop] %s %dx%d -> %dx%d\n", mlt_image_format_name(*format),
                                 *width, *height, owidth, oheight);
 
-               // 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" ) );
                
@@ -114,12 +108,12 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        crop( *image, output, bpp, *width, *height, left, right, top, bottom );
 
                        // Now update the frame
-                       mlt_frame_set_image( this, output, size, mlt_pool_release );
+                       mlt_frame_set_image( frame, output, size, mlt_pool_release );
                        *image = output;
                }
 
                // We should resize the alpha too
-               uint8_t *alpha = mlt_frame_get_alpha_mask( this );
+               uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
                int alpha_size = 0;
                mlt_properties_get_data( properties, "alpha", &alpha_size );
                if ( alpha && alpha_size >= ( *width * *height ) )
@@ -128,8 +122,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        if ( newalpha )
                        {
                                crop( alpha, newalpha, 1, *width, *height, left, right, top, bottom );
-                               mlt_frame_set_alpha( this, newalpha, owidth * oheight, mlt_pool_release );
-                               this->get_alpha_mask = NULL;
+                               mlt_frame_set_alpha( frame, newalpha, owidth * oheight, mlt_pool_release );
                        }
                }
                *width = owidth;
@@ -142,25 +135,26 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 {
-       if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "active" ) )
+       if ( mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "active" ) )
        {
                // Push the get_image method on to the stack
+               mlt_frame_push_service( frame, mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) );
                mlt_frame_push_get_image( frame, filter_get_image );
        }
        else
        {
-               mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
+               mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
                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" );
+               int width  = mlt_properties_get_int( frame_props, "meta.media.width" );
+               int height = mlt_properties_get_int( frame_props, "meta.media.height" );
                int use_profile = mlt_properties_get_int( filter_props, "use_profile" );
-               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
+               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
 
                if ( use_profile )
                {
@@ -173,9 +167,9 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                {
                        double aspect_ratio = mlt_frame_get_aspect_ratio( frame );
                        if ( aspect_ratio == 0.0 )
-                               aspect_ratio = mlt_properties_get_double( frame_props, "consumer_aspect_ratio" );
+                               aspect_ratio = mlt_profile_sar( profile );
                        double input_ar = aspect_ratio * width / height;
-                       double output_ar = mlt_profile_dar( mlt_service_profile( MLT_FILTER_SERVICE(this) ) );
+                       double output_ar = mlt_profile_dar( mlt_service_profile( MLT_FILTER_SERVICE(filter) ) );
                        int bias = mlt_properties_get_int( filter_props, "center_bias" );
                        
                        if ( input_ar > output_ar )
@@ -213,8 +207,8 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                mlt_properties_set_int( frame_props, "crop.bottom", bottom );
                mlt_properties_set_int( frame_props, "crop.original_width", width );
                mlt_properties_set_int( frame_props, "crop.original_height", height );
-               mlt_properties_set_int( frame_props, "real_width", width - left - right );
-               mlt_properties_set_int( frame_props, "real_height", height - top - bottom );
+               mlt_properties_set_int( frame_props, "meta.media.width", width - left - right );
+               mlt_properties_set_int( frame_props, "meta.media.height", height - top - bottom );
        }
        return frame;
 }
@@ -224,12 +218,12 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 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 )
+       mlt_filter filter = calloc( 1, sizeof( struct mlt_filter_s ) );
+       if ( mlt_filter_init( filter, filter ) == 0 )
        {
-               this->process = filter_process;
+               filter->process = filter_process;
                if ( arg )
-                       mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "active", atoi( arg ) );
+                       mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "active", atoi( arg ) );
        }
-       return this;
+       return filter;
 }
index 73d7d778f243fcc6c599be29da3e8258de637955..47f09f26645677737ca4297bc1ee95942c899f26 100644 (file)
@@ -55,7 +55,10 @@ static mlt_filter obtain_filter( mlt_filter filter, char *type )
                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 );
+               {
+                       strncpy( temp, profile, sizeof( temp ) );
+                       temp[ sizeof( temp ) - 1 ] = '\0';
+               }
 
                // Load the specified profile or use the default
                profile_properties = mlt_properties_load( temp );
@@ -207,7 +210,7 @@ static int process_feed( mlt_properties feed, mlt_filter filter, mlt_frame frame
                                                                        // 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 );
+                                                                       strncat( result, tc, sizeof( result ) - strlen( result ) - 1 );
                                                                        free( tc );
                                                                }
                                                                else if ( !strcmp( keywords, "frame" ) )
@@ -216,13 +219,14 @@ static int process_feed( mlt_properties feed, mlt_filter filter, mlt_frame frame
                                                                        int pos = mlt_properties_get_int( feed, "position" );
                                                                        char s[12];
                                                                        snprintf( s, sizeof(s) - 1, "%d", pos );
+                                                                       s[sizeof( s ) - 1] = '\0';
                                                                        strcat( result, s );
                                                                }
                                                                else
                                                                {
                                                                        // replace keyword with metadata value
                                                                        char *metavalue = metadata_value( MLT_FRAME_PROPERTIES( frame ), keywords );
-                                                                       strcat( result, metavalue ? metavalue : "-" );
+                                                                       strncat( result, metavalue ? metavalue : "-", sizeof( result ) - strlen( result ) -1 );
                                                                }
                                                                keywords = strtok( NULL, "#" );
                                                                ct++;
index 259981154f247f79c72faa8fe3164d3f9b80d932..a0a571f0c868dd1743a2a9b71a458b9cfdda63de 100644 (file)
@@ -47,11 +47,8 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
                        mlt_properties_get_int( properties, "progressive" ) == 0 )
                {
                        // We only work with non-planar formats
-                       if ( *format == mlt_image_yuv420p )
-                       {
-                               *format = mlt_image_yuv422;
-                               mlt_frame_get_image( frame, image, format, width, height, writable );
-                       }
+                       if ( *format == mlt_image_yuv420p && frame->convert_image )
+                               error = frame->convert_image( frame, image, format, mlt_image_yuv422 );
 
                        // Make a new image
                        int bpp;
@@ -74,7 +71,8 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
                }
 
                // Correct field order if needed
-               if ( mlt_properties_get_int( properties, "top_field_first" ) != tff &&
+               if ( tff != -1 &&
+                    mlt_properties_get_int( properties, "top_field_first" ) != tff &&
                     mlt_properties_get( properties, "progressive" ) &&
                     mlt_properties_get_int( properties, "progressive" ) == 0 )
                {
index 1dfc8b9c90bbb37ee761ed5f1b0e90dcdcf4875b..33c938802ce8762a91d1d840e24c09982cdcf8b8 100644 (file)
@@ -337,6 +337,8 @@ static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *f
                                         ? mlt_pool_alloc( width * height ) : NULL;
                        if ( requested_format == mlt_image_rgb24a || requested_format == mlt_image_opengl )
                        {
+                               if ( alpha )
+                                       mlt_pool_release( alpha );
                                alpha = mlt_frame_get_alpha_mask( frame );
                                mlt_properties_get_data( properties, "alpha", &alpha_size );
                        }
@@ -370,7 +372,8 @@ static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *f
 
 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 {
-       frame->convert_image = convert_image;
+       if ( !frame->convert_image )
+               frame->convert_image = convert_image;
        return frame;
 }
 
@@ -379,7 +382,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+       mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( mlt_filter_init( this, this ) == 0 )
        {
                this->process = filter_process;
index 01b6f462deda35c10d4a4e1edea60c4a13764be6..10952e13989c84e15b493539e6025835cf145d8b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_mono.c -- mix all channels to a mono signal across n channels
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -44,6 +44,20 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
 
        switch ( *format )
        {
+               case mlt_audio_u8:
+               {
+                       uint8_t *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               uint8_t mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((uint8_t*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
                case mlt_audio_s16:
                {
                        int16_t *new_buffer = mlt_pool_alloc( size );
@@ -58,6 +72,34 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        *buffer = new_buffer;
                        break;
                }
+               case mlt_audio_s32le:
+               {
+                       int32_t *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               int32_t mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((int32_t*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
+               case mlt_audio_f32le:
+               {
+                       float *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               float mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((float*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
                case mlt_audio_s32:
                {
                        int32_t *new_buffer = mlt_pool_alloc( size );
index 97376bae9bb266911d9c2f2ab73b3e6ae6d1e7f8..eeff9b6a3a27de607717f2aec0c20e48b3e335e3 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_profile.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -213,11 +214,8 @@ static void obscure_render( uint8_t *image, int width, int height, struct geomet
 
 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 );
+       mlt_filter filter = mlt_frame_pop_service( frame );
 
        // Get the image from the frame
        *format = mlt_image_yuv422;
@@ -226,14 +224,11 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
        // Get the image from the frame
        if ( error == 0 )
        {
-               if ( this != NULL )
+               if ( filter != 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" );
+                       mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+                       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
 
                        // Structures for geometry
                        struct geometry_s result;
@@ -241,11 +236,11 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                        struct geometry_s end;
 
                        // Retrieve the position
-                       float position = mlt_filter_get_progress( this, frame );
+                       float position = mlt_filter_get_progress( filter, frame );
 
                        // 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 );
+                       geometry_parse( &start, NULL, mlt_properties_get( properties, "start" ), profile->width, profile->height );
+                       geometry_parse( &end, &start, mlt_properties_get( properties, "end" ), profile->width, profile->height );
 
                        // Do the calculation
                        geometry_calculate( &result, &start, &end, position, *width, *height );
@@ -261,10 +256,10 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 {
        // Push this on to the service stack
-       mlt_frame_push_service( frame, this );
+       mlt_frame_push_service( frame, filter );
        
        // Push the get image call
        mlt_frame_push_get_image( frame, filter_get_image );
@@ -277,14 +272,14 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 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_filter filter = mlt_filter_new( );
+       if ( filter != NULL )
        {
-               mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-               this->process = filter_process;
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               filter->process = filter_process;
                mlt_properties_set( properties, "start", arg != NULL ? arg : "0%/0%:100%x100%" );
                mlt_properties_set( properties, "end", "" );
        }
-       return this;
+       return filter;
 }
 
index 6ce55d9c984b1f4d278f8adbf78f189e21a9b6ba..88009b20a2010c00539e9ea3fecad23eb9e3afa8 100644 (file)
@@ -292,7 +292,7 @@ static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 
 mlt_filter filter_panner_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       mlt_filter filter = calloc( sizeof( struct mlt_filter_s ), 1 );
+       mlt_filter filter = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( filter != NULL && mlt_filter_init( filter, NULL ) == 0 )
        {
                filter->process = filter_process;
index 8fd8e8d6ab84e78a236e06dd2c58471471c39b04..7ccfe5287681abc2f73f6ce8c8b722df9cc9e12d 100644 (file)
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+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 properties of the filter
-       mlt_properties properties = MLT_FILTER_PROPERTIES( this );
+       mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+
+       mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
 
        // Get the region transition
        mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL );
@@ -42,21 +47,36 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
        if ( transition == NULL )
        {
                // Create the transition
-               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( this ) );
+               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
                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 );
+               mlt_properties_set_data( MLT_TRANSITION_PROPERTIES( transition ), "_region_filter", filter, 0, NULL, NULL );
        }
 
+       mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
+
        // Pass all properties down
-       mlt_properties_pass( MLT_TRANSITION_PROPERTIES( transition ), properties, "" );
+       mlt_properties_inherit( MLT_TRANSITION_PROPERTIES( transition ), properties );
+
+       // Make the frame's position relative to this filter's in point
+       mlt_frame_set_position( frame, mlt_filter_get_position( filter, frame ) );
 
        // Process the frame
-       return mlt_transition_process( transition, frame, NULL );
+       mlt_transition_process( transition, frame, NULL );
+
+       return mlt_frame_get_image( frame, image, format, width, height, writable );
+}
+
+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.
@@ -86,4 +106,3 @@ mlt_filter filter_region_init( mlt_profile profile, mlt_service_type type, const
        // Return the filter
        return this;
 }
-
index b0cd765712b3997b7142d90708f343ba3ab79ad7..2f7f933fab6517ffde052efc05be9145626e1d00 100644 (file)
@@ -21,6 +21,7 @@
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
 #include <framework/mlt_log.h>
+#include <framework/mlt_profile.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -37,9 +38,9 @@
  * rgb24a -> yuv422
  */
 
-typedef int ( *image_scaler )( mlt_frame this, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight );
+typedef int ( *image_scaler )( mlt_frame frame, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight );
 
-static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight )
+static int filter_scale( mlt_frame frame, uint8_t **image, mlt_image_format *format, int iwidth, int iheight, int owidth, int oheight )
 {
        // Create the output image
        uint8_t *output = mlt_pool_alloc( owidth * ( oheight + 1 ) * 2 );
@@ -103,17 +104,17 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format *form
        }
  
        // Now update the frame
-       mlt_frame_set_image( this, output, owidth * ( oheight + 1 ) * 2, mlt_pool_release );
+       mlt_frame_set_image( frame, output, owidth * ( oheight + 1 ) * 2, mlt_pool_release );
        *image = output;
 
        return 0;
 }
 
-static void scale_alpha( mlt_frame this, int iwidth, int iheight, int owidth, int oheight )
+static void scale_alpha( mlt_frame frame, int iwidth, int iheight, int owidth, int oheight )
 {
        // Scale the alpha
        uint8_t *output = NULL;
-       uint8_t *input = mlt_frame_get_alpha_mask( this );
+       uint8_t *input = mlt_frame_get_alpha_mask( frame );
 
        if ( input != NULL )
        {
@@ -134,22 +135,22 @@ static void scale_alpha( mlt_frame this, int iwidth, int iheight, int owidth, in
                }
 
                // Set it back on the frame
-               mlt_frame_set_alpha( this, output, owidth * oheight, mlt_pool_release );
+               mlt_frame_set_alpha( frame, output, owidth * oheight, mlt_pool_release );
        }
 }
 
 /** Do it :-).
 */
 
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
        int error = 0;
        
        // Get the frame properties
-       mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        // Get the filter from the stack
-       mlt_filter filter = mlt_frame_pop_service( this );
+       mlt_filter filter = mlt_frame_pop_service( frame );
 
        // Get the filter properties
        mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
@@ -160,8 +161,9 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        // 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" );
+               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
+               *width = profile->width;
+               *height = profile->height;
        }
 
        // There can be problems with small images - avoid them (by hacking - gah)
@@ -182,11 +184,11 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        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" ) )
+               // If meta.media.width/height exist, we want that as minimum information
+               if ( mlt_properties_get_int( properties, "meta.media.width" ) )
                {
-                       iwidth = mlt_properties_get_int( properties, "real_width" );
-                       iheight = mlt_properties_get_int( properties, "real_height" );
+                       iwidth = mlt_properties_get_int( properties, "meta.media.width" );
+                       iheight = mlt_properties_get_int( properties, "meta.media.height" );
                }
        
                // Let the producer know what we are actually requested to obtain
@@ -212,7 +214,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        *format = mlt_image_yuv422;
 
                // Get the image as requested
-               mlt_frame_get_image( this, image, format, &iwidth, &iheight, writable );
+               mlt_frame_get_image( frame, image, format, &iwidth, &iheight, writable );
 
                // Get rescale interpretation again, in case the producer wishes to override scaling
                interps = mlt_properties_get( properties, "rescale.interp" );
@@ -227,7 +229,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                             *format == mlt_image_rgb24a || *format == mlt_image_opengl )
                        {
                                // Call the virtual function
-                               scaler_method( this, image, format, iwidth, iheight, owidth, oheight );
+                               scaler_method( frame, image, format, iwidth, iheight, owidth, oheight );
                                *width = owidth;
                                *height = oheight;
                        }
@@ -235,7 +237,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        int alpha_size = 0;
                        mlt_properties_get_data( properties, "alpha", &alpha_size );
                        if ( alpha_size > 0 && alpha_size != ( owidth * oheight ) && alpha_size != ( owidth * ( oheight + 1 ) ) )
-                               scale_alpha( this, iwidth, iheight, owidth, oheight );
+                               scale_alpha( frame, iwidth, iheight, owidth, oheight );
                }
                else
                {
@@ -254,10 +256,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 {
        // Push the filter
-       mlt_frame_push_service( frame, this );
+       mlt_frame_push_service( frame, filter );
 
        // Push the get image method
        mlt_frame_push_service( frame, filter_get_image );
@@ -271,16 +273,16 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 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( );
+       mlt_filter filter = mlt_filter_new( );
 
        // If successful, then initialise it
-       if ( this != NULL )
+       if ( filter != NULL )
        {
                // Get the properties
-               mlt_properties properties = MLT_FILTER_PROPERTIES( this );
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
 
                // Set the process method
-               this->process = filter_process;
+               filter->process = filter_process;
 
                // Set the inerpolation
                mlt_properties_set( properties, "interpolation", arg == NULL ? "bilinear" : arg );
@@ -289,6 +291,6 @@ mlt_filter filter_rescale_init( mlt_profile profile, mlt_service_type type, cons
                mlt_properties_set_data( properties, "method", filter_scale, 0, NULL, NULL );
        }
 
-       return this;
+       return filter;
 }
 
index af7a0254f55d16315edb58088b46cabb2e084ea9..06e5b9a0001566d40fd89b3293ecfa0456b1d2be 100644 (file)
@@ -123,14 +123,14 @@ static void resize_image( uint8_t *output, int owidth, int oheight, uint8_t *inp
        resizes.
 */
 
-static uint8_t *frame_resize_image( mlt_frame this, int owidth, int oheight, int bpp )
+static uint8_t *frame_resize_image( mlt_frame frame, int owidth, int oheight, int bpp )
 {
        // Get properties
-       mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        // 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 );
+       uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
        int alpha_size = 0;
        mlt_properties_get_data( properties, "alpha", &alpha_size );
 
@@ -149,17 +149,14 @@ static uint8_t *frame_resize_image( mlt_frame this, int owidth, int oheight, int
                resize_image( output, owidth, oheight, input, iwidth, iheight, bpp );
 
                // Now update the frame
-               mlt_frame_set_image( this, output, owidth * ( oheight + 1 ) * bpp, mlt_pool_release );
+               mlt_frame_set_image( frame, output, owidth * ( oheight + 1 ) * bpp, mlt_pool_release );
 
                // We should resize the alpha too
                if ( alpha && alpha_size >= iwidth * iheight )
                {
                        alpha = resize_alpha( alpha, owidth, oheight, iwidth, iheight, alpha_value );
                        if ( alpha )
-                       {
-                               mlt_frame_set_alpha( this, alpha, owidth * oheight, mlt_pool_release );
-                               this->get_alpha_mask = NULL;
-                       }
+                               mlt_frame_set_alpha( frame, alpha, owidth * oheight, mlt_pool_release );
                }
 
                // Return the output
@@ -172,25 +169,26 @@ static uint8_t *frame_resize_image( mlt_frame this, int owidth, int oheight, int
 /** Do it :-).
 */
 
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+static int filter_get_image( mlt_frame frame, 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 );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        // Pop the top of stack now
-       mlt_filter filter = mlt_frame_pop_service( this );
+       mlt_filter filter = mlt_frame_pop_service( frame );
+       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
 
        // Retrieve the aspect ratio
-       double aspect_ratio = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( this ) );
+       double aspect_ratio = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( frame ) );
        double consumer_aspect = mlt_profile_sar( mlt_service_profile( MLT_FILTER_SERVICE( filter ) ) );
 
        // 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" );
+               *width = profile->width;
+               *height = profile->height;
        }
 
        // Assign requested width/height from our subordinate
@@ -204,18 +202,25 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        // Reset the aspect ratio
        mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
 
+       // XXX: This is a hack, but it forces the force_full_luma to apply by doing a RGB
+       // conversion because range scaling only occurs on YUV->RGB. And we do it here,
+       // after the deinterlace filter, which only operates in YUV to avoid a YUV->RGB->YUV->?.
+       // Instead, it will go YUV->RGB->?.
+       if ( mlt_properties_get_int( properties, "force_full_luma" ) )
+               *format = mlt_image_rgb24a;
+
        // 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 );
+               return mlt_frame_get_image( frame, 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" );
+               int normalised_width = profile->width;
+               int normalised_height = profile->height;
+               int real_width = mlt_properties_get_int( properties, "meta.media.width" );
+               int real_height = mlt_properties_get_int( properties, "meta.media.height" );
                if ( real_width == 0 )
                        real_width = mlt_properties_get_int( properties, "width" );
                if ( real_height == 0 )
@@ -242,7 +247,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                oheight = rint( scaled_height * oheight / normalised_height );
 
                // Tell frame we have conformed the aspect to the consumer
-               mlt_frame_set_aspect_ratio( this, consumer_aspect );
+               mlt_frame_set_aspect_ratio( frame, consumer_aspect );
        }
 
        mlt_properties_set_int( properties, "distort", 0 );
@@ -254,13 +259,13 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        // Now get the image
        if ( *format == mlt_image_yuv422 )
                owidth -= owidth % 2;
-       error = mlt_frame_get_image( this, image, format, &owidth, &oheight, writable );
+       error = mlt_frame_get_image( frame, image, format, &owidth, &oheight, writable );
 
        if ( error == 0 && *image )
        {
                int bpp;
                mlt_image_format_size( *format, owidth, oheight, &bpp );
-               *image = frame_resize_image( this, *width, *height, bpp );
+               *image = frame_resize_image( frame, *width, *height, bpp );
        }
 
        return error;
@@ -269,13 +274,13 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 /** Filter processing.
 */
 
-static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+static mlt_frame filter_process( mlt_filter filter, 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 );
+       mlt_frame_push_service( frame, filter );
 
        // Push the get_image method on to the stack
        mlt_frame_push_get_image( frame, filter_get_image );
@@ -288,10 +293,10 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 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 )
+       mlt_filter filter = calloc( 1, sizeof( struct mlt_filter_s ) );
+       if ( mlt_filter_init( filter, filter ) == 0 )
        {
-               this->process = filter_process;
+               filter->process = filter_process;
        }
-       return this;
+       return filter;
 }
index 54a4693c8921eb92377945bcd3c414a9ed756978..b5adba315b159e22ad61d41b3d2a89167cc50f31 100644 (file)
@@ -143,21 +143,17 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                        // Get the a and b frame properties
                        mlt_properties a_props = MLT_FRAME_PROPERTIES( frame );
                        mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
+                       mlt_profile profile = mlt_service_profile( service );
 
                        // 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" ) );
+                               mlt_frame_set_aspect_ratio( b_frame, mlt_profile_sar( profile ) );
                        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" ) );
+                               mlt_frame_set_aspect_ratio( frame, mlt_profile_sar( profile ) );
 
                        if ( mlt_properties_get_int( properties, "distort" ) )
                        {
index fc9d8b1abfbfaeb1a6512910a665e2cbb4a68179..2956cc3ffe59c1dedc377ed8120f904efa700d49 100644 (file)
@@ -1,4 +1,7 @@
-http://*=avformat
+http://*=avformat,webvfx:plain:
+https://*=webvfx:plain:
+plain:http://*=webvfx:plain:
+plain:https://*=webvfx:plain:
 <?xml*=xml-string
 *.mlt=xml
 *.westley=xml
@@ -7,16 +10,19 @@ http://*=avformat
 *.inigo=melt_file
 *.asf=avformat
 *.avi=mcdv,avformat,libdv
-*.bmp=pixbuf,qimage,sdl_image
+*.bmp=pixbuf,qimage
 *.dv=mcdv,avformat,libdv
 *.dif=mcdv,avformat,libdv
 *.exr=qimage
-*.gif=pixbuf,qimage,sdl_image
+*.gif=pixbuf,qimage
 *.graphics=xml
+*.htm=webvfx:plain:
+*.html=webvfx:plain:
 *.jfx=xml
 *.jef=xml
-*.jpg=pixbuf,qimage,sdl_image
-*.jpeg=pixbuf,qimage,sdl_image
+*.jpg=pixbuf,qimage
+*.jpeg=pixbuf,qimage
+*.kdenlivetitle=kdenlivetitle
 *.kino=xml
 *.mp3=avformat
 *.mov=mcdv,avformat,libdv
@@ -24,21 +30,21 @@ http://*=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
+*.pcx=pixbuf,qimage
+*.pgm=pgm,pixbuf,qimage
+*.png=pixbuf,qimage
 *.psd=qimage
+*.qml=webvfx:plain:
 *.story=xml
 *.svg=pixbuf,qimage
-*.swf=swfdec,avformat
-*.tga=pixbuf,qimage,sdl_image
-*.tif=pixbuf,qimage,sdl_image
-*.tiff=pixbuf,qimage,sdl_image
+*.swf=avformat,swfdec
+*.tga=pixbuf,qimage
+*.tif=pixbuf,qimage
+*.tiff=pixbuf,qimage
 *.txt=pango
 *.vob=mcmpeg,avformat
 *.wav=avformat
 *.wmv=avformat
-*.xcf=qimage,sdl_image
+*.xcf=qimage
 *.xml=xml
-*.kdenlivetitle=kdenlivetitle
 *=avformat
index d7967eddb238dfdb48ef2b62acabc848008de82a..c586a176a32f4ca2c395ff72fcc075c1a3c31aee 100644 (file)
@@ -7,11 +7,11 @@
 # the second and third are applied as applicable).
 
 # image filters
-crop=crop:1
 deinterlace=deinterlace,avdeinterlace
-rescaler=swscale,gtkrescale,rescale
 fieldorder=fieldorder
-resizer=resize
+crop=movit.crop,crop:1
+rescaler=movit.resample,swscale,gtkrescale,rescale
+resizer=movit.resize,resize
 
 # audio filters
 channels=audiochannels
index 91c354b134d296433ed241dd400b85e60f589a27..670bd403123f4cd3d971941f524dc2b46a481c45 100644 (file)
@@ -48,7 +48,7 @@ mlt_producer producer_colour_init( mlt_profile profile, mlt_service_type type, c
                producer->close = ( mlt_destructor )producer_close;
 
                // Set the default properties
-               mlt_properties_set( properties, "resource", colour == NULL ? "0x000000ff" : colour );
+               mlt_properties_set( properties, "resource", ( !colour || !strcmp( colour, "" ) ) ? "0x000000ff" : colour );
                mlt_properties_set( properties, "_resource", "" );
                mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
                
@@ -80,6 +80,12 @@ rgba_color parse_color( char *color, unsigned int color_int )
                result.g = 0x00;
                result.b = 0xff;
        }
+       else if ( !strcmp( color, "black" ) )
+       {
+               result.r = 0x00;
+               result.g = 0x00;
+               result.b = 0x00;
+       }
        else if ( strcmp( color, "white" ) )
        {
                result.r = ( color_int >> 24 ) & 0xff;
@@ -221,8 +227,8 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        mlt_frame_set_image( frame, *buffer, size, mlt_pool_release );
        mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release );
        mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
-       mlt_properties_set_int( properties, "real_width", *width );
-       mlt_properties_set_int( properties, "real_height", *height );
+       mlt_properties_set_int( properties, "meta.media.width", *width );
+       mlt_properties_set_int( properties, "meta.media.height", *height );
 
 
        return 0;
@@ -249,7 +255,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
                // 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_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) );
+               mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
 
                // colour is an alias for resource
                if ( mlt_properties_get( producer_props, "colour" ) != NULL )
index 1f6e812a0961a199cd10806c577e822e4db41845..794843d0c8cc9e4526262e3d7f239f995098b5eb 100644 (file)
@@ -89,13 +89,14 @@ static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format,
                mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
                memcpy( new_buffer, *buffer, size );
                *buffer = new_buffer;
+               cx->audio_position = mlt_frame_get_position( nested_frame );
        }
        else
        {
                // otherwise return no samples
                *samples = 0;
+               *buffer = NULL;
        }
-       cx->audio_position = mlt_frame_get_position( nested_frame );
 
        return result;
 }
@@ -141,6 +142,7 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
 
                // Since we control the seeking, prevent it from seeking on its own
                mlt_producer_set_speed( cx->producer, 0 );
+               cx->audio_position = -1;
 
                // We will encapsulate a consumer
                cx->consumer = mlt_consumer_new( cx->profile );
@@ -158,7 +160,7 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
 
        // Generate a frame
        *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
-       if ( frame )
+       if ( *frame )
        {
                // Seek the producer to the correct place
                // Calculate our positions
@@ -191,8 +193,8 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
                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, "meta.media.width", cx->profile->width );
+               mlt_properties_set_int( frame_props, "meta.media.height", cx->profile->height );
                mlt_properties_set_int( frame_props, "progressive", cx->profile->progressive );
        }
 
index 2600b62cc46b6374ea85a9fc916dd2b3921051d8..ccf2e4469fb337fd870ba1b4b1dd09eafc6d5511 100644 (file)
@@ -40,7 +40,23 @@ static mlt_producer create_from( mlt_profile profile, char *file, char *services
                char *p = strchr( service, ',' );
                if ( p != NULL )
                        *p ++ = '\0';
-               producer = mlt_factory_producer( profile, service, file );
+
+               // If  the service name has a colon as field delimiter, then treat the
+               // second field as a prefix for the file/url.
+               char *prefix = strchr( service, ':' );
+               if ( prefix )
+               {
+                       *prefix ++ = '\0';
+                       char* prefix_file = calloc( 1, strlen( file ) + strlen( prefix ) + 1 );
+                       strcpy( prefix_file, prefix );
+                       strcat( prefix_file, file );
+                       producer = mlt_factory_producer( profile, service, prefix_file );
+                       free( prefix_file );
+               }
+               else
+               {
+                       producer = mlt_factory_producer( profile, service, file );
+               }
                service = p;
        }
        while ( producer == NULL && service != NULL );
@@ -90,11 +106,21 @@ static mlt_producer create_producer( mlt_profile profile, char *file )
                        p ++;
                }
 
+               // Chop off the query string
+               p = strrchr( lookup, '?' );
+               if ( p )
+                       p[0] = '\0';
+
+               // Strip file:// prefix
+               p = lookup;
+               if ( strncmp( lookup, "file://", 7 ) == 0 )
+                       p += 7;
+                       
                // 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 )
+                       if ( fnmatch( name, p, 0 ) == 0 )
                                result = create_from( profile, file, mlt_properties_get_value( dictionary, i ) );
                }       
 
@@ -143,7 +169,7 @@ static void create_filter( mlt_profile profile, mlt_producer producer, char *eff
 
        // The swscale and avcolor_space filters require resolution as arg to test compatibility
        if ( strncmp( effect, "swscale", 7 ) == 0 || strncmp( effect, "avcolo", 6 ) == 0 )
-               arg = (char*) mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "_real_width" );
+               arg = (char*) mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( producer ), "meta.media.width" );
 
        mlt_filter filter = mlt_factory_filter( profile, id, arg );
        if ( filter != NULL )
@@ -202,6 +228,7 @@ mlt_producer producer_loader_init( mlt_profile profile, mlt_service_type type, c
 
        // Attach filters if we have a producer and it isn't already xml'd :-)
        if ( producer && strcmp( id, "abnormal" ) &&
+               strncmp( arg, "abnormal:", 9 ) &&
                mlt_properties_get( properties, "xml" ) == NULL &&
                mlt_properties_get( properties, "_xml" ) == NULL &&
                mlt_properties_get( properties, "loader_normalised" ) == NULL )
@@ -211,6 +238,9 @@ mlt_producer producer_loader_init( mlt_profile profile, mlt_service_type type, c
        {
                // Always let the image and audio be converted
                int created = 0;
+               // movit.convert skips setting the frame->convert_image pointer if GLSL cannot be used.
+               create_filter( profile, producer, "movit.convert", &created );
+               // avcolor_space and imageconvert only set frame->convert_image if it has not been set.
                create_filter( profile, producer, "avcolor_space", &created );
                if ( !created )
                        create_filter( profile, producer, "imageconvert", &created );
index 1a5789fd5477da2029bb60c90079ad3648803f2f..b3ba3a14710da58d331c44987c3c700d1584097d 100644 (file)
@@ -41,6 +41,7 @@ mlt_producer producer_melt_file_init( mlt_profile profile, mlt_service_type type
                        if ( strcmp( temp, "" ) )
                                args[ count ++ ] = strdup( temp );
                }
+               fclose( input );
        }
 
        mlt_producer result = producer_melt_init( profile, type, id, args );
@@ -126,7 +127,7 @@ mlt_producer producer_melt_init( mlt_profile profile, mlt_service_type type, con
        int track = 0;
        mlt_producer producer = NULL;
        mlt_tractor mix = NULL;
-       mlt_playlist playlist = mlt_playlist_init( );
+       mlt_playlist playlist = mlt_playlist_new( profile );
        mlt_properties group = mlt_properties_new( );
        mlt_tractor tractor = mlt_tractor_new( );
        mlt_properties properties = MLT_TRACTOR_PROPERTIES( tractor );
@@ -373,7 +374,11 @@ mlt_producer producer_melt_init( mlt_profile profile, mlt_service_type type, con
                        if ( producer != NULL && !mlt_producer_is_cut( producer ) )
                                mlt_playlist_append( playlist, producer );
                        producer = NULL;
-                       mlt_playlist_blank( playlist, atof( argv[ ++ i ] ) );
+                       if ( strchr( argv[ i + 1 ], ':' ) )
+                               mlt_playlist_blank_time( playlist, argv[ ++ i ] );
+                       else
+                               // support for legacy where plain int is an out point instead of length
+                               mlt_playlist_blank( playlist, atof( argv[ ++ i ] ) );
                }
                else if ( !strcmp( argv[ i ], "-track" ) ||
                                  !strcmp( argv[ i ], "-null-track" ) ||
@@ -391,7 +396,7 @@ mlt_producer producer_melt_init( mlt_profile profile, mlt_service_type type, con
                        {
                                mlt_multitrack_connect( multitrack, MLT_PLAYLIST_PRODUCER( playlist ), track ++ );
                                track_service( field, playlist, ( mlt_destructor )mlt_playlist_close );
-                               playlist = mlt_playlist_init( );
+                               playlist = mlt_playlist_new( profile );
                        }
                        if ( playlist != NULL )
                        {
@@ -439,7 +444,8 @@ mlt_producer producer_melt_init( mlt_profile profile, mlt_service_type type, con
                                backtrack = 1;
                        }
 
-                       while ( argv[ i ] != NULL && strchr( argv[ i ], '=' ) )
+                       while ( argv[ i ] != NULL && strchr( argv[ i ], '=' ) &&
+                               ( !strchr( argv[ i ], ':' ) || strchr( argv[ i ], ':' ) > strchr( argv[ i ], '=' ) ) )
                        {
                                i ++;
                                backtrack = 1;
@@ -457,7 +463,7 @@ mlt_producer producer_melt_init( mlt_profile profile, mlt_service_type type, con
        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 ), "_melt_first" ) || 
+       if ( playlist && !mlt_properties_get_int( MLT_PLAYLIST_PROPERTIES( playlist ), "_melt_first" ) || 
                  mlt_producer_get_playtime( MLT_PLAYLIST_PRODUCER( playlist ) ) > 0 )
                mlt_multitrack_connect( multitrack, MLT_PLAYLIST_PRODUCER( playlist ), track );
 
index 3c676f41dc089ed5e5aa524471470d03063f1b9c..0e39eb7a3097e2d4d78f190f7665b3bc0b3c6993 100644 (file)
@@ -146,7 +146,8 @@ static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index
                mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
 
                // Aspect ratio is whatever it needs to be
-               mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this ), "aspect_ratio" ) );
+               mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( this ) );
+               mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
 
                // Set producer-specific frame properties
                mlt_properties_set_int( properties, "progressive", 1 );
index 929d663369ec0c038337a91f98c70bdd00fc6d1d..cda58c046541247b208beed091b8484fdfb0c3f1 100644 (file)
@@ -40,7 +40,7 @@ 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 );
+       producer_ppm this = calloc( 1, sizeof( struct producer_ppm_s ) );
        if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
        {
                mlt_producer producer = &this->parent;
index f7054acb33fce012675525af2445444e64181b95..cd0183b5bdd2be088622084d1867001b55bb9ac2 100644 (file)
@@ -66,9 +66,9 @@ static int alignment_parse( char* align )
 /** Calculate real geometry.
 */
 
-static void geometry_calculate( mlt_transition this, struct geometry_s *output, double position )
+static void geometry_calculate( mlt_transition self, struct geometry_s *output, double position )
 {
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
        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" );
@@ -87,19 +87,19 @@ static void geometry_calculate( mlt_transition this, struct geometry_s *output,
        mlt_geometry_fetch( geometry, &output->item, position );
 }
 
-static mlt_geometry transition_parse_keys( mlt_transition this, int normalised_width, int normalised_height )
+static mlt_geometry transition_parse_keys( mlt_transition self, 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 );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
 
        // Create an empty geometries object
        mlt_geometry geometry = mlt_geometry_init( );
 
        // Get the duration
-       mlt_position length = mlt_transition_get_length( this );
+       mlt_position length = mlt_transition_get_length( self );
        double cycle = mlt_properties_get_double( properties, "cycle" );
 
        // Get the new style geometry string
@@ -174,10 +174,10 @@ static void alignment_calculate( struct geometry_s *geometry )
 /** Calculate the position for this frame.
 */
 
-static int position_calculate( mlt_transition this, mlt_position position )
+static int position_calculate( mlt_transition self, mlt_position position )
 {
        // Get the in and out position
-       mlt_position in = mlt_transition_get_in( this );
+       mlt_position in = mlt_transition_get_in( self );
 
        // Now do the calcs
        return position - in;
@@ -355,7 +355,7 @@ static void luma_read_yuv422( uint8_t *image, uint16_t **map, int width, int hei
 
 static inline int calculate_mix( uint16_t *luma, int j, int softness, int weight, int alpha, uint32_t step )
 {
-       return ( ( luma ? smoothstep( luma[ j ], luma[ j ] + softness, step ) : weight ) * alpha ) >> 8;
+       return ( ( luma ? smoothstep( luma[ j ], luma[ j ] + softness, step ) : weight ) * ( alpha + 1 ) ) >> 8;
 }
 
 static inline uint8_t sample_mix( uint8_t dest, uint8_t src, int mix )
@@ -365,13 +365,28 @@ static inline uint8_t sample_mix( uint8_t dest, uint8_t src, int mix )
 
 /** Composite a source line over a destination line
 */
+#if defined(USE_SSE) && defined(ARCH_X86_64)
+void composite_line_yuv_sse2_simple(uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight);
+#endif
 
-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, uint32_t step )
+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, uint32_t step )
 {
-       register int j;
+       register int j = 0;
        register int mix;
 
-       for ( j = 0; j < width; j ++ )
+#if defined(USE_SSE) && defined(ARCH_X86_64)
+       if ( !luma && width > 7 )
+       {
+               composite_line_yuv_sse2_simple(dest, src, width, alpha_b, alpha_a, weight);
+               j = width - width % 8;
+               dest += j * 2;
+               src += j * 2;
+               alpha_a += j;
+               alpha_b += j;
+       }
+#endif
+
+       for ( ; j < width; j ++ )
        {
                mix = calculate_mix( luma, j, soft, weight, *alpha_b ++, step );
                *dest = sample_mix( *dest, *src++, mix );
@@ -445,8 +460,8 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint
        int stride_src = geometry.sw * bpp;
        int stride_dest = width_dest * bpp;
        int i_softness = ( 1 << 16 ) * softness;
-       int weight = ( ( 1 << 16 ) - 1 ) * geometry.item.mix / 100;
-       uint32_t luma_step = ( ( 1 << 16 ) - 1 ) * geometry.item.mix / 100 * ( 1.0 + softness );
+       int weight = ( ( 1 << 16 ) * geometry.item.mix + 50 ) / 100;
+       uint32_t luma_step = ( ( ( 1 << 16 ) - 1 ) * geometry.item.mix + 50 ) / 100 * ( 1.0 + softness );
 
        // Adjust to consumer scale
        int x = rint( geometry.item.x * width_dest / geometry.nw );
@@ -506,7 +521,7 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint
        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;
+       p_dest += x * bpp + y * stride_dest;
 
        // offset pointer into alpha channel based upon cropping
        alpha_b += x_src + y_src * stride_src / bpp;
@@ -546,7 +561,6 @@ static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint
        if ( uneven_x != uneven_x_src )
        {
                p_src += 2;
-               width_src -= 2;
                alpha_b += 1;
        }
 
@@ -592,7 +606,7 @@ scale_luma ( uint16_t *dest_buf, int dest_width, int dest_height, const uint16_t
        }
 }
 
-static uint16_t* get_luma( mlt_transition this, mlt_properties properties, int width, int height )
+static uint16_t* get_luma( mlt_transition self, mlt_properties properties, int width, int height )
 {
        // The cached luma map information
        int luma_width = mlt_properties_get_int( properties, "_luma.width" );
@@ -679,7 +693,7 @@ static uint16_t* get_luma( mlt_transition this, mlt_properties properties, int w
                                char *factory = mlt_properties_get( properties, "factory" );
        
                                // Create the producer
-                               mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
+                               mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( self ) );
                                mlt_producer producer = mlt_factory_producer( profile, factory, resource );
        
                                // If we have one
@@ -742,26 +756,24 @@ static uint16_t* get_luma( mlt_transition this, mlt_properties properties, int w
 /** 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 )
+static int get_b_frame_image( mlt_transition self, 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 );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
        uint8_t resize_alpha = mlt_properties_get_int( b_props, "resize_alpha" );
-       double consumer_ar = mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(this) ) );
+       double output_ar = mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(self) ) );
 
        // 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" );
+               int real_width = get_value( b_props, "meta.media.width", "width" );
+               int real_height = get_value( b_props, "meta.media.height", "height" );
                double input_ar = mlt_properties_get_double( b_props, "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;
@@ -773,16 +785,14 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **
                // 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" );
+               int real_width = get_value( b_props, "meta.media.width", "width" );
+               int real_height = get_value( b_props, "meta.media.height", "height" );
                double input_ar = mlt_properties_get_double( b_props, "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__,
+// fprintf(stderr, "%s: scaled %dx%d norm %dx%d real %dx%d output_ar %f\n", __FILE__,
 // scaled_width, scaled_height, normalised_width, normalised_height, real_width, real_height,
-// background_ar, output_ar);
+// output_ar);
 
                // Now ensure that our images fit in the normalised frame
                if ( scaled_width > normalised_width )
@@ -855,7 +865,7 @@ static int get_b_frame_image( mlt_transition this, mlt_frame b_frame, uint8_t **
        return ret && image != NULL;
 }
 
-static void crop_calculate( mlt_transition this, mlt_properties properties, struct geometry_s *result, double position )
+static void crop_calculate( mlt_transition self, mlt_properties properties, struct geometry_s *result, double position )
 {
        // Initialize panning info
        result->x_src = 0;
@@ -866,7 +876,7 @@ static void crop_calculate( mlt_transition this, mlt_properties properties, stru
                if ( !crop )
                {
                        crop = mlt_geometry_init();
-                       mlt_position length = mlt_transition_get_length( this );
+                       mlt_position length = mlt_transition_get_length( self );
                        double cycle = mlt_properties_get_double( properties, "cycle" );
 
                        // Allow a geometry repeat cycle
@@ -898,10 +908,10 @@ static void crop_calculate( mlt_transition this, mlt_properties properties, stru
        }
 }
 
-static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s *result, mlt_frame a_frame, double position )
+static mlt_geometry composite_calculate( mlt_transition self, struct geometry_s *result, mlt_frame a_frame, double position )
 {
        // Get the properties from the transition
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
 
        // Get the properties from the frame
        mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
@@ -910,8 +920,9 @@ static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s
        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" );
+       mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( self ) );
+       int normalised_width = profile->width;
+       int normalised_height = profile->height;
 
        char *name = mlt_properties_get( properties, "_unique_id" );
        char key[ 256 ];
@@ -927,14 +938,14 @@ static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s
                if ( start == NULL )
                {
                        // Parse the transitions properties
-                       start = transition_parse_keys( this, normalised_width, normalised_height );
+                       start = transition_parse_keys( self, 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
                {
-                       mlt_position length = mlt_transition_get_length( this );
+                       mlt_position length = mlt_transition_get_length( self );
                        double cycle = mlt_properties_get_double( properties, "cycle" );
                        if ( cycle > 1 )
                                length = cycle;
@@ -944,7 +955,7 @@ static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s
                }
 
                // Do the calculation
-               geometry_calculate( this, result, position );
+               geometry_calculate( self, result, position );
 
                // Assign normalised info
                result->nw = normalised_width;
@@ -955,15 +966,15 @@ static mlt_geometry composite_calculate( mlt_transition this, struct geometry_s
        result->halign = alignment_parse( mlt_properties_get( properties, "halign" ) );
        result->valign = alignment_parse( mlt_properties_get( properties, "valign" ) );
 
-       crop_calculate( this, properties, result, position );
+       crop_calculate( self, properties, result, position );
 
        return start;
 }
 
-mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_position frame_position )
+mlt_frame composite_copy_region( mlt_transition self, mlt_frame a_frame, mlt_position frame_position )
 {
        // Create a frame to return
-       mlt_frame b_frame = mlt_frame_init( MLT_TRANSITION_SERVICE( this ) );
+       mlt_frame b_frame = mlt_frame_init( MLT_TRANSITION_SERVICE( self ) );
 
        // Get the properties of the a frame
        mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
@@ -972,10 +983,10 @@ mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_pos
        mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
 
        // Get the position
-       int position = position_calculate( this, frame_position );
+       int position = position_calculate( self, frame_position );
 
        // Get the unique id of the transition
-       char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( this ), "_unique_id" );
+       char *name = mlt_properties_get( MLT_TRANSITION_PROPERTIES( self ), "_unique_id" );
        char key[ 256 ];
 
        // Destination image
@@ -1007,7 +1018,7 @@ mlt_frame composite_copy_region( mlt_transition this, mlt_frame a_frame, mlt_pos
        struct geometry_s result;
 
        // Calculate the region now
-       composite_calculate( this, &result, a_frame, position );
+       composite_calculate( self, &result, a_frame, position );
 
        // Need to scale down to actual dimensions
        x = rint( result.item.x * width / result.nw );
@@ -1086,7 +1097,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        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 );
+       mlt_transition self = mlt_frame_pop_service( a_frame );
 
        // Get in and out
        double position = mlt_deque_pop_back_double( MLT_FRAME_IMAGE_STACK( a_frame ) );
@@ -1094,7 +1105,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        int in = mlt_frame_pop_service_int( a_frame );
 
        // Get the properties from the transition
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
 
        // TODO: clean up always_active behaviour
        if ( mlt_properties_get_int( properties, "always_active" ) )
@@ -1120,13 +1131,14 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                struct geometry_s result;
 
                // Calculate the position
-               double delta = mlt_transition_get_progress_delta( this, a_frame );
-               mlt_position length = mlt_transition_get_length( this );
+               double delta = mlt_transition_get_progress_delta( self, a_frame );
+               mlt_position length = mlt_transition_get_length( self );
 
                // Get the image from the b frame
                uint8_t *image_b = NULL;
-               int width_b = *width > 0 ? *width : mlt_properties_get_int( a_props, "normalised_width" );
-               int height_b = *height > 0 ? *height : mlt_properties_get_int( a_props, "normalised_height" );
+               mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( self ) );
+               int width_b = *width > 0 ? *width : profile->width;
+               int height_b = *height > 0 ? *height : profile->height;
        
                // Vars for alphas
                uint8_t *alpha_a = NULL;
@@ -1135,9 +1147,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                // Do the calculation
                // NB: Locks needed here since the properties are being modified
                int invert = mlt_properties_get_int( properties, "invert" );
-               mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
-               composite_calculate( this, &result, invert ? b_frame : a_frame, position );
-               mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
+               mlt_service_lock( MLT_TRANSITION_SERVICE( self ) );
+               composite_calculate( self, &result, invert ? b_frame : a_frame, position );
+               mlt_service_unlock( MLT_TRANSITION_SERVICE( self ) );
 
                // Manual option to deinterlace
                if ( mlt_properties_get_int( properties, "deinterlace" ) )
@@ -1159,7 +1171,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                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 );
+                       get_b_frame_image( self, 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 );
                }
@@ -1195,7 +1207,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                        height_b = mlt_properties_get_int( a_props, "dest_height" );
                }
 
-               if ( *image != image_b && ( ( invert ? 0 : image_b ) || get_b_frame_image( this, b_frame, invert ? image : &image_b, &width_b, &height_b, &result ) == 0 ) )
+               if ( *image != image_b && ( ( invert ? 0 : image_b ) || get_b_frame_image( self, b_frame, invert ? image : &image_b, &width_b, &height_b, &result ) == 0 ) )
                {
                        uint8_t *dest = *image;
                        uint8_t *src = image_b;
@@ -1205,9 +1217,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                        int field;
                        
                        double luma_softness = mlt_properties_get_double( properties, "softness" );
-                       mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
-                       uint16_t *luma_bitmap = get_luma( this, properties, width_b, height_b );
-                       mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
+                       mlt_service_lock( MLT_TRANSITION_SERVICE( self ) );
+                       uint16_t *luma_bitmap = get_luma( self, properties, width_b, height_b );
+                       mlt_service_unlock( MLT_TRANSITION_SERVICE( self ) );
                        char *operator = mlt_properties_get( properties, "operator" );
 
                        alpha_b = alpha_b == NULL ? mlt_frame_get_alpha_mask( b_frame ) : alpha_b;
@@ -1239,9 +1251,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                                
                                // 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, invert ? b_frame : a_frame, field_position );
-                               mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
+                               mlt_service_lock( MLT_TRANSITION_SERVICE( self ) );
+                               composite_calculate( self, &result, invert ? b_frame : a_frame, field_position );
+                               mlt_service_unlock( MLT_TRANSITION_SERVICE( self ) );
 
                                if ( mlt_properties_get_int( properties, "titles" ) )
                                {
@@ -1286,14 +1298,14 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
 /** Composition transition processing.
 */
 
-static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
+static mlt_frame composite_process( mlt_transition self, 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 )
+       if ( mlt_properties_get_int(  MLT_TRANSITION_PROPERTIES( self ), "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 ) ) );
+               mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( self ), "in" ) );
+               mlt_frame_push_service_int( a_frame, mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( self ), "out" ) );
+               mlt_deque_push_back_double( MLT_FRAME_IMAGE_STACK( a_frame ), position_calculate( self, mlt_frame_get_position( a_frame ) ) );
        }
        else
        {
@@ -1303,7 +1315,7 @@ static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_
                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_service( a_frame, self );
        mlt_frame_push_frame( a_frame, b_frame );
        mlt_frame_push_get_image( a_frame, transition_get_image );
        return a_frame;
@@ -1314,12 +1326,12 @@ static mlt_frame composite_process( mlt_transition this, mlt_frame a_frame, mlt_
 
 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_transition self = calloc( 1, sizeof( struct mlt_transition_s ) );
+       if ( self != NULL && mlt_transition_init( self, NULL ) == 0 )
        {
-               mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES( self );
                
-               this->process = composite_process;
+               self->process = composite_process;
                
                // Default starting motion and zoom
                mlt_properties_set( properties, "start", arg != NULL ? arg : "0/0:100%x100%" );
@@ -1336,5 +1348,5 @@ mlt_transition transition_composite_init( mlt_profile profile, mlt_service_type
                // Inform apps and framework that this is a video only transition
                mlt_properties_set_int( properties, "_transition_type", 1 );
        }
-       return this;
+       return self;
 }
index 6523b95b4f5e3d007e48fd55c283d874174013de..416ab5603d5b5dd10293dd7238991613fae45762 100644 (file)
@@ -27,5 +27,7 @@ extern mlt_transition transition_composite_init( mlt_profile profile, mlt_servic
 
 // Courtesy functionality - allows regionalised filtering
 extern mlt_frame composite_copy_region( mlt_transition, mlt_frame, mlt_position );
+extern 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, uint32_t step );
 
 #endif
index 7e026da865ba0a59aa0b4b18cebf2eeba85e09cd..90aaf5079646e9e7ce53ffc69070c07fc8d7dfa4 100644 (file)
@@ -117,7 +117,7 @@ parameters:
       
       Mix is always a 2 digit percentage, defaults to 100.
     type: geometry
-    default: "85%/5%:10%x10%"
+    default: "0%/0%:100%x100%"
     readonly: no
     mutable: yes
   - identifier: end
index 437eb9f1b511d585e24e920cfade4c586b958a10..c3263da25b78a620a5984af2c424f52657195085 100644 (file)
 #include <ctype.h>
 #include <string.h>
 #include <math.h>
+#include "transition_composite.h"
 
 static inline int dissolve_yuv( mlt_frame this, mlt_frame that, float weight, int width, int height )
 {
        int ret = 0;
+       int i = height + 1;
        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 );
+       int mix = weight * ( 1 << 16 );
 
        if ( mlt_properties_get( &this->parent, "distort" ) )
                mlt_properties_set( &that->parent, "distort", mlt_properties_get( &this->parent, "distort" ) );
@@ -53,16 +51,14 @@ static inline int dissolve_yuv( mlt_frame this, mlt_frame that, float weight, in
        // 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 )
+       while ( --i )
        {
-               *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;
+               composite_line_yuv( p_dest, p_src, width_src, alpha_src, alpha_dst, mix, NULL, 0, 0 );
+               p_src += width_src << 1;
+               p_dest += width << 1;
+               alpha_src += width_src;
+               alpha_dst += width;
        }
 
        return ret;
index e265366303e69b27f37d554ad8e698b96a401a7e..d40a5041b3dfced7d636147ad38cf4cab7772bfe 100644 (file)
@@ -295,7 +295,7 @@ static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt
 
 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 );
+       mlt_transition this = calloc( 1, sizeof( struct mlt_transition_s ) );
        if ( this != NULL && mlt_transition_init( this, NULL ) == 0 )
        {
                this->process = transition_process;
index 3822df9bbc532b28882e7d234ffe805aa9b0badf..0c2e59727b47e752f109c07d8d404ec5894a2dbb 100644 (file)
@@ -27,7 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-static int create_instance( mlt_transition this, char *name, char *value, int count )
+static int create_instance( mlt_transition transition, char *name, char *value, int count )
 {
        // Return from this function
        int error = 0;
@@ -46,14 +46,15 @@ static int create_instance( mlt_transition this, char *name, char *value, int co
                *arg ++ = '\0';
 
        // Create the filter
-       mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( this ) );
-       filter = mlt_factory_filter( profile, type, arg );
+       mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) );
+       if ( type )
+               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 );
+               // Properties of transition
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
 
                // String to hold the property name
                char id[ 256 ];
@@ -73,6 +74,7 @@ static int create_instance( mlt_transition this, char *name, char *value, int co
 
                // Pass all the key properties on the filter down
                mlt_properties_pass( MLT_FILTER_PROPERTIES( filter ), properties, key );
+               mlt_properties_pass_list( MLT_FILTER_PROPERTIES( filter ), properties, "in, out, length" );
 
                // Ensure that filter is assigned
                mlt_properties_set_data( properties, id, filter, 0, ( mlt_destructor )mlt_filter_close, NULL );
@@ -90,19 +92,19 @@ static int create_instance( mlt_transition this, char *name, char *value, int co
        return error;
 }
 
-static uint8_t *filter_get_alpha_mask( mlt_frame this )
+static uint8_t *filter_get_alpha_mask( mlt_frame frame )
 {
        uint8_t *alpha = NULL;
 
        // Obtain properties of frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        // 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" );
+       int region_width = mlt_properties_get_int( properties, "width" );
+       int region_height = mlt_properties_get_int( properties, "height" );
        uint8_t *image = NULL;
        mlt_image_format format = mlt_image_yuv422;
                                        
@@ -112,27 +114,26 @@ static uint8_t *filter_get_alpha_mask( mlt_frame this )
 
        alpha = mlt_frame_get_alpha_mask( shape_frame );
 
+       int size = region_width * region_height;
+       uint8_t *alpha_duplicate = mlt_pool_alloc( size );
+
        // 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;
+               alpha = alpha_duplicate;
                while ( size -- )
                {
-                       *p ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 );
+                       *alpha ++ = ( int )( ( ( *image ++ - 16 ) * 299 ) / 255 );
                        image ++;
                }
-               mlt_frame_set_alpha( this, alpha, region_width * region_height, mlt_pool_release );
        }
        else
        {
-               mlt_frame_set_alpha( this, alpha, region_width * region_height, NULL );
+               memcpy( alpha_duplicate, alpha, size );
        }
+       mlt_frame_set_alpha( frame, alpha_duplicate, region_width * region_height, mlt_pool_release );
 
-       this->get_alpha_mask = NULL;
-
-       return alpha;
+       return alpha_duplicate;
 }
 
 /** Do it :-).
@@ -147,12 +148,15 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
        mlt_frame b_frame = mlt_frame_pop_frame( frame );
 
        // Get the watermark transition object
-       mlt_transition this = mlt_frame_pop_service( frame );
+       mlt_transition transition = mlt_frame_pop_service( frame );
 
        // Get the properties of the transition
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
+
+       // Get the properties of the a frame
+       mlt_properties a_props = MLT_FRAME_PROPERTIES( frame );
 
-       mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
+       mlt_service_lock( MLT_TRANSITION_SERVICE( transition ) );
 
        // Get the composite from the transition
        mlt_transition composite = mlt_properties_get_data( properties, "composite", NULL );
@@ -161,13 +165,13 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
        mlt_filter filter = mlt_properties_get_data( properties, "_filter_0", NULL );
 
        // Get the position
-       mlt_position position = mlt_transition_get_position( this, frame );
+       mlt_position position = mlt_transition_get_position( transition, frame );
 
        // 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 ) );
+               mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) );
                composite = mlt_factory_transition( profile, "composite", NULL );
 
                // If we have one
@@ -216,7 +220,7 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
                                char *value = mlt_properties_get_value( properties, i );
 
                                // Create an instance
-                               if ( create_instance( this, name, value, count ) == 0 )
+                               if ( create_instance( transition, name, value, count ) == 0 )
                                        count ++;
                        }
                }
@@ -264,8 +268,8 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
                }
        }
 
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "width", *width );
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "height", *height );
+       mlt_properties_set_int( a_props, "width", *width );
+       mlt_properties_set_int( a_props, "height", *height );
 
        // Only continue if we have both filter and composite
        if ( composite != NULL )
@@ -290,14 +294,19 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 
                        // Ensure a destructor
                        char *name = mlt_properties_get( properties, "_unique_id" );
-                       mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
+                       mlt_properties_set_data( a_props, name, b_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
                }
 
+               // Properties of the B frame
+               mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
+
                // filter_only prevents copying the alpha channel of the shape to the output frame
                // by compositing filtered frame over itself
                if ( mlt_properties_get_int( properties, "filter_only" ) )
                {
+                       char *name = mlt_properties_get( properties, "_unique_id" );
                        frame = composite_copy_region( composite, b_frame, position );
+                       mlt_properties_set_data( b_props, name, frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
                }
 
                // Make sure the filter is in the correct position
@@ -345,7 +354,7 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
                                        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 ) );
+                               mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) );
                                producer = mlt_factory_producer( profile, factory, resource );
 
                                // If we have one
@@ -378,7 +387,7 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
                                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 );
+                                       mlt_properties_set_data( b_props, "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;
@@ -390,7 +399,7 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
                error = mlt_frame_get_image( frame, image, format, width, height, 0 );
        }
 
-       mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
+       mlt_service_unlock( MLT_TRANSITION_SERVICE( transition ) );
 
        return error;
 }
@@ -398,10 +407,10 @@ static int transition_get_image( mlt_frame frame, uint8_t **image, mlt_image_for
 /** Filter processing.
 */
 
-static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt_frame b_frame )
+static mlt_frame transition_process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
 {
        // Push the transition on to the frame
-       mlt_frame_push_service( a_frame, this );
+       mlt_frame_push_service( a_frame, transition );
 
        // Push the b_frame on to the stack
        mlt_frame_push_frame( a_frame, b_frame );
@@ -419,16 +428,16 @@ static mlt_frame transition_process( mlt_transition this, mlt_frame a_frame, mlt
 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( );
+       mlt_transition transition = mlt_transition_new( );
 
        // Further initialisation
-       if ( this != NULL )
+       if ( transition != NULL )
        {
                // Get the properties from the transition
-               mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
 
                // Assign the transition process method
-               this->process = transition_process;
+               transition->process = transition_process;
 
                // Default factory
                mlt_properties_set( properties, "factory", mlt_environment( "MLT_PRODUCER" ) );
@@ -441,6 +450,6 @@ mlt_transition transition_region_init( mlt_profile profile, mlt_service_type typ
        }
 
        // Return the transition
-       return this;
+       return transition;
 }
 
index b04ff393b60d9d0e1856913e86a9800e65f32698..c9798b4fa002499a67a1aa8026e5faecc14937c1 100755 (executable)
@@ -7,13 +7,21 @@ include ../../../config.mak
 TARGET = ../libmltdecklink$(LIBSUF)
 
 OBJS = consumer_decklink.o \
-       producer_decklink.o
+       producer_decklink.o \
+       common.o
 
 ifeq ($(targetos), MinGW)
-OBJS += DeckLinkAPI_i.o
+CFLAGS += -Iwin
+OBJS += win/DeckLinkAPI_i.o
 LDFLAGS += -lole32
 else
-OBJS += DeckLinkAPIDispatch.o
+ifeq ($(targetos), Darwin)
+CFLAGS += -Idarwin
+OBJS += darwin/DeckLinkAPIDispatch.o
+else
+CFLAGS += -Ilinux
+OBJS += linux/DeckLinkAPIDispatch.o
+endif
 endif
 
 SRCS := $(OBJS:.o=.cpp)
@@ -37,13 +45,13 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/decklink"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/decklink"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/decklink"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/decklink"
 
 uninstall:
-       rm "$(DESTDIR)$(libdir)/mlt/libmltdecklink$(LIBSUF)" 2> /dev/null || true
-       rm -rf "$(DESTDIR)$(datadir)/mlt/decklink"
+       rm "$(DESTDIR)$(moduledir)/libmltdecklink$(LIBSUF)" 2> /dev/null || true
+       rm -rf "$(DESTDIR)$(mltdatadir)/decklink"
 
 ifneq ($(wildcard .depend),)
 include .depend
diff --git a/src/modules/decklink/common.cpp b/src/modules/decklink/common.cpp
new file mode 100644 (file)
index 0000000..83f5e53
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * common.cpp -- Blackmagic Design DeckLink common functions
+ * Copyright (C) 2012 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 consumer library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "common.h"
+#include <stdlib.h>
+
+#ifdef __DARWIN__
+
+char* getCString( DLString aDLString )
+{
+       char* CString = (char*) malloc( 64 );
+       CFStringGetCString( aDLString, CString, 64, kCFStringEncodingMacRoman );
+       return CString;
+}
+
+void freeCString( char* aCString )
+{
+       if ( aCString ) free( aCString );
+}
+
+void freeDLString( DLString aDLString )
+{
+       if ( aDLString ) CFRelease( aDLString );
+}
+
+#elif defined(WIN32)
+
+char* getCString( DLString aDLString )
+{
+       char* CString = NULL;
+       if ( aDLString )
+       {
+               int size = WideCharToMultiByte( CP_UTF8, 0, aDLString, -1, NULL, 0, NULL, NULL );
+               if (size)
+               {
+                       CString = new char[ size ];
+                       size = WideCharToMultiByte( CP_UTF8, 0, aDLString, -1, CString, size, NULL, NULL );
+                       if ( !size )
+                       {
+                               delete[] CString;
+                               CString = NULL;
+                       }
+               }
+       }
+       return CString;
+}
+
+void freeCString( char* aCString )
+{
+       delete[] aCString;
+}
+
+void freeDLString( DLString aDLString )
+{
+       if ( aDLString ) free( (void*) aDLString );
+}
+
+#else
+
+char* getCString( DLString aDLString )
+{
+       return aDLString? (char*) aDLString : NULL;
+}
+
+void freeCString( char* aCString )
+{
+}
+
+void freeDLString( DLString aDLString )
+{
+       if ( aDLString ) free( (void*) aDLString );
+}
+
+#endif
+
diff --git a/src/modules/decklink/common.h b/src/modules/decklink/common.h
new file mode 100644 (file)
index 0000000..3b48b9c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * common.h -- Blackmagic Design DeckLink common functions
+ * Copyright (C) 2012 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 consumer library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DECKLINK_COMMON_H
+#define DECKLINK_COMMON_H
+
+#ifdef WIN32
+#      include <objbase.h>
+#      include "DeckLinkAPI_h.h"
+       typedef BSTR DLString;
+#else
+#      include "DeckLinkAPI.h"
+#      ifdef __DARWIN__
+               typedef CFStringRef DLString;
+#      else
+               typedef const char* DLString;
+#      endif
+#endif
+
+#define SAFE_RELEASE(V) if (V) { V->Release(); V = NULL; }
+
+char* getCString( DLString aDLString );
+void freeCString( char* aCString );
+void freeDLString( DLString aDLString );
+
+#endif // DECKLINK_COMMON_H
index 39c251f238ef544c7f29870bd8fed5eadba34465..f8ef0cde01214065ce981a699f22294a982378c8 100644 (file)
 #include <sys/time.h>
 #include <limits.h>
 #include <pthread.h>
-#ifdef WIN32
-#include <objbase.h>
-#include "DeckLinkAPI_h.h"
-#else
-#include "DeckLinkAPI.h"
-#endif
+#include "common.h"
 
 static const unsigned PREROLL_MINIMUM = 3;
 
@@ -64,10 +59,10 @@ private:
        IDeckLinkDisplayMode* getDisplayMode()
        {
                mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( getConsumer() ) );
-               IDeckLinkDisplayModeIterator* iter;
-               IDeckLinkDisplayMode* mode;
+               IDeckLinkDisplayModeIterator* iter = NULL;
+               IDeckLinkDisplayMode* mode = NULL;
                IDeckLinkDisplayMode* result = 0;
-               
+
                if ( m_deckLinkOutput->GetDisplayModeIterator( &iter ) == S_OK )
                {
                        while ( !result && iter->Next( &mode ) == S_OK )
@@ -78,31 +73,41 @@ private:
                                m_fps = (double) m_timescale / m_duration;
                                int p = mode->GetFieldDominance() == bmdProgressiveFrame;
                                mlt_log_verbose( getConsumer(), "BMD mode %dx%d %.3f fps prog %d\n", m_width, m_height, m_fps, p );
-                               
+
                                if ( m_width == profile->width && p == profile->progressive
-                                        && m_fps == mlt_profile_fps( profile )
+                                        && (int) m_fps == (int) mlt_profile_fps( profile )
                                         && ( m_height == profile->height || ( m_height == 486 && profile->height == 480 ) ) )
                                        result = mode;
+                               else
+                                       SAFE_RELEASE( mode );
                        }
+                       SAFE_RELEASE( iter );
                }
-               
+
                return result;
        }
-       
+
 public:
        mlt_consumer getConsumer()
                { return &m_consumer; }
-       
+
+       DeckLinkConsumer()
+       {
+               m_displayMode = NULL;
+               m_deckLinkKeyer = NULL;
+               m_deckLinkOutput = NULL;
+               m_deckLink = NULL;
+               m_decklinkFrame = NULL;
+       }
+
        ~DeckLinkConsumer()
        {
-               if ( m_deckLinkKeyer )
-                       m_deckLinkKeyer->Release();
-               if ( m_deckLinkOutput )
-                       m_deckLinkOutput->Release();
-               if ( m_deckLink )
-                       m_deckLink->Release();
+               SAFE_RELEASE( m_displayMode );
+               SAFE_RELEASE( m_deckLinkKeyer );
+               SAFE_RELEASE( m_deckLinkOutput );
+               SAFE_RELEASE( m_deckLink );
        }
-       
+
        bool open( unsigned card = 0 )
        {
                unsigned i = 0;
@@ -122,37 +127,39 @@ public:
                }
 #else
                IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance();
-               
+
                if ( !deckLinkIterator )
                {
                        mlt_log_error( getConsumer(), "The DeckLink drivers not installed.\n" );
                        return false;
                }
 #endif
-               
+
                // Connect to the Nth DeckLink instance
-               do {
-                       if ( deckLinkIterator->Next( &m_deckLink ) != S_OK )
-                       {
-                               mlt_log_error( getConsumer(), "DeckLink card not found\n" );
-                               deckLinkIterator->Release();
-                               return false;
-                       }
-               } while ( ++i <= card );
-               deckLinkIterator->Release();
-               
+               for ( i = 0; deckLinkIterator->Next( &m_deckLink ) == S_OK ; i++)
+               {
+                       if( i == card )
+                               break;
+                       else
+                               SAFE_RELEASE( m_deckLink );
+               }
+               SAFE_RELEASE( deckLinkIterator );
+               if ( !m_deckLink )
+               {
+                       mlt_log_error( getConsumer(), "DeckLink card not found\n" );
+                       return false;
+               }
+
                // Obtain the audio/video output interface (IDeckLinkOutput)
                if ( m_deckLink->QueryInterface( IID_IDeckLinkOutput, (void**)&m_deckLinkOutput ) != S_OK )
                {
                        mlt_log_error( getConsumer(), "No DeckLink cards support output\n" );
-                       m_deckLink->Release();
-                       m_deckLink = 0;
+                       SAFE_RELEASE( m_deckLink );
                        return false;
                }
-               
+
                // Get the keyer interface
                IDeckLinkAttributes *deckLinkAttributes = 0;
-               m_deckLinkKeyer = 0;
                if ( m_deckLink->QueryInterface( IID_IDeckLinkAttributes, (void**) &deckLinkAttributes ) == S_OK )
                {
 #ifdef WIN32
@@ -165,31 +172,32 @@ public:
                                if ( m_deckLink->QueryInterface( IID_IDeckLinkKeyer, (void**) &m_deckLinkKeyer ) != S_OK )
                                {
                                        mlt_log_error( getConsumer(), "Failed to get keyer\n" );
-                                       m_deckLinkOutput->Release();
-                                       m_deckLinkOutput = 0;
-                                       m_deckLink->Release();
-                                       m_deckLink = 0;
+                                       SAFE_RELEASE( m_deckLinkOutput );
+                                       SAFE_RELEASE( m_deckLink );
                                        return false;
                                }
                        }
-                       deckLinkAttributes->Release();
+                       SAFE_RELEASE( deckLinkAttributes );
                }
 
                // Provide this class as a delegate to the audio and video output interfaces
                m_deckLinkOutput->SetScheduledFrameCompletionCallback( this );
-               
+
                return true;
        }
 
 
        void* preroll_thread()
        {
+               mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() );
+
                // preroll frames
-               for ( unsigned i = 0; i < m_preroll; i++ )
+               for ( unsigned i = 0; i < m_preroll && mlt_properties_get_int( properties, "running" ); i++ )
                        ScheduleNextFrame( true );
 
                // start scheduled playback
-               m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 );
+               if ( mlt_properties_get_int( properties, "running" ) )
+                       m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 );
 
                return 0;
        }
@@ -220,7 +228,7 @@ public:
                        mlt_log_error( getConsumer(), "Profile is not compatible with decklink.\n" );
                        return false;
                }
-               
+
                // Set the keyer
                if ( m_deckLinkKeyer && ( m_isKeyer = mlt_properties_get_int( properties, "keyer" ) ) )
                {
@@ -261,15 +269,15 @@ public:
                m_preroll = preroll;
                m_reprio = false;
 
-               // Do preroll in thread to ensure asynchronicity of mlt_consumer_start().
-               pthread_create( &m_prerollThread, NULL, preroll_thread_proxy, this );
-
                // Set the running state
                mlt_properties_set_int( properties, "running", 1 );
 
+               // Do preroll in thread to ensure asynchronicity of mlt_consumer_start().
+               pthread_create( &m_prerollThread, NULL, preroll_thread_proxy, this );
+
                return true;
        }
-       
+
        bool stop()
        {
                mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() );
@@ -277,7 +285,9 @@ public:
 
                // set running state is 0
                mlt_properties_set_int( properties, "running", 0 );
-               mlt_consumer_stopped( getConsumer() );
+
+               if ( wasRunning )
+                       pthread_join( m_prerollThread, NULL );
 
                // Stop the audio and video output streams immediately
                if ( m_deckLinkOutput )
@@ -288,12 +298,9 @@ public:
                }
 
                // release decklink frame
-               if ( m_decklinkFrame )
-                       m_decklinkFrame->Release();
-               m_decklinkFrame = NULL;
+               SAFE_RELEASE( m_decklinkFrame );
 
-               if ( wasRunning )
-                       pthread_join( m_prerollThread, NULL );
+               mlt_consumer_stopped( getConsumer() );
 
                return true;
        }
@@ -347,7 +354,7 @@ public:
                        stop();
                        return false;
                }
-               
+
                // Make the first line black for field order correction.
                if ( S_OK == frame->GetBytes( (void**) &buffer ) && buffer )
                {
@@ -379,8 +386,7 @@ public:
                        uint8_t* buffer = 0;
                        int stride = m_width * ( m_isKeyer? 4 : 2 );
 
-                       if ( m_decklinkFrame )
-                               m_decklinkFrame->Release();
+                       SAFE_RELEASE( m_decklinkFrame );
                        if ( createFrame( &m_decklinkFrame ) )
                                m_decklinkFrame->GetBytes( (void**) &buffer );
 
@@ -467,7 +473,7 @@ public:
 
                return result;
        }
-       
+
        // *** DeckLink API implementation of IDeckLinkVideoOutputCallback IDeckLinkAudioOutputCallback *** //
 
        // IUnknown needs only a dummy implementation
@@ -477,9 +483,9 @@ public:
                { return 1; }
        virtual ULONG STDMETHODCALLTYPE Release()
                { return 1; }
-       
+
        /************************* DeckLink API Delegate Methods *****************************/
-       
+
        virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completed )
        {
                if( !m_reprio )
@@ -561,7 +567,7 @@ public:
        {
                return mlt_consumer_is_stopped( getConsumer() ) ? S_FALSE : S_OK;
        }
-       
+
 
        void ScheduleNextFrame( bool preroll )
        {
@@ -643,6 +649,53 @@ static void close( mlt_consumer consumer )
 
 extern "C" {
 
+// Listen for the list_devices property to be set
+static void on_property_changed( void*, mlt_properties properties, const char *name )
+{
+       IDeckLinkIterator* decklinkIterator = NULL;
+       IDeckLink* decklink = NULL;
+       IDeckLinkInput* decklinkOutput = NULL;
+       int i = 0;
+
+       if ( name && !strcmp( name, "list_devices" ) )
+               mlt_event_block( (mlt_event) mlt_properties_get_data( properties, "list-devices-event", NULL ) );
+       else
+               return;
+
+#ifdef WIN32
+       if ( FAILED( CoInitialize( NULL ) ) )
+               return;
+       if ( FAILED( CoCreateInstance( CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**) &decklinkIterator ) ) )
+               return;
+#else
+       if ( !( decklinkIterator = CreateDeckLinkIteratorInstance() ) )
+               return;
+#endif
+       for ( ; decklinkIterator->Next( &decklink ) == S_OK; i++ )
+       {
+               if ( decklink->QueryInterface( IID_IDeckLinkOutput, (void**) &decklinkOutput ) == S_OK )
+               {
+                       DLString name = NULL;
+                       if ( decklink->GetModelName( &name ) == S_OK )
+                       {
+                               char *name_cstr = getCString( name );
+                               const char *format = "device.%d";
+                               char *key = (char*) calloc( 1, strlen( format ) + 1 );
+
+                               sprintf( key, format, i );
+                               mlt_properties_set( properties, key, name_cstr );
+                               free( key );
+                               freeDLString( name );
+                               freeCString( name_cstr );
+                       }
+                       SAFE_RELEASE( decklinkOutput );
+               }
+               SAFE_RELEASE( decklink );
+       }
+       SAFE_RELEASE( decklinkIterator );
+       mlt_properties_set_int( properties, "devices", i );
+}
+
 /** Initialise the consumer.
  */
 
@@ -659,13 +712,17 @@ mlt_consumer consumer_decklink_init( mlt_profile profile, mlt_service_type type,
                if ( decklink->open( arg? atoi(arg) : 0 ) )
                {
                        consumer = decklink->getConsumer();
-                       
+                       mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+
                        // Setup callbacks
                        consumer->close = close;
                        consumer->start = start;
                        consumer->stop = stop;
                        consumer->is_stopped = is_stopped;
-                       mlt_properties_set( MLT_CONSUMER_PROPERTIES(consumer), "deinterlace_method", "onefield" );
+                       mlt_properties_set( properties, "deinterlace_method", "onefield" );
+
+                       mlt_event event = mlt_events_listen( properties, properties, "property-changed", (mlt_listener) on_property_changed );
+                       mlt_properties_set_data( properties, "list-devices-event", event, 0, NULL, NULL );
                }
        }
 
index 92c24c92b4dfa79af1017bfa3914082102d46c06..513236be522a346534d9b19b0ac5a3cf9f3113a0 100644 (file)
@@ -79,3 +79,15 @@ parameters:
     maximum: 1
     default: 1
     widget: slider
+
+  - identifier: devices
+    title: Number of devices
+    type: integer
+    readonly: yes
+    minimum: 0
+
+  - identifier: device.*
+    title: Device model
+    description: The model name of each device that provides output.
+    type: string
+    readonly: yes
diff --git a/src/modules/decklink/darwin/DeckLinkAPI.h b/src/modules/decklink/darwin/DeckLinkAPI.h
new file mode 100755 (executable)
index 0000000..17eb6da
--- /dev/null
@@ -0,0 +1,1162 @@
+/* -LICENSE-START-
+** Copyright (c) 2011 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+** 
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+** 
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+/* DeckLinkAPI.h */
+
+#ifndef __DeckLink_API_h__
+#define __DeckLink_API_h__
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFPlugInCOM.h>
+#include <stdint.h>
+
+#define BLACKMAGIC_DECKLINK_API_MAGIC  1
+
+// Type Declarations
+
+typedef int64_t BMDTimeValue;
+typedef int64_t BMDTimeScale;
+typedef uint32_t BMDTimecodeBCD;
+typedef uint32_t BMDTimecodeUserBits;
+
+
+// Interface ID Declarations
+
+#define IID_IDeckLinkVideoOutputCallback                 /* 20AA5225-1958-47CB-820B-80A8D521A6EE */ (REFIID){0x20,0xAA,0x52,0x25,0x19,0x58,0x47,0xCB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE}
+#define IID_IDeckLinkInputCallback                       /* DD04E5EC-7415-42AB-AE4A-E80C4DFC044A */ (REFIID){0xDD,0x04,0xE5,0xEC,0x74,0x15,0x42,0xAB,0xAE,0x4A,0xE8,0x0C,0x4D,0xFC,0x04,0x4A}
+#define IID_IDeckLinkMemoryAllocator                     /* B36EB6E7-9D29-4AA8-92EF-843B87A289E8 */ (REFIID){0xB3,0x6E,0xB6,0xE7,0x9D,0x29,0x4A,0xA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8}
+#define IID_IDeckLinkAudioOutputCallback                 /* 403C681B-7F46-4A12-B993-2BB127084EE6 */ (REFIID){0x40,0x3C,0x68,0x1B,0x7F,0x46,0x4A,0x12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6}
+#define IID_IDeckLinkIterator                            /* 74E936FC-CC28-4A67-81A0-1E94E52D4E69 */ (REFIID){0x74,0xE9,0x36,0xFC,0xCC,0x28,0x4A,0x67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69}
+#define IID_IDeckLinkAPIInformation                      /* 7BEA3C68-730D-4322-AF34-8A7152B532A4 */ (REFIID){0x7B,0xEA,0x3C,0x68,0x73,0x0D,0x43,0x22,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4}
+#define IID_IDeckLinkDisplayModeIterator                 /* 9C88499F-F601-4021-B80B-032E4EB41C35 */ (REFIID){0x9C,0x88,0x49,0x9F,0xF6,0x01,0x40,0x21,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35}
+#define IID_IDeckLinkDisplayMode                         /* 3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78 */ (REFIID){0x3E,0xB2,0xC1,0xAB,0x0A,0x3D,0x45,0x23,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78}
+#define IID_IDeckLink                                    /* 62BFF75D-6569-4E55-8D4D-66AA03829ABC */ (REFIID){0x62,0xBF,0xF7,0x5D,0x65,0x69,0x4E,0x55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC}
+#define IID_IDeckLinkOutput                              /* A3EF0963-0862-44ED-92A9-EE89ABF431C7 */ (REFIID){0xA3,0xEF,0x09,0x63,0x08,0x62,0x44,0xED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7}
+#define IID_IDeckLinkInput                               /* 6D40EF78-28B9-4E21-990D-95BB7750A04F */ (REFIID){0x6D,0x40,0xEF,0x78,0x28,0xB9,0x4E,0x21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F}
+#define IID_IDeckLinkTimecode                            /* BC6CFBD3-8317-4325-AC1C-1216391E9340 */ (REFIID){0xBC,0x6C,0xFB,0xD3,0x83,0x17,0x43,0x25,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40}
+#define IID_IDeckLinkVideoFrame                          /* 3F716FE0-F023-4111-BE5D-EF4414C05B17 */ (REFIID){0x3F,0x71,0x6F,0xE0,0xF0,0x23,0x41,0x11,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17}
+#define IID_IDeckLinkMutableVideoFrame                   /* 69E2639F-40DA-4E19-B6F2-20ACE815C390 */ (REFIID){0x69,0xE2,0x63,0x9F,0x40,0xDA,0x4E,0x19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90}
+#define IID_IDeckLinkVideoFrame3DExtensions              /* DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7 */ (REFIID){0xDA,0x0F,0x7E,0x4A,0xED,0xC7,0x48,0xA8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7}
+#define IID_IDeckLinkVideoInputFrame                     /* 05CFE374-537C-4094-9A57-680525118F44 */ (REFIID){0x05,0xCF,0xE3,0x74,0x53,0x7C,0x40,0x94,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44}
+#define IID_IDeckLinkVideoFrameAncillary                 /* 732E723C-D1A4-4E29-9E8E-4A88797A0004 */ (REFIID){0x73,0x2E,0x72,0x3C,0xD1,0xA4,0x4E,0x29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04}
+#define IID_IDeckLinkAudioInputPacket                    /* E43D5870-2894-11DE-8C30-0800200C9A66 */ (REFIID){0xE4,0x3D,0x58,0x70,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66}
+#define IID_IDeckLinkScreenPreviewCallback               /* B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438 */ (REFIID){0xB1,0xD3,0xF4,0x9A,0x85,0xFE,0x4C,0x5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38}
+#define IID_IDeckLinkCocoaScreenPreviewCallback          /* D174152F-8F96-4C07-83A5-DD5F5AF0A2AA */ (REFIID){0xD1,0x74,0x15,0x2F,0x8F,0x96,0x4C,0x07,0x83,0xA5,0xDD,0x5F,0x5A,0xF0,0xA2,0xAA}
+#define IID_IDeckLinkGLScreenPreviewHelper               /* 504E2209-CAC7-4C1A-9FB4-C5BB6274D22F */ (REFIID){0x50,0x4E,0x22,0x09,0xCA,0xC7,0x4C,0x1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F}
+#define IID_IDeckLinkConfiguration                       /* C679A35B-610C-4D09-B748-1D0478100FC0 */ (REFIID){0xC6,0x79,0xA3,0x5B,0x61,0x0C,0x4D,0x09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0}
+#define IID_IDeckLinkAttributes                          /* ABC11843-D966-44CB-96E2-A1CB5D3135C4 */ (REFIID){0xAB,0xC1,0x18,0x43,0xD9,0x66,0x44,0xCB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4}
+#define IID_IDeckLinkKeyer                               /* 89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3 */ (REFIID){0x89,0xAF,0xCA,0xF5,0x65,0xF8,0x42,0x1E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3}
+#define IID_IDeckLinkVideoConversion                     /* 3BBCB8A2-DA2C-42D9-B5D8-88083644E99A */ (REFIID){0x3B,0xBC,0xB8,0xA2,0xDA,0x2C,0x42,0xD9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A}
+#define IID_IDeckLinkDeckControlStatusCallback           /* E5F693C1-4283-4716-B18F-C1431521955B */ (REFIID){0xE5,0xF6,0x93,0xC1,0x42,0x83,0x47,0x16,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B}
+#define IID_IDeckLinkDeckControl                         /* 522A9E39-0F3C-4742-94EE-D80DE335DA1D */ (REFIID){0x52,0x2A,0x9E,0x39,0x0F,0x3C,0x47,0x42,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D}
+
+
+/* Enum BMDDisplayMode - Video display modes */
+
+typedef uint32_t BMDDisplayMode;
+enum _BMDDisplayMode {
+
+    /* SD Modes */
+
+    bmdModeNTSC                                        = 'ntsc',
+    bmdModeNTSC2398                                    = 'nt23',       // 3:2 pulldown
+    bmdModePAL                                         = 'pal ',
+    bmdModeNTSCp                                       = 'ntsp',
+    bmdModePALp                                        = 'palp',
+
+    /* HD 1080 Modes */
+
+    bmdModeHD1080p2398                                 = '23ps',
+    bmdModeHD1080p24                                   = '24ps',
+    bmdModeHD1080p25                                   = 'Hp25',
+    bmdModeHD1080p2997                                 = 'Hp29',
+    bmdModeHD1080p30                                   = 'Hp30',
+    bmdModeHD1080i50                                   = 'Hi50',
+    bmdModeHD1080i5994                                 = 'Hi59',
+    bmdModeHD1080i6000                                 = 'Hi60',       // N.B. This _really_ is 60.00 Hz.
+    bmdModeHD1080p50                                   = 'Hp50',
+    bmdModeHD1080p5994                                 = 'Hp59',
+    bmdModeHD1080p6000                                 = 'Hp60',       // N.B. This _really_ is 60.00 Hz.
+
+    /* HD 720 Modes */
+
+    bmdModeHD720p50                                    = 'hp50',
+    bmdModeHD720p5994                                  = 'hp59',
+    bmdModeHD720p60                                    = 'hp60',
+
+    /* 2k Modes */
+
+    bmdMode2k2398                                      = '2k23',
+    bmdMode2k24                                        = '2k24',
+    bmdMode2k25                                        = '2k25'
+};
+
+
+/* Enum BMDFieldDominance - Video field dominance */
+
+typedef uint32_t BMDFieldDominance;
+enum _BMDFieldDominance {
+    bmdUnknownFieldDominance                           = 0,
+    bmdLowerFieldFirst                                 = 'lowr',
+    bmdUpperFieldFirst                                 = 'uppr',
+    bmdProgressiveFrame                                = 'prog',
+    bmdProgressiveSegmentedFrame                       = 'psf '
+};
+
+
+/* Enum BMDPixelFormat - Video pixel formats supported for output/input */
+
+typedef uint32_t BMDPixelFormat;
+enum _BMDPixelFormat {
+    bmdFormat8BitYUV                                   = '2vuy',
+    bmdFormat10BitYUV                                  = 'v210',
+    bmdFormat8BitARGB                                  = 32,
+    bmdFormat8BitBGRA                                  = 'BGRA',
+    bmdFormat10BitRGB                                  = 'r210'        // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10
+};
+
+
+/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */
+
+typedef uint32_t BMDDisplayModeFlags;
+enum _BMDDisplayModeFlags {
+    bmdDisplayModeSupports3D                           = 1 << 0,
+    bmdDisplayModeColorspaceRec601                     = 1 << 1,
+    bmdDisplayModeColorspaceRec709                     = 1 << 2
+};
+
+
+/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */
+
+typedef uint32_t BMDVideoOutputFlags;
+enum _BMDVideoOutputFlags {
+    bmdVideoOutputFlagDefault                          = 0,
+    bmdVideoOutputVANC                                 = 1 << 0,
+    bmdVideoOutputVITC                                 = 1 << 1,
+    bmdVideoOutputRP188                                = 1 << 2,
+    bmdVideoOutputDualStream3D                         = 1 << 4
+};
+
+
+/* Enum BMDFrameFlags - Frame flags */
+
+typedef uint32_t BMDFrameFlags;
+enum _BMDFrameFlags {
+    bmdFrameFlagDefault                                = 0,
+    bmdFrameFlagFlipVertical                           = 1 << 0,
+
+    /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */
+
+    bmdFrameHasNoInputSource                           = 1 << 31
+};
+
+
+/* Enum BMDVideoInputFlags - Flags applicable to video input */
+
+typedef uint32_t BMDVideoInputFlags;
+enum _BMDVideoInputFlags {
+    bmdVideoInputFlagDefault                           = 0,
+    bmdVideoInputEnableFormatDetection                 = 1 << 0,
+    bmdVideoInputDualStream3D                          = 1 << 1
+};
+
+
+/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */
+
+typedef uint32_t BMDVideoInputFormatChangedEvents;
+enum _BMDVideoInputFormatChangedEvents {
+    bmdVideoInputDisplayModeChanged                    = 1 << 0,
+    bmdVideoInputFieldDominanceChanged                 = 1 << 1,
+    bmdVideoInputColorspaceChanged                     = 1 << 2
+};
+
+
+/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */
+
+typedef uint32_t BMDDetectedVideoInputFormatFlags;
+enum _BMDDetectedVideoInputFormatFlags {
+    bmdDetectedVideoInputYCbCr422                      = 1 << 0,
+    bmdDetectedVideoInputRGB444                        = 1 << 1
+};
+
+
+/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */
+
+typedef uint32_t BMDOutputFrameCompletionResult;
+enum _BMDOutputFrameCompletionResult {
+    bmdOutputFrameCompleted,                          
+    bmdOutputFrameDisplayedLate,                      
+    bmdOutputFrameDropped,                            
+    bmdOutputFrameFlushed                             
+};
+
+
+/* Enum BMDReferenceStatus - GenLock input status */
+
+typedef uint32_t BMDReferenceStatus;
+enum _BMDReferenceStatus {
+    bmdReferenceNotSupportedByHardware                 = 1 << 0,
+    bmdReferenceLocked                                 = 1 << 1
+};
+
+
+/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */
+
+typedef uint32_t BMDAudioSampleRate;
+enum _BMDAudioSampleRate {
+    bmdAudioSampleRate48kHz                            = 48000
+};
+
+
+/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */
+
+typedef uint32_t BMDAudioSampleType;
+enum _BMDAudioSampleType {
+    bmdAudioSampleType16bitInteger                     = 16,
+    bmdAudioSampleType32bitInteger                     = 32
+};
+
+
+/* Enum BMDAudioOutputStreamType - Audio output stream type */
+
+typedef uint32_t BMDAudioOutputStreamType;
+enum _BMDAudioOutputStreamType {
+    bmdAudioOutputStreamContinuous,                   
+    bmdAudioOutputStreamContinuousDontResample,       
+    bmdAudioOutputStreamTimestamped                   
+};
+
+
+/* Enum BMDDisplayModeSupport - Output mode supported flags */
+
+typedef uint32_t BMDDisplayModeSupport;
+enum _BMDDisplayModeSupport {
+    bmdDisplayModeNotSupported                         = 0,
+    bmdDisplayModeSupported,                          
+    bmdDisplayModeSupportedWithConversion             
+};
+
+
+/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */
+
+typedef uint32_t BMDTimecodeFormat;
+enum _BMDTimecodeFormat {
+    bmdTimecodeRP188                                   = 'rp18',
+    bmdTimecodeRP188Field2                             = 'rp12',
+    bmdTimecodeVITC                                    = 'vitc',
+    bmdTimecodeVITCField2                              = 'vit2',
+    bmdTimecodeSerial                                  = 'seri'
+};
+
+
+/* Enum BMDTimecodeFlags - Timecode flags */
+
+typedef uint32_t BMDTimecodeFlags;
+enum _BMDTimecodeFlags {
+    bmdTimecodeFlagDefault                             = 0,
+    bmdTimecodeIsDropFrame                             = 1 << 0
+};
+
+
+/* Enum BMDVideoConnection - Video connection types */
+
+typedef uint32_t BMDVideoConnection;
+enum _BMDVideoConnection {
+    bmdVideoConnectionSDI                              = 1 << 0,
+    bmdVideoConnectionHDMI                             = 1 << 1,
+    bmdVideoConnectionOpticalSDI                       = 1 << 2,
+    bmdVideoConnectionComponent                        = 1 << 3,
+    bmdVideoConnectionComposite                        = 1 << 4,
+    bmdVideoConnectionSVideo                           = 1 << 5
+};
+
+
+/* Enum BMDAnalogVideoFlags - Analog video display flags */
+
+typedef uint32_t BMDAnalogVideoFlags;
+enum _BMDAnalogVideoFlags {
+    bmdAnalogVideoFlagCompositeSetup75                 = 1 << 0,
+    bmdAnalogVideoFlagComponentBetacamLevels           = 1 << 1
+};
+
+
+/* Enum BMDAudioConnection - Audio connection types */
+
+typedef uint32_t BMDAudioConnection;
+enum _BMDAudioConnection {
+    bmdAudioConnectionEmbedded                         = 'embd',
+    bmdAudioConnectionAESEBU                           = 'aes ',
+    bmdAudioConnectionAnalog                           = 'anlg'
+};
+
+
+/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */
+
+typedef uint32_t BMDAudioOutputAnalogAESSwitch;
+enum _BMDAudioOutputAnalogAESSwitch {
+    bmdAudioOutputSwitchAESEBU                         = 'aes ',
+    bmdAudioOutputSwitchAnalog                         = 'anlg'
+};
+
+
+/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */
+
+typedef uint32_t BMDVideoOutputConversionMode;
+enum _BMDVideoOutputConversionMode {
+    bmdNoVideoOutputConversion                         = 'none',
+    bmdVideoOutputLetterboxDownconversion              = 'ltbx',
+    bmdVideoOutputAnamorphicDownconversion             = 'amph',
+    bmdVideoOutputHD720toHD1080Conversion              = '720c',
+    bmdVideoOutputHardwareLetterboxDownconversion      = 'HWlb',
+    bmdVideoOutputHardwareAnamorphicDownconversion     = 'HWam',
+    bmdVideoOutputHardwareCenterCutDownconversion      = 'HWcc',
+    bmdVideoOutputHardware720p1080pCrossconversion     = 'xcap',
+    bmdVideoOutputHardwareAnamorphic720pUpconversion   = 'ua7p',
+    bmdVideoOutputHardwareAnamorphic1080iUpconversion  = 'ua1i',
+    bmdVideoOutputHardwareAnamorphic149To720pUpconversion = 'u47p',
+    bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = 'u41i',
+    bmdVideoOutputHardwarePillarbox720pUpconversion    = 'up7p',
+    bmdVideoOutputHardwarePillarbox1080iUpconversion   = 'up1i'
+};
+
+
+/* Enum BMDVideoInputConversionMode - Video input conversion mode */
+
+typedef uint32_t BMDVideoInputConversionMode;
+enum _BMDVideoInputConversionMode {
+    bmdNoVideoInputConversion                          = 'none',
+    bmdVideoInputLetterboxDownconversionFromHD1080     = '10lb',
+    bmdVideoInputAnamorphicDownconversionFromHD1080    = '10am',
+    bmdVideoInputLetterboxDownconversionFromHD720      = '72lb',
+    bmdVideoInputAnamorphicDownconversionFromHD720     = '72am',
+    bmdVideoInputLetterboxUpconversion                 = 'lbup',
+    bmdVideoInputAnamorphicUpconversion                = 'amup'
+};
+
+
+/* Enum BMDVideo3DPackingFormat - Video 3D packing format */
+
+typedef uint32_t BMDVideo3DPackingFormat;
+enum _BMDVideo3DPackingFormat {
+    bmdVideo3DPackingSidebySideHalf                    = 'sbsh',
+    bmdVideo3DPackingLinebyLine                        = 'lbyl',
+    bmdVideo3DPackingTopAndBottom                      = 'tabo',
+    bmdVideo3DPackingFramePacking                      = 'frpk',
+    bmdVideo3DPackingLeftOnly                          = 'left',
+    bmdVideo3DPackingRightOnly                         = 'righ'
+};
+
+
+/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */
+
+typedef uint32_t BMDIdleVideoOutputOperation;
+enum _BMDIdleVideoOutputOperation {
+    bmdIdleVideoOutputBlack                            = 'blac',
+    bmdIdleVideoOutputLastFrame                        = 'lafa'
+};
+
+
+/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */
+
+typedef uint32_t BMDDeckLinkConfigurationID;
+enum _BMDDeckLinkConfigurationID {
+
+    /* Serial port Flags */
+
+    bmdDeckLinkConfigSwapSerialRxTx                    = 'ssrt',
+
+    /* Video Input/Output Flags */
+
+    bmdDeckLinkConfigUse1080pNotPsF                    = 'fpro',
+
+    /* Video Input/Output Integers */
+
+    bmdDeckLinkConfigHDMI3DPackingFormat               = '3dpf',
+    bmdDeckLinkConfigBypass                            = 'byps',
+
+    /* Audio Input/Output Flags */
+
+    bmdDeckLinkConfigAnalogAudioConsumerLevels         = 'aacl',
+
+    /* Video output flags */
+
+    bmdDeckLinkConfigFieldFlickerRemoval               = 'fdfr',
+    bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion  = 'to59',
+    bmdDeckLinkConfig444SDIVideoOutput                 = '444o',
+    bmdDeckLinkConfig3GBpsVideoOutput                  = '3gbs',
+    bmdDeckLinkConfigBlackVideoOutputDuringCapture     = 'bvoc',
+    bmdDeckLinkConfigLowLatencyVideoOutput             = 'llvo',
+
+    /* Video Output Integers */
+
+    bmdDeckLinkConfigVideoOutputConnection             = 'vocn',
+    bmdDeckLinkConfigVideoOutputConversionMode         = 'vocm',
+    bmdDeckLinkConfigAnalogVideoOutputFlags            = 'avof',
+    bmdDeckLinkConfigReferenceInputTimingOffset        = 'glot',
+    bmdDeckLinkConfigVideoOutputIdleOperation          = 'voio',
+
+    /* Video Output Floats */
+
+    bmdDeckLinkConfigVideoOutputComponentLumaGain      = 'oclg',
+    bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = 'occb',
+    bmdDeckLinkConfigVideoOutputComponentChromaRedGain = 'occr',
+    bmdDeckLinkConfigVideoOutputCompositeLumaGain      = 'oilg',
+    bmdDeckLinkConfigVideoOutputCompositeChromaGain    = 'oicg',
+    bmdDeckLinkConfigVideoOutputSVideoLumaGain         = 'oslg',
+    bmdDeckLinkConfigVideoOutputSVideoChromaGain       = 'oscg',
+
+    /* Video Input Integers */
+
+    bmdDeckLinkConfigVideoInputConnection              = 'vicn',
+    bmdDeckLinkConfigAnalogVideoInputFlags             = 'avif',
+    bmdDeckLinkConfigVideoInputConversionMode          = 'vicm',
+    bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = 'pdif',
+    bmdDeckLinkConfigVANCSourceLine1Mapping            = 'vsl1',
+    bmdDeckLinkConfigVANCSourceLine2Mapping            = 'vsl2',
+    bmdDeckLinkConfigVANCSourceLine3Mapping            = 'vsl3',
+
+    /* Video Input Floats */
+
+    bmdDeckLinkConfigVideoInputComponentLumaGain       = 'iclg',
+    bmdDeckLinkConfigVideoInputComponentChromaBlueGain = 'iccb',
+    bmdDeckLinkConfigVideoInputComponentChromaRedGain  = 'iccr',
+    bmdDeckLinkConfigVideoInputCompositeLumaGain       = 'iilg',
+    bmdDeckLinkConfigVideoInputCompositeChromaGain     = 'iicg',
+    bmdDeckLinkConfigVideoInputSVideoLumaGain          = 'islg',
+    bmdDeckLinkConfigVideoInputSVideoChromaGain        = 'iscg',
+
+    /* Audio Input Integers */
+
+    bmdDeckLinkConfigAudioInputConnection              = 'aicn',
+
+    /* Audio Input Floats */
+
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel1     = 'ais1',
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel2     = 'ais2',
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel3     = 'ais3',
+    bmdDeckLinkConfigAnalogAudioInputScaleChannel4     = 'ais4',
+    bmdDeckLinkConfigDigitalAudioInputScale            = 'dais',
+
+    /* Audio Output Integers */
+
+    bmdDeckLinkConfigAudioOutputAESAnalogSwitch        = 'aoaa',
+
+    /* Audio Output Floats */
+
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel1    = 'aos1',
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel2    = 'aos2',
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel3    = 'aos3',
+    bmdDeckLinkConfigAnalogAudioOutputScaleChannel4    = 'aos4',
+    bmdDeckLinkConfigDigitalAudioOutputScale           = 'daos'
+};
+
+
+/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */
+
+typedef uint32_t BMDDeckLinkAttributeID;
+enum _BMDDeckLinkAttributeID {
+
+    /* Flags */
+
+    BMDDeckLinkSupportsInternalKeying                  = 'keyi',
+    BMDDeckLinkSupportsExternalKeying                  = 'keye',
+    BMDDeckLinkSupportsHDKeying                        = 'keyh',
+    BMDDeckLinkSupportsInputFormatDetection            = 'infd',
+    BMDDeckLinkHasReferenceInput                       = 'hrin',
+    BMDDeckLinkHasSerialPort                           = 'hspt',
+    BMDDeckLinkHasAnalogVideoOutputGain                = 'avog',
+    BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain     = 'ovog',
+    BMDDeckLinkHasVideoInputAntiAliasingFilter         = 'aafl',
+    BMDDeckLinkHasBypass                               = 'byps',
+
+    /* Integers */
+
+    BMDDeckLinkMaximumAudioChannels                    = 'mach',
+    BMDDeckLinkNumberOfSubDevices                      = 'nsbd',
+    BMDDeckLinkSubDeviceIndex                          = 'subi',
+    BMDDeckLinkVideoOutputConnections                  = 'vocn',
+    BMDDeckLinkVideoInputConnections                   = 'vicn',
+
+    /* Floats */
+
+    BMDDeckLinkVideoInputGainMinimum                   = 'vigm',
+    BMDDeckLinkVideoInputGainMaximum                   = 'vigx',
+    BMDDeckLinkVideoOutputGainMinimum                  = 'vogm',
+    BMDDeckLinkVideoOutputGainMaximum                  = 'vogx',
+
+    /* Strings */
+
+    BMDDeckLinkSerialPortDeviceName                    = 'slpn'
+};
+
+
+/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */
+
+typedef uint32_t BMDDeckLinkAPIInformationID;
+enum _BMDDeckLinkAPIInformationID {
+    BMDDeckLinkAPIVersion                              = 'vers'
+};
+
+
+/* Enum BMDDeckControlMode - DeckControl mode */
+
+typedef uint32_t BMDDeckControlMode;
+enum _BMDDeckControlMode {
+    bmdDeckControlNotOpened                            = 'ntop',
+    bmdDeckControlVTRControlMode                       = 'vtrc',
+    bmdDeckControlExportMode                           = 'expm',
+    bmdDeckControlCaptureMode                          = 'capm'
+};
+
+
+/* Enum BMDDeckControlEvent - DeckControl event */
+
+typedef uint32_t BMDDeckControlEvent;
+enum _BMDDeckControlEvent {
+    bmdDeckControlAbortedEvent                         = 'abte',       // This event is triggered when a capture or edit-to-tape operation is aborted.
+
+    /* Export-To-Tape events */
+
+    bmdDeckControlPrepareForExportEvent                = 'pfee',       // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback() should be called at this point.
+    bmdDeckControlExportCompleteEvent                  = 'exce',       // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback.
+
+    /* Capture events */
+
+    bmdDeckControlPrepareForCaptureEvent               = 'pfce',       // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid.
+    bmdDeckControlCaptureCompleteEvent                 = 'ccev'        // This event is triggered a few frames after reaching the out-point.
+};
+
+
+/* Enum BMDDeckControlVTRControlState - VTR Control state */
+
+typedef uint32_t BMDDeckControlVTRControlState;
+enum _BMDDeckControlVTRControlState {
+    bmdDeckControlNotInVTRControlMode                  = 'nvcm',
+    bmdDeckControlVTRControlPlaying                    = 'vtrp',
+    bmdDeckControlVTRControlRecording                  = 'vtrr',
+    bmdDeckControlVTRControlStill                      = 'vtra',
+    bmdDeckControlVTRControlSeeking                    = 'vtrs',
+    bmdDeckControlVTRControlStopped                    = 'vtro'
+};
+
+
+/* Enum BMDDeckControlStatusFlags - Deck Control status flags */
+
+typedef uint32_t BMDDeckControlStatusFlags;
+enum _BMDDeckControlStatusFlags {
+    bmdDeckControlStatusDeckConnected                  = 1 << 0,
+    bmdDeckControlStatusRemoteMode                     = 1 << 1,
+    bmdDeckControlStatusRecordInhibited                = 1 << 2,
+    bmdDeckControlStatusCassetteOut                    = 1 << 3
+};
+
+
+/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */
+
+typedef uint32_t BMDDeckControlExportModeOpsFlags;
+enum _BMDDeckControlExportModeOpsFlags {
+    bmdDeckControlExportModeInsertVideo                = 1 << 0,
+    bmdDeckControlExportModeInsertAudio1               = 1 << 1,
+    bmdDeckControlExportModeInsertAudio2               = 1 << 2,
+    bmdDeckControlExportModeInsertAudio3               = 1 << 3,
+    bmdDeckControlExportModeInsertAudio4               = 1 << 4,
+    bmdDeckControlExportModeInsertAudio5               = 1 << 5,
+    bmdDeckControlExportModeInsertAudio6               = 1 << 6,
+    bmdDeckControlExportModeInsertAudio7               = 1 << 7,
+    bmdDeckControlExportModeInsertAudio8               = 1 << 8,
+    bmdDeckControlExportModeInsertAudio9               = 1 << 9,
+    bmdDeckControlExportModeInsertAudio10              = 1 << 10,
+    bmdDeckControlExportModeInsertAudio11              = 1 << 11,
+    bmdDeckControlExportModeInsertAudio12              = 1 << 12,
+    bmdDeckControlExportModeInsertTimeCode             = 1 << 13,
+    bmdDeckControlExportModeInsertAssemble             = 1 << 14,
+    bmdDeckControlExportModeInsertPreview              = 1 << 15,
+    bmdDeckControlUseManualExport                      = 1 << 16
+};
+
+
+/* Enum BMDDeckControlError - Deck Control error */
+
+typedef uint32_t BMDDeckControlError;
+enum _BMDDeckControlError {
+    bmdDeckControlNoError                              = 'noer',
+    bmdDeckControlModeError                            = 'moer',
+    bmdDeckControlMissedInPointError                   = 'mier',
+    bmdDeckControlDeckTimeoutError                     = 'dter',
+    bmdDeckControlCommandFailedError                   = 'cfer',
+    bmdDeckControlDeviceAlreadyOpenedError             = 'dalo',
+    bmdDeckControlFailedToOpenDeviceError              = 'fder',
+    bmdDeckControlInLocalModeError                     = 'lmer',
+    bmdDeckControlEndOfTapeError                       = 'eter',
+    bmdDeckControlUserAbortError                       = 'uaer',
+    bmdDeckControlNoTapeInDeckError                    = 'nter',
+    bmdDeckControlNoVideoFromCardError                 = 'nvfc',
+    bmdDeckControlNoCommunicationError                 = 'ncom',
+    bmdDeckControlBufferTooSmallError                  = 'btsm',
+    bmdDeckControlBadChecksumError                     = 'chks',
+    bmdDeckControlUnknownError                         = 'uner'
+};
+
+
+/* Enum BMD3DPreviewFormat - Linked Frame preview format */
+
+typedef uint32_t BMD3DPreviewFormat;
+enum _BMD3DPreviewFormat {
+    bmd3DPreviewFormatDefault                          = 'defa',
+    bmd3DPreviewFormatLeftOnly                         = 'left',
+    bmd3DPreviewFormatRightOnly                        = 'righ',
+    bmd3DPreviewFormatSideBySide                       = 'side',
+    bmd3DPreviewFormatTopBottom                        = 'topb'
+};
+
+
+#if defined(__cplusplus)
+
+// Forward Declarations
+
+class IDeckLinkVideoOutputCallback;
+class IDeckLinkInputCallback;
+class IDeckLinkMemoryAllocator;
+class IDeckLinkAudioOutputCallback;
+class IDeckLinkIterator;
+class IDeckLinkAPIInformation;
+class IDeckLinkDisplayModeIterator;
+class IDeckLinkDisplayMode;
+class IDeckLink;
+class IDeckLinkOutput;
+class IDeckLinkInput;
+class IDeckLinkTimecode;
+class IDeckLinkVideoFrame;
+class IDeckLinkMutableVideoFrame;
+class IDeckLinkVideoFrame3DExtensions;
+class IDeckLinkVideoInputFrame;
+class IDeckLinkVideoFrameAncillary;
+class IDeckLinkAudioInputPacket;
+class IDeckLinkScreenPreviewCallback;
+class IDeckLinkCocoaScreenPreviewCallback;
+class IDeckLinkGLScreenPreviewHelper;
+class IDeckLinkConfiguration;
+class IDeckLinkAttributes;
+class IDeckLinkKeyer;
+class IDeckLinkVideoConversion;
+class IDeckLinkDeckControlStatusCallback;
+class IDeckLinkDeckControl;
+
+
+/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */
+
+class IDeckLinkVideoOutputCallback : public IUnknown
+{
+public:
+    virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame *completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0;
+    virtual HRESULT ScheduledPlaybackHasStopped (void) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoOutputCallback () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkInputCallback - Frame arrival callback. */
+
+class IDeckLinkInputCallback : public IUnknown
+{
+public:
+    virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;
+    virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0;
+
+protected:
+    virtual ~IDeckLinkInputCallback () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */
+
+class IDeckLinkMemoryAllocator : public IUnknown
+{
+public:
+    virtual HRESULT AllocateBuffer (/* in */ uint32_t bufferSize, /* out */ void **allocatedBuffer) = 0;
+    virtual HRESULT ReleaseBuffer (/* in */ void *buffer) = 0;
+
+    virtual HRESULT Commit (void) = 0;
+    virtual HRESULT Decommit (void) = 0;
+};
+
+
+/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */
+
+class IDeckLinkAudioOutputCallback : public IUnknown
+{
+public:
+    virtual HRESULT RenderAudioSamples (/* in */ bool preroll) = 0;
+};
+
+
+/* Interface IDeckLinkIterator - enumerates installed DeckLink hardware */
+
+class IDeckLinkIterator : public IUnknown
+{
+public:
+    virtual HRESULT Next (/* out */ IDeckLink **deckLinkInstance) = 0;
+};
+
+
+/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */
+
+class IDeckLinkAPIInformation : public IUnknown
+{
+public:
+    virtual HRESULT GetFlag (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ bool *value) = 0;
+    virtual HRESULT GetInt (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ int64_t *value) = 0;
+    virtual HRESULT GetFloat (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ double *value) = 0;
+    virtual HRESULT GetString (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ CFStringRef *value) = 0;
+
+protected:
+    virtual ~IDeckLinkAPIInformation () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */
+
+class IDeckLinkDisplayModeIterator : public IUnknown
+{
+public:
+    virtual HRESULT Next (/* out */ IDeckLinkDisplayMode **deckLinkDisplayMode) = 0;
+
+protected:
+    virtual ~IDeckLinkDisplayModeIterator () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkDisplayMode - represents a display mode */
+
+class IDeckLinkDisplayMode : public IUnknown
+{
+public:
+    virtual HRESULT GetName (/* out */ CFStringRef *name) = 0;
+    virtual BMDDisplayMode GetDisplayMode (void) = 0;
+    virtual long GetWidth (void) = 0;
+    virtual long GetHeight (void) = 0;
+    virtual HRESULT GetFrameRate (/* out */ BMDTimeValue *frameDuration, /* out */ BMDTimeScale *timeScale) = 0;
+    virtual BMDFieldDominance GetFieldDominance (void) = 0;
+    virtual BMDDisplayModeFlags GetFlags (void) = 0;
+
+protected:
+    virtual ~IDeckLinkDisplayMode () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLink - represents a DeckLink device */
+
+class IDeckLink : public IUnknown
+{
+public:
+    virtual HRESULT GetModelName (/* out */ CFStringRef *modelName) = 0;
+};
+
+
+/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */
+
+class IDeckLinkOutput : public IUnknown
+{
+public:
+    virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+    /* Video Output */
+
+    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;
+    virtual HRESULT DisableVideoOutput (void) = 0;
+
+    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0;
+    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;
+    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0;
+    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;
+
+    /* Audio Output */
+
+    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;
+    virtual HRESULT DisableAudioOutput (void) = 0;
+
+    virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;
+
+    virtual HRESULT BeginAudioPreroll (void) = 0;
+    virtual HRESULT EndAudioPreroll (void) = 0;
+    virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;
+
+    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;
+    virtual HRESULT FlushBufferedAudioSamples (void) = 0;
+
+    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+    /* Output Control */
+
+    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;
+    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0;
+    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;
+    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0;
+    virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0;
+
+    /* Hardware Timing */
+
+    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;
+
+protected:
+    virtual ~IDeckLinkOutput () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */
+
+class IDeckLinkInput : public IUnknown
+{
+public:
+    virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+    /* Video Input */
+
+    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;
+    virtual HRESULT DisableVideoInput (void) = 0;
+    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;
+
+    /* Audio Input */
+
+    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;
+    virtual HRESULT DisableAudioInput (void) = 0;
+    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;
+
+    /* Input Control */
+
+    virtual HRESULT StartStreams (void) = 0;
+    virtual HRESULT StopStreams (void) = 0;
+    virtual HRESULT PauseStreams (void) = 0;
+    virtual HRESULT FlushStreams (void) = 0;
+    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback *theCallback) = 0;
+
+    /* Hardware Timing */
+
+    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;
+
+protected:
+    virtual ~IDeckLinkInput () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */
+
+class IDeckLinkTimecode : public IUnknown
+{
+public:
+    virtual BMDTimecodeBCD GetBCD (void) = 0;
+    virtual HRESULT GetComponents (/* out */ uint8_t *hours, /* out */ uint8_t *minutes, /* out */ uint8_t *seconds, /* out */ uint8_t *frames) = 0;
+    virtual HRESULT GetString (/* out */ CFStringRef *timecode) = 0;
+    virtual BMDTimecodeFlags GetFlags (void) = 0;
+    virtual HRESULT GetTimecodeUserBits (/* out */ BMDTimecodeUserBits *userBits) = 0;
+
+protected:
+    virtual ~IDeckLinkTimecode () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */
+
+class IDeckLinkVideoFrame : public IUnknown
+{
+public:
+    virtual long GetWidth (void) = 0;
+    virtual long GetHeight (void) = 0;
+    virtual long GetRowBytes (void) = 0;
+    virtual BMDPixelFormat GetPixelFormat (void) = 0;
+    virtual BMDFrameFlags GetFlags (void) = 0;
+    virtual HRESULT GetBytes (/* out */ void **buffer) = 0;
+
+    virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode **timecode) = 0;
+    virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary **ancillary) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoFrame () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */
+
+class IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame
+{
+public:
+    virtual HRESULT SetFlags (/* in */ BMDFrameFlags newFlags) = 0;
+
+    virtual HRESULT SetTimecode (/* in */ BMDTimecodeFormat format, /* in */ IDeckLinkTimecode *timecode) = 0;
+    virtual HRESULT SetTimecodeFromComponents (/* in */ BMDTimecodeFormat format, /* in */ uint8_t hours, /* in */ uint8_t minutes, /* in */ uint8_t seconds, /* in */ uint8_t frames, /* in */ BMDTimecodeFlags flags) = 0;
+    virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary *ancillary) = 0;
+    virtual HRESULT SetTimecodeUserBits (/* in */ BMDTimecodeFormat format, /* in */ BMDTimecodeUserBits userBits) = 0;
+
+protected:
+    virtual ~IDeckLinkMutableVideoFrame () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */
+
+class IDeckLinkVideoFrame3DExtensions : public IUnknown
+{
+public:
+    virtual BMDVideo3DPackingFormat Get3DPackingFormat (void) = 0;
+    virtual HRESULT GetFrameForRightEye (/* out */ IDeckLinkVideoFrame* *rightEyeFrame) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoFrame3DExtensions () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */
+
+class IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame
+{
+public:
+    virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, /* in */ BMDTimeScale timeScale) = 0;
+    virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoInputFrame () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkVideoFrameAncillary - Obtained through QueryInterface() on an IDeckLinkVideoFrame object. */
+
+class IDeckLinkVideoFrameAncillary : public IUnknown
+{
+public:
+
+    virtual HRESULT GetBufferForVerticalBlankingLine (/* in */ uint32_t lineNumber, /* out */ void **buffer) = 0;
+    virtual BMDPixelFormat GetPixelFormat (void) = 0;
+    virtual BMDDisplayMode GetDisplayMode (void) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoFrameAncillary () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */
+
+class IDeckLinkAudioInputPacket : public IUnknown
+{
+public:
+    virtual long GetSampleFrameCount (void) = 0;
+    virtual HRESULT GetBytes (/* out */ void **buffer) = 0;
+    virtual HRESULT GetPacketTime (/* out */ BMDTimeValue *packetTime, /* in */ BMDTimeScale timeScale) = 0;
+
+protected:
+    virtual ~IDeckLinkAudioInputPacket () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */
+
+class IDeckLinkScreenPreviewCallback : public IUnknown
+{
+public:
+    virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+
+protected:
+    virtual ~IDeckLinkScreenPreviewCallback () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkCocoaScreenPreviewCallback - Screen preview callback for Cocoa-based applications */
+
+class IDeckLinkCocoaScreenPreviewCallback : public IDeckLinkScreenPreviewCallback
+{
+public:
+
+protected:
+    virtual ~IDeckLinkCocoaScreenPreviewCallback () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */
+
+class IDeckLinkGLScreenPreviewHelper : public IUnknown
+{
+public:
+
+    /* Methods must be called with OpenGL context set */
+
+    virtual HRESULT InitializeGL (void) = 0;
+    virtual HRESULT PaintGL (void) = 0;
+    virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+    virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0;
+
+protected:
+    virtual ~IDeckLinkGLScreenPreviewHelper () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */
+
+class IDeckLinkConfiguration : public IUnknown
+{
+public:
+    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;
+    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;
+    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;
+    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;
+    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;
+    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;
+    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ CFStringRef value) = 0;
+    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ CFStringRef *value) = 0;
+    virtual HRESULT WriteConfigurationToPreferences (void) = 0;
+
+protected:
+    virtual ~IDeckLinkConfiguration () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkAttributes - DeckLink Attribute interface */
+
+class IDeckLinkAttributes : public IUnknown
+{
+public:
+    virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool *value) = 0;
+    virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t *value) = 0;
+    virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double *value) = 0;
+    virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ CFStringRef *value) = 0;
+
+protected:
+    virtual ~IDeckLinkAttributes () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkKeyer - DeckLink Keyer interface */
+
+class IDeckLinkKeyer : public IUnknown
+{
+public:
+    virtual HRESULT Enable (/* in */ bool isExternal) = 0;
+    virtual HRESULT SetLevel (/* in */ uint8_t level) = 0;
+    virtual HRESULT RampUp (/* in */ uint32_t numberOfFrames) = 0;
+    virtual HRESULT RampDown (/* in */ uint32_t numberOfFrames) = 0;
+    virtual HRESULT Disable (void) = 0;
+
+protected:
+    virtual ~IDeckLinkKeyer () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */
+
+class IDeckLinkVideoConversion : public IUnknown
+{
+public:
+    virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame* srcFrame, /* in */ IDeckLinkVideoFrame* dstFrame) = 0;
+
+protected:
+    virtual ~IDeckLinkVideoConversion () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */
+
+class IDeckLinkDeckControlStatusCallback : public IUnknown
+{
+public:
+    virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0;
+    virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState newState, /* in */ BMDDeckControlError error) = 0;
+    virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0;
+    virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0;
+
+protected:
+    virtual ~IDeckLinkDeckControlStatusCallback () {}; // call Release method to drop reference count
+};
+
+
+/* Interface IDeckLinkDeckControl - Deck Control main interface */
+
+class IDeckLinkDeckControl : public IUnknown
+{
+public:
+    virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Close (/* in */ bool standbyOn) = 0;
+    virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0;
+    virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0;
+    virtual HRESULT SendCommand (/* in */ uint8_t *inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t *outBuffer, /* out */ uint32_t *outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT GetTimecodeString (/* out */ CFStringRef *currentTimeCode, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0;
+    virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0;
+    virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0;
+    virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0;
+    virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0;
+    virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0;
+    virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0;
+    virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT Abort (void) = 0;
+    virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0;
+    virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback *callback) = 0;
+
+protected:
+    virtual ~IDeckLinkDeckControl () {}; // call Release method to drop reference count
+};
+
+
+/* Functions */
+
+extern "C" {
+
+    IDeckLinkIterator* CreateDeckLinkIteratorInstance (void);
+    IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void);
+    IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void);
+    IDeckLinkCocoaScreenPreviewCallback* CreateCocoaScreenPreview (void* /* (NSView*) */ parentView);
+    IDeckLinkVideoConversion* CreateVideoConversionInstance (void);
+
+};
+
+
+#endif      // defined(__cplusplus)
+#endif      // __DeckLink_API_h__
diff --git a/src/modules/decklink/darwin/DeckLinkAPIDispatch.cpp b/src/modules/decklink/darwin/DeckLinkAPIDispatch.cpp
new file mode 100755 (executable)
index 0000000..368351a
--- /dev/null
@@ -0,0 +1,131 @@
+/* -LICENSE-START-
+** Copyright (c) 2009 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+** 
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+** 
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+/* DeckLinkAPIDispatch.cpp */
+
+#include "DeckLinkAPI.h"
+#include <pthread.h>
+
+#if BLACKMAGIC_DECKLINK_API_MAGIC != 1
+       #error The DeckLink API version of DeckLinkAPIDispatch.cpp is not the same version as DeckLinkAPI.h
+#endif
+
+#define kDeckLinkAPI_BundlePath "/Library/Application Support/Blackmagic Design/Blackmagic DeckLink/DeckLinkAPI.bundle"
+
+typedef IDeckLinkIterator* (*CreateIteratorFunc)(void);
+typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);
+typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);
+typedef IDeckLinkCocoaScreenPreviewCallback* (*CreateCocoaScreenPreviewFunc)(void*);
+typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);
+
+static pthread_once_t                                          gDeckLinkOnceControl            = PTHREAD_ONCE_INIT;
+static CFBundleRef                                                     gBundleRef                                      = NULL;
+static CreateIteratorFunc                                      gCreateIteratorFunc                     = NULL;
+static CreateAPIInformationFunc                                gCreateAPIInformationFunc       = NULL;
+static CreateOpenGLScreenPreviewHelperFunc     gCreateOpenGLPreviewFunc        = NULL;
+static CreateCocoaScreenPreviewFunc                    gCreateCocoaPreviewFunc         = NULL;
+static CreateVideoConversionInstanceFunc       gCreateVideoConversionFunc      = NULL;
+
+
+void   InitDeckLinkAPI (void)
+{
+       CFURLRef                bundleURL;
+
+       bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true);
+       if (bundleURL != NULL)
+       {
+               gBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL);
+               if (gBundleRef != NULL)
+               {
+                       gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0001"));
+                       gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001"));
+                       gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001"));
+                       gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateCocoaScreenPreview_0001"));
+                       gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("CreateVideoConversionInstance_0001"));
+               }
+               CFRelease(bundleURL);
+       }
+}
+
+bool           IsDeckLinkAPIPresent (void)
+{
+       // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller
+       if (gBundleRef != NULL)
+               return true;
+       
+       return false;
+}
+
+IDeckLinkIterator*             CreateDeckLinkIteratorInstance (void)
+{
+       pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+       
+       if (gCreateIteratorFunc == NULL)
+               return NULL;
+       
+       return gCreateIteratorFunc();
+}
+
+IDeckLinkAPIInformation*       CreateDeckLinkAPIInformationInstance (void)
+{
+       pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+       
+       if (gCreateAPIInformationFunc == NULL)
+               return NULL;
+       
+       return gCreateAPIInformationFunc();
+}
+
+IDeckLinkGLScreenPreviewHelper*                CreateOpenGLScreenPreviewHelper (void)
+{
+       pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+       
+       if (gCreateOpenGLPreviewFunc == NULL)
+               return NULL;
+       
+       return gCreateOpenGLPreviewFunc();
+}
+
+IDeckLinkCocoaScreenPreviewCallback*   CreateCocoaScreenPreview (void* parentView)
+{
+       pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+       
+       if (gCreateCocoaPreviewFunc == NULL)
+               return NULL;
+       
+       return gCreateCocoaPreviewFunc(parentView);
+}
+
+IDeckLinkVideoConversion* CreateVideoConversionInstance (void)
+{
+       pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+       
+       if (gCreateVideoConversionFunc == NULL)
+               return NULL;
+       
+       return gCreateVideoConversionFunc();
+}
+
index 608426a4ca86f517b6b27deaabc98da1d0842a1c..51456120e1f9ba774b4adc50a941c7dfb725e41a 100644 (file)
 #include <unistd.h>
 #include <limits.h>
 #include <sys/time.h>
-#ifdef WIN32
-#include <objbase.h>
-#include "DeckLinkAPI_h.h"
-#else
-#include "DeckLinkAPI.h"
-#endif
+#include "common.h"
 
 class DeckLinkProducer
        : public IDeckLinkInputCallback
@@ -51,8 +46,8 @@ private:
 
        BMDDisplayMode getDisplayMode( mlt_profile profile, int vancLines )
        {
-               IDeckLinkDisplayModeIterator* iter;
-               IDeckLinkDisplayMode* mode;
+               IDeckLinkDisplayModeIterator* iter = NULL;
+               IDeckLinkDisplayMode* mode = NULL;
                BMDDisplayMode result = (BMDDisplayMode) bmdDisplayModeNotSupported;
 
                if ( m_decklinkInput->GetDisplayModeIterator( &iter ) == S_OK )
@@ -72,9 +67,11 @@ private:
 
                                if ( width == profile->width && p == profile->progressive
                                         && ( height + vancLines == profile->height || ( height == 486 && profile->height == 480 + vancLines ) )
-                                        && fps == mlt_profile_fps( profile ) )
+                                        && (int) fps == (int) mlt_profile_fps( profile ) )
                                        result = mode->GetDisplayMode();
+                               SAFE_RELEASE( mode );
                        }
+                       SAFE_RELEASE( iter );
                }
 
                return result;
@@ -88,6 +85,13 @@ public:
        mlt_producer getProducer() const
                { return m_producer; }
 
+       DeckLinkProducer()
+       {
+               m_producer = NULL;
+               m_decklink = NULL;
+               m_decklinkInput = NULL;
+       }
+
        ~DeckLinkProducer()
        {
                if ( m_queue )
@@ -98,10 +102,8 @@ public:
                        pthread_cond_destroy( &m_condition );
                        mlt_cache_close( m_cache );
                }
-               if ( m_decklinkInput )
-                       m_decklinkInput->Release();
-               if ( m_decklink )
-                       m_decklink->Release();
+               SAFE_RELEASE( m_decklinkInput );
+               SAFE_RELEASE( m_decklink );
        }
 
        bool open( unsigned card =  0 )
@@ -121,14 +123,17 @@ public:
                        if ( !decklinkIterator )
                                throw "The DeckLink drivers are not installed.";
 #endif
-
                        // Connect to the Nth DeckLink instance
-                       unsigned i = 0;
-                       do {
-                               if ( decklinkIterator->Next( &m_decklink ) != S_OK )
-                                       throw "DeckLink card not found.";
-                       } while ( ++i <= card );
-                       decklinkIterator->Release();
+                       for ( unsigned i = 0; decklinkIterator->Next( &m_decklink ) == S_OK ; i++)
+                       {
+                               if ( i == card )
+                                       break;
+                               else
+                                       SAFE_RELEASE( m_decklink );
+                       }
+                       SAFE_RELEASE( decklinkIterator );
+                       if ( !m_decklink )
+                               throw "DeckLink card not found.";
 
                        // Get the input interface
                        if ( m_decklink->QueryInterface( IID_IDeckLinkInput, (void**) &m_decklinkInput ) != S_OK )
@@ -151,8 +156,8 @@ public:
                }
                catch ( const char *error )
                {
-                       if ( decklinkIterator )
-                               decklinkIterator->Release();
+                       SAFE_RELEASE( m_decklinkInput );
+                       SAFE_RELEASE( m_decklink );
                        mlt_log_error( getProducer(), "%s\n", error );
                        return false;
                }
@@ -193,7 +198,7 @@ public:
                        {
                                if ( decklinkAttributes->GetFlag( BMDDeckLinkSupportsInputFormatDetection, &doesDetectFormat ) != S_OK )
                                        doesDetectFormat = false;
-                               decklinkAttributes->Release();
+                               SAFE_RELEASE( decklinkAttributes );
                        }
                        mlt_log_verbose( getProducer(), "%s format detection\n", doesDetectFormat ? "supports" : "does not support" );
 
@@ -238,6 +243,8 @@ public:
                pthread_mutex_unlock( &m_mutex );
 
                m_decklinkInput->StopStreams();
+               m_decklinkInput->DisableVideoInput();
+               m_decklinkInput->DisableAudioInput();
 
                // Cleanup queue
                pthread_mutex_lock( &m_mutex );
@@ -248,12 +255,11 @@ public:
 
        mlt_frame getFrame()
        {
-               mlt_frame frame = NULL;
                struct timeval now;
                struct timespec tm;
                double fps = mlt_producer_get_fps( getProducer() );
                mlt_position position = mlt_producer_position( getProducer() );
-               mlt_cache_item cached = mlt_cache_get( m_cache, (void*) position );
+               mlt_frame frame = mlt_cache_get_frame( m_cache, position );
 
                // Allow the buffer to fill to the requested initial buffer level.
                if ( m_isBuffering )
@@ -278,13 +284,7 @@ public:
                        pthread_mutex_unlock( &m_mutex );
                }
 
-               if ( cached )
-               {
-                       // Copy cached frame instead of pulling from queue
-                       frame = mlt_frame_clone( (mlt_frame) mlt_cache_item_data( cached, NULL ), 0 );
-                       mlt_cache_item_close( cached );
-               }
-               else
+               if ( !frame )
                {
                        // Wait if queue is empty
                        pthread_mutex_lock( &m_mutex );
@@ -305,8 +305,10 @@ public:
 
                        // add to cache
                        if ( frame )
-                               mlt_cache_put( m_cache, (void*) position, mlt_frame_clone( frame, 1 ), 0,
-                                       (mlt_destructor) mlt_frame_close );
+                       {
+                               mlt_frame_set_position( frame, position );
+                               mlt_cache_put_frame( m_cache, frame );
+                       }
                }
 
                // Set frame timestamp and properties
@@ -323,10 +325,8 @@ public:
                        mlt_properties_set_int( properties, "meta.media.frame_rate_num", profile->frame_rate_num );
                        mlt_properties_set_int( properties, "meta.media.frame_rate_den", profile->frame_rate_den );
                        mlt_properties_set_int( properties, "width", profile->width );
-                       mlt_properties_set_int( properties, "real_width", profile->width );
                        mlt_properties_set_int( properties, "meta.media.width", profile->width );
                        mlt_properties_set_int( properties, "height", profile->height );
-                       mlt_properties_set_int( properties, "real_height", profile->height );
                        mlt_properties_set_int( properties, "meta.media.height", profile->height );
                        mlt_properties_set_int( properties, "format", mlt_image_yuv422 );
                        mlt_properties_set_int( properties, "colorspace", m_colorspace );
@@ -357,6 +357,13 @@ public:
                        IDeckLinkVideoInputFrame* video,
                        IDeckLinkAudioInputPacket* audio )
        {
+               if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "preview" ) &&
+                       mlt_producer_get_speed( getProducer() ) == 0.0 && !mlt_deque_count( m_queue ))
+               {
+                       pthread_cond_broadcast( &m_condition );
+                       return S_OK;
+               }
+
                // Create mlt_frame
                mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( getProducer() ) );
 
@@ -391,7 +398,7 @@ public:
                                                        else
                                                                mlt_log_debug( getProducer(), "failed capture vanc line %d\n", i );
                                                }
-                                               vanc->Release();
+                                               SAFE_RELEASE(vanc);
                                        }
                                }
 
@@ -420,20 +427,17 @@ public:
                        IDeckLinkTimecode* timecode = 0;
                        if ( video->GetTimecode( bmdTimecodeVITC, &timecode ) == S_OK && timecode )
                        {
-                               const char* timecodeString = 0;
+                               DLString timecodeString = 0;
 
-#ifdef WIN32
-                               if ( timecode->GetString( (BSTR*) &timecodeString ) == S_OK )
-#else
                                if ( timecode->GetString( &timecodeString ) == S_OK )
-#endif
                                {
-                                       mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "meta.attr.vitc.markup", timecodeString );
-                                       mlt_log_debug( getProducer(), "timecode %s\n", timecodeString );
+                                       char* s = getCString( timecodeString );
+                                       mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "meta.attr.vitc.markup", s );
+                                       mlt_log_debug( getProducer(), "timecode %s\n", s );
+                                       freeCString( s );
                                }
-                               if ( timecodeString )
-                                       free( (void*) timecodeString );
-                               timecode->Release();
+                               freeDLString( timecodeString );
+                               SAFE_RELEASE( timecode );
                        }
                }
                else
@@ -593,7 +597,6 @@ static int get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
                *frame = mlt_frame_init( MLT_PRODUCER_SERVICE(producer) );
 
        // Calculate the next timecode
-       mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
        mlt_producer_prepare_next( producer );
 
        // Close DeckLink if at end
@@ -616,6 +619,53 @@ static void producer_close( mlt_producer producer )
 
 extern "C" {
 
+// Listen for the list_devices property to be set
+static void on_property_changed( void*, mlt_properties properties, const char *name )
+{
+       IDeckLinkIterator* decklinkIterator = NULL;
+       IDeckLink* decklink = NULL;
+       IDeckLinkInput* decklinkInput = NULL;
+       int i = 0;
+
+       if ( name && !strcmp( name, "list_devices" ) )
+               mlt_event_block( (mlt_event) mlt_properties_get_data( properties, "list-devices-event", NULL ) );
+       else
+               return;
+
+#ifdef WIN32
+       if ( FAILED( CoInitialize( NULL ) ) )
+               return;
+       if ( FAILED( CoCreateInstance( CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**) &decklinkIterator ) ) )
+               return;
+#else
+       if ( !( decklinkIterator = CreateDeckLinkIteratorInstance() ) )
+               return;
+#endif
+       for ( ; decklinkIterator->Next( &decklink ) == S_OK; i++ )
+       {
+               if ( decklink->QueryInterface( IID_IDeckLinkInput, (void**) &decklinkInput ) == S_OK )
+               {
+                       DLString name = NULL;
+                       if ( decklink->GetModelName( &name ) == S_OK )
+                       {
+                               char *name_cstr = getCString( name );
+                               const char *format = "device.%d";
+                               char *key = (char*) calloc( 1, strlen( format ) + 1 );
+
+                               sprintf( key, format, i );
+                               mlt_properties_set( properties, key, name_cstr );
+                               free( key );
+                               freeDLString( name );
+                               freeCString( name_cstr );
+                       }
+                       SAFE_RELEASE( decklinkInput );
+               }
+               SAFE_RELEASE( decklink );
+       }
+       SAFE_RELEASE( decklinkIterator );
+       mlt_properties_set_int( properties, "devices", i );
+}
+
 /** Initialise the producer.
  */
 
@@ -650,6 +700,9 @@ mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type,
                        mlt_properties_set_int( properties, "length", INT_MAX );
                        mlt_properties_set_int( properties, "out", INT_MAX - 1 );
                        mlt_properties_set( properties, "eof", "loop" );
+
+                       mlt_event event = mlt_events_listen( properties, properties, "property-changed", (mlt_listener) on_property_changed );
+                       mlt_properties_set_data( properties, "list-devices-event", event, 0, NULL, NULL );
                }
        }
 
index 3d60725eb95a856dceb2ca9128512a1e90ed7227..6cea8851f41404bff01f6feaf8bc09e682619c6f 100644 (file)
@@ -75,3 +75,24 @@ parameters:
     default: 0
     unit: lines
     widget: spinner
+
+  - identifier: preview
+    title: Enable preview
+    description: Support preview monitoring when paused (speed = 0).
+    type: integer
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
+
+  - identifier: devices
+    title: Number of devices
+    type: integer
+    readonly: yes
+    minimum: 0
+
+  - identifier: device.*
+    title: Device model
+    description: The model name of each device that accepts input.
+    type: string
+    readonly: yes
index 0fbf5f6ebd23f834967b7f5c9f0d13ea5ce41660..f1dfbfef425e2fc83009981be7fe2b470b82ff13 100644 (file)
@@ -26,7 +26,7 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 48c6c5b0b790acc418e755c7e8269ebc7e1c24f7..4252ef148dd3dd1a6d48d6e41e280ac1e1ace459 100644 (file)
@@ -31,9 +31,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/dv"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/dv"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/dv"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/dv"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 5125d2e3d7505708533a1961cc80c863017d0f27..59e8c5f7c3a4fc23bbbe219bc02af1bc17646b06 100644 (file)
@@ -138,7 +138,7 @@ 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 );
+       producer_libdv this = calloc( 1, sizeof( struct producer_libdv_s ) );
 
        if ( filename != NULL && this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
        {
@@ -279,7 +279,6 @@ static int producer_collect_info( producer_libdv this, mlt_profile profile )
                                        aspect_ratio = 8 / 9;
                        }
                        mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio);
-                       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" );
@@ -289,6 +288,10 @@ static int producer_collect_info( producer_libdv this, mlt_profile profile )
                        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" );
+                       mlt_properties_set_int( properties, "meta.media.width", 720 );
+                       mlt_properties_set_int( properties, "meta.media.height", this->is_pal ? 576 : 480 );
+                       mlt_properties_set_int( properties, "meta.media.frame_rate_num", this->is_pal? 25 : 30000 );
+                       mlt_properties_set_int( properties, "meta.media.frame_rate_den", this->is_pal?  1 :  1001 );
 
                        // Return the decoder
                        dv_decoder_return( dv_decoder );
@@ -503,8 +506,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                // 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 );
                mlt_properties_set_int( properties, "colorspace", 601 );
        
@@ -536,7 +537,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        }
 
        // Update timecode on the frame we're creating
-       mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
+       if ( *frame != NULL )
+               mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
 
        // Calculate the next timecode
        mlt_producer_prepare_next( producer );
index 8887374d6852a713719680128eaff46bf8bf57c8..b52d2633c511933c12a409b7100a528b28ea78ac 100644 (file)
@@ -28,9 +28,9 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/effectv"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/effectv"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/effectv"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/effectv"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 2388dc1e185e6be526059f4f1d70fa743cb066b8..45bd7aed2ce37385e4df3ef67648f4a989743c31 100644 (file)
@@ -9,7 +9,7 @@ distclean:
 clean:
 
 install:       all
-       install -d "$(DESTDIR)$(datadir)/mlt/feeds/PAL"
-       install -d "$(DESTDIR)$(datadir)/mlt/feeds/NTSC"
-       install -m 644 PAL/*.* "$(DESTDIR)$(datadir)/mlt/feeds/PAL"
-       install -m 644 NTSC/*.* "$(DESTDIR)$(datadir)/mlt/feeds/NTSC"
+       install -d "$(DESTDIR)$(mltdatadir)/feeds/PAL"
+       install -d "$(DESTDIR)$(mltdatadir)/feeds/NTSC"
+       install -m 644 PAL/*.* "$(DESTDIR)$(mltdatadir)/feeds/PAL"
+       install -m 644 NTSC/*.* "$(DESTDIR)$(mltdatadir)/feeds/NTSC"
index 7abbb74bdae9ba0c16d5fae0f6f9053b979e14bc..5b7a33c79afe84b41d81b2d50dc32799712f7684 100644 (file)
@@ -34,10 +34,10 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(prefix)/share/mlt/frei0r"
-       install -m 644 blacklist.txt "$(DESTDIR)$(datadir)/mlt/frei0r"
-       install -m 644 not_thread_safe.txt "$(DESTDIR)$(datadir)/mlt/frei0r"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/frei0r"
+       install -m 644 blacklist.txt "$(DESTDIR)$(mltdatadir)/frei0r"
+       install -m 644 not_thread_safe.txt "$(DESTDIR)$(mltdatadir)/frei0r"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 73757a468def86fc5a5191470306eddec29f9533..e911ea95de7a4348fee895523bf15d5124e1096c 100755 (executable)
@@ -3,7 +3,7 @@
 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
+       echo "#include <frei0r.h> int main(){ f0r_plugin_info_t test; test.name;return 0;}"| $CC $(pkg-config --cflags frei0r) $CFLAGS -c -x c -  >/dev/null 2>&1
 
        if [ "$?" = "1" ]
        then
index e214292d6dddd78ebe00e40085861937d4f15098..ad9ecb777d0ce4d26f6c14802322c56697f97561 100644 (file)
@@ -178,7 +178,7 @@ static mlt_properties fill_param_info ( mlt_service_type type, const char *servi
                mlt_properties_set_data ( parameter , string , pnum , 0 , ( mlt_destructor )mlt_properties_close, NULL );
                f0r_param_info_t paraminfo;
                param_info(&paraminfo,j);
-               mlt_properties_set ( pnum , "identifier" , paraminfo.name );
+               mlt_properties_set ( pnum , "identifier" , string );
                mlt_properties_set ( pnum , "title" , paraminfo.name );
                mlt_properties_set ( pnum , "description" , paraminfo.explanation);
                if ( paraminfo.type == F0R_PARAM_DOUBLE ){
@@ -310,13 +310,13 @@ static void * load_lib( mlt_profile profile, mlt_service_type type , void* handl
                        }
                }
                check_thread_safe( properties, name );
-               mlt_properties_set_data(properties, "_dlclose_handle", handle , sizeof (void*) , NULL , NULL );
+               mlt_properties_set_data(properties, "_dlclose_handle", handle , sizeof ( handle ) , 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);
+               mlt_properties_set_data(properties, "f0r_construct", f0r_construct , sizeof( f0r_construct ),NULL,NULL);
+               mlt_properties_set_data(properties, "f0r_update", f0r_update , sizeof( f0r_update ),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_update2", f0r_update2 , sizeof( f0r_update2 ),NULL,NULL);
+               mlt_properties_set_data(properties, "f0r_destruct", f0r_destruct , sizeof( f0r_destruct ),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);
@@ -419,9 +419,10 @@ MLT_REPOSITORY
                        char* firstname = strtok_r( shortname, ".", &save_firstptr );
 #endif
                        char pluginname[1024]="frei0r.";
-                       strcat(pluginname,firstname);
+                       if ( firstname )
+                               strncat( pluginname, firstname, sizeof( pluginname ) - strlen( pluginname ) -1 );
 
-                       if ( mlt_properties_get( blacklist, firstname ) )
+                       if ( firstname && mlt_properties_get( blacklist, firstname ) )
                                continue;
 
                        void* handle=dlopen(strcat(name, LIBSUF),RTLD_LAZY);
index 4f73c0f2470fdcfcda505f38c0a1f2d5a0d5d26e..fdb74c41a1701f620797952a4b576fdb491e117f 100644 (file)
@@ -76,7 +76,7 @@ int process_frei0r_item( mlt_service service, double position, double time, mlt_
        }
        if ( neu == 0 ){
                inst= f0r_construct(*width,*height);
-               mlt_properties_set_data(  prop  ,  ctorname , inst, sizeof(void*) , f0r_destruct , NULL );;
+               mlt_properties_set_data(  prop  ,  ctorname , inst, sizeof( inst ) , f0r_destruct , NULL );;
        }else{
                inst=mlt_properties_get_data( prop ,  ctorname , NULL );
        }
@@ -89,12 +89,16 @@ int process_frei0r_item( mlt_service service, double position, double time, mlt_
                for (i=0;i<info.num_params;i++){
                        f0r_param_info_t pinfo;
                        f0r_get_param_info(&pinfo,i);
-                       if (mlt_properties_get( prop , pinfo.name ) !=NULL ){
+                       char index[20];
+                       snprintf( index, sizeof(index), "%d", i );
+                       char *val = mlt_properties_get( prop , index );
+                       if ( !val )
+                               val = mlt_properties_get( prop , pinfo.name );
+                       if ( val ) {
                                switch (pinfo.type) {
                                        case F0R_PARAM_DOUBLE:
                                        case F0R_PARAM_BOOL:
                                        {
-                                               char *val=mlt_properties_get(prop, pinfo.name );
                                                mlt_geometry geom=mlt_geometry_init();
                                                struct mlt_geometry_item_s item;
                                                mlt_geometry_parse(geom,val,-1,-1,-1);
@@ -107,14 +111,15 @@ int process_frei0r_item( mlt_service service, double position, double time, mlt_
                                        case F0R_PARAM_COLOR:
                                        {
                                                f0r_param_color_t color;
-                                               parse_color(mlt_properties_get_int(prop , pinfo.name), &color);
+                                               int int_color = mlt_properties_get(prop, index) ?
+                                                       mlt_properties_get_int(prop, index) : mlt_properties_get_int(prop, pinfo.name);
+                                               parse_color(int_color, &color);
                                                f0r_set_param_value(inst, &color, i);
                                                break;
                                        }
                                        case F0R_PARAM_STRING:
                                        {
-                                               f0r_param_string val = mlt_properties_get(prop, pinfo.name);
-                                               if (val) f0r_set_param_value(inst, &val, i);
+                                               f0r_set_param_value(inst, &val, i);
                                                break;
                                        }
                                }
index 6a5abcd5741fc930b97220e2caffc33027becd85..7e24be456582b3ad20bc8cba8489cdd9b693511d 100644 (file)
@@ -84,7 +84,8 @@ int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
 
                // 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_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) );
+               mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
 
                // Push the get_image method
                mlt_frame_push_get_image( *frame, producer_get_image );
index b286dbe46b4d2d4a4d147806c97a874c9b2e1d86..5712644f6d1f35680cadf856ba115d251542bc19 100644 (file)
@@ -11,14 +11,14 @@ OBJS = factory.o
 
 ifdef USE_GTK2
 OBJS += consumer_gtk2.o
-CFLAGS += `pkg-config gtk+-2.0 --cflags`
-LDFLAGS += `pkg-config gtk+-2.0 --libs`
+CFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --cflags gtk+-2.0`
+LDFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --libs gtk+-2.0`
 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`
+CFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --cflags gdk-pixbuf-2.0`
+LDFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --libs gdk-pixbuf-2.0`
 endif
 
 ifdef USE_EXIF
@@ -35,8 +35,8 @@ endif
 ifdef USE_PANGO
 OBJS += producer_pango.o
 OBJS += filter_dynamictext.o
-CFLAGS += `pkg-config pangoft2 --cflags`
-LDFLAGS += `pkg-config pangoft2 --libs`
+CFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --cflags pangoft2`
+LDFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --libs pangoft2`
 ifeq ($(targetos),Darwin)
 LDFLAGS += -liconv
 endif
@@ -71,9 +71,9 @@ clean:
                rm -f $(OBJS) $(ASM_OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/gtk2"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/gtk2"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/gtk2"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/gtk2"
 
 ifneq ($(wildcard .depend),)
 include .depend
index a01e40801f38dc85ce8f5c3301bd6e2e855a9364..60f8dd7845eb332ba609e3822d64628e0c676426 100755 (executable)
@@ -1,15 +1,31 @@
 #!/bin/sh
 
-if [ "$help" != "1" ]
+if [ "$help" = "1" ]
 then
+       cat << EOF
+GTK+ options:
 
-       pkg-config gtk+-2.0 2> /dev/null
+  --gtk2-prefix=path      - Override the gtk+-2.0 prefix for pkg-config
+
+EOF
+
+else
+       pkgconfig_prefix=
+       for i in "$@"
+       do
+               case $i in
+                       --gtk2-prefix=* )       pkgconfig_prefix="${i#--gtk2-prefix=}" ;;
+               esac
+       done
+       [ "$pkgconfig_prefix" != "" ] && pkgconfig_prefix="--define-variable=prefix=\"$pkgconfig_prefix\""
+
+       pkg-config $pkgconfig_prefix gtk+-2.0 2> /dev/null
        disable_gtk2=$?
 
-       pkg-config gdk-pixbuf-2.0 2> /dev/null
+       pkg-config $pkgconfig_prefix gdk-pixbuf-2.0 2> /dev/null
        disable_pixbuf=$?
 
-       pkg-config pangoft2 2> /dev/null
+       pkg-config $pkgconfig_prefix gdk-pixbuf-2.0 pangoft2 2> /dev/null
        disable_pango=$?
 
        if [ "$disable_gtk2" != "0" -a "$disable_pixbuf" != 0 -a "$disable_pango" != "0" ]
@@ -33,6 +49,8 @@ then
        [ "$disable_pixbuf" = "0" ] && echo "USE_PIXBUF=1" >> config.mak
        [ "$disable_pango" = "0" ] && echo "USE_PANGO=1" >> config.mak
 
+       [ "$pkgconfig_prefix" != "" ] && echo "PKGCONFIG_PREFIX=$pkgconfig_prefix" >> config.mak
+
        pkg-config --exists 'libexif'
        if [ $? -eq 0 ]
        then
index d3d3e66ab03731d37d205f0552f5412b247961af..7149dd984feb3f3f28d6d8a89a6a8c83f5cc0e6e 100644 (file)
@@ -34,7 +34,7 @@
 static int get_next_token(char* str, int* pos, char* token, int* is_keyword)
 {
        int token_pos = 0;
-       int str_len = strlen(str);
+       int str_len = strlen( str );
 
        if( (*pos) >= str_len || str[*pos] == '\0' )
        {
@@ -90,7 +90,7 @@ static void get_timecode_str( mlt_filter filter, mlt_frame frame, char* text )
        char tc[12] = "";
        if (fps == 0)
        {
-               strncat( text, "-", MAX_TEXT_LEN - strlen(text) - 1 );
+               strncat( text, "-", MAX_TEXT_LEN - strlen( text ) - 1 );
        }
        else
        {
@@ -101,7 +101,7 @@ static void get_timecode_str( mlt_filter filter, mlt_frame frame, char* text )
                int hours = minutes / 60;
                minutes = minutes % 60;
                sprintf(tc, "%.2d:%.2d:%.2d:%.2d", hours, minutes, seconds, frames);
-               strncat( text, tc, MAX_TEXT_LEN - strlen(text) - 1 );
+               strncat( text, tc, MAX_TEXT_LEN - strlen( text ) - 1 );
        }
 }
 
@@ -109,14 +109,14 @@ static void get_frame_str( mlt_filter filter, mlt_frame frame, char* text )
 {
        int pos = mlt_frame_get_position( frame );
        char s[12];
-       snprintf( s, sizeof(s) - 1, "%d", pos );
-       strncat( text, s, MAX_TEXT_LEN - strlen(text) - 1 );
+       snprintf( s, sizeof( s ) - 1, "%d", pos );
+       strncat( text, s, MAX_TEXT_LEN - strlen( text ) - 1 );
 }
 
 static void get_filedate_str( mlt_filter filter, mlt_frame frame, char* text )
 {
-       mlt_producer producer = mlt_producer_cut_parent(mlt_frame_get_original_producer( frame ));
-       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES(producer);
+       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
        char* filename = mlt_properties_get( producer_properties, "resource");
        struct stat file_info;
 
@@ -125,14 +125,35 @@ static void get_filedate_str( mlt_filter filter, mlt_frame frame, char* text )
                struct tm* time_info = gmtime( &(file_info.st_mtime) );
                char date[11] = "";
                strftime( date, 11, "%Y/%m/%d", time_info );
-               strncat( text, date, MAX_TEXT_LEN - strlen(text) - 1);
+               strncat( text, date, MAX_TEXT_LEN - strlen( text ) - 1);
        }
 }
 
+static void get_localfiledate_str( mlt_filter filter, mlt_frame frame, char* text )
+{
+       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       char* filename = mlt_properties_get( producer_properties, "resource" );
+       struct stat file_info;
+
+       if( !stat( filename, &file_info ) )
+       {
+               struct tm* time_info = localtime( &(file_info.st_mtime) );
+               char date[11] = "";
+               strftime( date, 11, "%Y/%m/%d", time_info );
+               strncat( text, date, MAX_TEXT_LEN - strlen( text ) - 1);
+       }
+}
+
+static void get_resource_str( mlt_filter filter, mlt_frame frame, char* text )
+{
+       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       strncat( text, mlt_properties_get( producer_properties, "resource" ), MAX_TEXT_LEN - strlen( text ) - 1 );
+}
 
 /** Perform substitution for keywords that are enclosed in "# #".
 */
-
 static void substitute_keywords(mlt_filter filter, char* result, char* value, mlt_frame frame)
 {
        char keyword[MAX_TEXT_LEN] = "";
@@ -143,26 +164,27 @@ static void substitute_keywords(mlt_filter filter, char* result, char* value, ml
        {
                if(!is_keyword)
                {
-                       strncat( result, keyword, MAX_TEXT_LEN - strlen(result) - 1 );
+                       strncat( result, keyword, MAX_TEXT_LEN - strlen( result ) - 1 );
                }
                else if ( !strcmp( keyword, "timecode" ) )
                {
-                       get_timecode_str(filter, frame, result);
+                       get_timecode_str( filter, frame, result );
                }
                else if ( !strcmp( keyword, "frame" ) )
                {
-                       get_frame_str(filter, frame, result);
+                       get_frame_str( filter, frame, result );
                }
                else if ( !strcmp( keyword, "filedate" ) )
                {
-                       get_filedate_str(filter, frame, result);
+                       get_filedate_str( filter, frame, result );
+               }
+               else if ( !strcmp( keyword, "localfiledate" ) )
+               {
+                       get_localfiledate_str( filter, frame, result );
                }
                else if ( !strcmp( keyword, "resource" ) )
                {
-                       // special case: replace #resource# with cut parent resource name
-                       mlt_producer producer = mlt_producer_cut_parent(mlt_frame_get_original_producer( frame ));
-                       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES(producer);
-                       strncat( result, mlt_properties_get( producer_properties, "resource"), MAX_TEXT_LEN - strlen(result) - 1 );
+                       get_resource_str( filter, frame, result );
                }
                else
                {
@@ -177,12 +199,11 @@ static void substitute_keywords(mlt_filter filter, char* result, char* value, ml
        }
 }
 
-static void apply_filter(mlt_filter filter, mlt_frame frame )
+static void setup_producer( mlt_filter filter, mlt_producer producer, mlt_frame frame )
 {
        mlt_properties my_properties = MLT_FILTER_PROPERTIES( filter );
-       mlt_filter watermark = mlt_properties_get_data( my_properties, "_watermark", NULL );
-       mlt_properties watermark_properties = MLT_FILTER_PROPERTIES( watermark );
-       char* dynamic_text = mlt_properties_get( my_properties, "argument");
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       char* dynamic_text = mlt_properties_get( my_properties, "argument" );
 
        // Check for keywords in dynamic text
        if ( dynamic_text )
@@ -190,111 +211,161 @@ static void apply_filter(mlt_filter filter, mlt_frame frame )
                // Apply keyword substitution before passing the text to the filter.
                char result[MAX_TEXT_LEN] = "";
                substitute_keywords( filter, result, dynamic_text, frame );
-               mlt_properties_set( watermark_properties, "producer.markup", (char*) result );
+               mlt_properties_set( producer_properties, "markup", (char*)result );
        }
 
-       // Pass the properties to the watermark filter composite transition
-       mlt_properties_set( watermark_properties, "composite.geometry", mlt_properties_get( my_properties, "geometry" ) );
-       mlt_properties_set( watermark_properties, "composite.halign", mlt_properties_get( my_properties, "halign" ) );
-       mlt_properties_set( watermark_properties, "composite.valign", mlt_properties_get( my_properties, "valign" ) );
-
-       // Pass the properties to the watermark filter pango producer
-       mlt_properties_set( watermark_properties, "producer.family", mlt_properties_get( my_properties, "family" ) );
-       mlt_properties_set( watermark_properties, "producer.size", mlt_properties_get( my_properties, "size" ) );
-       mlt_properties_set( watermark_properties, "producer.weight", mlt_properties_get( my_properties, "weight" ) );
-       mlt_properties_set( watermark_properties, "producer.fgcolour", mlt_properties_get( my_properties, "fgcolour" ) );
-       mlt_properties_set( watermark_properties, "producer.bgcolour", mlt_properties_get( my_properties, "bgcolour" ) );
-       mlt_properties_set( watermark_properties, "producer.olcolour", mlt_properties_get( my_properties, "olcolour" ) );
-       mlt_properties_set( watermark_properties, "producer.pad", mlt_properties_get( my_properties, "pad" ) );
-       mlt_properties_set( watermark_properties, "producer.outline", mlt_properties_get( my_properties, "outline" ) );
-
-       // Process the filter
-       mlt_filter_process( watermark, frame );
+       // Pass the properties to the pango producer
+       mlt_properties_set( producer_properties, "family", mlt_properties_get( my_properties, "family" ) );
+       mlt_properties_set( producer_properties, "size", mlt_properties_get( my_properties, "size" ) );
+       mlt_properties_set( producer_properties, "weight", mlt_properties_get( my_properties, "weight" ) );
+       mlt_properties_set( producer_properties, "fgcolour", mlt_properties_get( my_properties, "fgcolour" ) );
+       mlt_properties_set( producer_properties, "bgcolour", mlt_properties_get( my_properties, "bgcolour" ) );
+       mlt_properties_set( producer_properties, "olcolour", mlt_properties_get( my_properties, "olcolour" ) );
+       mlt_properties_set( producer_properties, "pad", mlt_properties_get( my_properties, "pad" ) );
+       mlt_properties_set( producer_properties, "outline", mlt_properties_get( my_properties, "outline" ) );
+       mlt_properties_set( producer_properties, "align", mlt_properties_get( my_properties, "halign" ) );
 }
 
+static void setup_transition( mlt_filter filter, mlt_transition transition )
+{
+       mlt_properties my_properties = MLT_FILTER_PROPERTIES( filter );
+       mlt_properties transition_properties = MLT_TRANSITION_PROPERTIES( transition );
+
+       mlt_properties_set( transition_properties, "geometry", mlt_properties_get( my_properties, "geometry" ) );
+       mlt_properties_set( transition_properties, "halign", mlt_properties_get( my_properties, "halign" ) );
+       mlt_properties_set( transition_properties, "valign", mlt_properties_get( my_properties, "valign" ) );
+       mlt_properties_set_int( transition_properties, "out", mlt_properties_get_int( my_properties, "_out" ) );
+       mlt_properties_set_int( transition_properties, "refresh", 1 );
+}
+
+
 /** 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
+       int error = 0;
        mlt_filter filter = mlt_frame_pop_service( frame );
+       mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+       mlt_producer producer = mlt_properties_get_data( properties, "_producer", NULL );
+       mlt_transition transition = mlt_properties_get_data( properties, "_transition", NULL );
+       mlt_frame text_frame = NULL;
+       mlt_position position = 0;
 
+       // Configure this filter
        mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
+       setup_producer( filter, producer, frame );
+       setup_transition( filter, transition );
+       mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
 
-       apply_filter(filter, frame);
+       // Make sure the producer is in the correct position
+       position = mlt_filter_get_position( filter, frame );
+       mlt_producer_seek( producer, position );
 
-       mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
+       // Get the b frame and process with transition if successful
+       if ( mlt_service_get_frame( MLT_PRODUCER_SERVICE( producer ), &text_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( text_frame );
 
-       // Need to get the image
-       return mlt_frame_get_image( frame, image, format, width, height, 1 );
-}
+               // Set the frame and text_frame to be in the same position and have same consumer requirements
+               mlt_frame_set_position( text_frame, position );
+               mlt_frame_set_position( frame, position );
+               mlt_properties_set_int( b_props, "consumer_deinterlace", mlt_properties_get_int( a_props, "consumer_deinterlace" ) );
 
+               // Apply all filters that are attached to this filter to the b frame
+               mlt_service_apply_filters( MLT_FILTER_SERVICE( filter ), text_frame, 0 );
+
+               // Process the frame
+               mlt_transition_process( transition, frame, text_frame );
+
+               // Get the image
+               *format = mlt_image_yuv422;
+               error = mlt_frame_get_image( frame, image, format, width, height, 1 );
+
+               // Close the b frame
+               mlt_frame_close( text_frame );
+       }
+
+       return error;
+}
 
 /** Filter processing.
 */
-
 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
 {
-       // Push the filter
+       // Get the properties of the frame
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+
+       // Save the frame out point
+       mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_out", mlt_properties_get_int( properties, "out" ) );
+
+       // Push the filter on to the stack
        mlt_frame_push_service( frame, filter );
 
-       // Register the get image method
+       // Push the get_image on to the stack
        mlt_frame_push_get_image( frame, filter_get_image );
 
-       // Return the frame
        return frame;
 }
 
 /** Constructor for the filter.
 */
-
-mlt_filter filter_dynamictext_init( mlt_profile profile, mlt_service_type type, const char *id, void *arg )
+mlt_filter filter_dynamictext_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       // Create the filter
-       mlt_filter filter = mlt_filter_new( );
-       mlt_filter watermark = mlt_factory_filter( profile, "watermark", "pango:" );
+       mlt_filter filter = mlt_filter_new();
+       mlt_transition transition = mlt_factory_transition( profile, "composite", NULL );
+       mlt_producer producer = mlt_factory_producer( profile, mlt_environment( "MLT_PRODUCER" ), "pango:" );
 
-       // Initialise it
-       if ( filter && watermark )
+       if ( filter && transition && producer )
        {
-               // Get the properties
-               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties my_properties = MLT_FILTER_PROPERTIES( filter );
+
+               // Register the transition for reuse/destruction
+       mlt_properties_set_data( my_properties, "_transition", transition, 0, ( mlt_destructor )mlt_transition_close, NULL );
 
-               // Store the watermark filter for future use
-               mlt_properties_set_data( properties, "_watermark", watermark, 0, ( mlt_destructor )mlt_filter_close, NULL );
+               // Register the producer for reuse/destruction
+               mlt_properties_set_data( my_properties, "_producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
+
+               // Ensure that we loop
+               mlt_properties_set( MLT_PRODUCER_PROPERTIES( producer ), "eof", "loop" );
 
                // Assign default values
-               mlt_properties_set( properties, "argument", arg ? arg: "#timecode#" );
-               mlt_properties_set( properties, "geometry", "0%/0%:100%x100%:100" );
-               mlt_properties_set( properties, "family", "Sans" );
-               mlt_properties_set( properties, "size", "48" );
-               mlt_properties_set( properties, "weight", "400" );
-               mlt_properties_set( properties, "fgcolour", "0x000000ff" );
-               mlt_properties_set( properties, "bgcolour", "0x00000020" );
-               mlt_properties_set( properties, "olcolour", "0x00000000" );
-               mlt_properties_set( properties, "pad", "0" );
-               mlt_properties_set( properties, "halign", "left" );
-               mlt_properties_set( properties, "valign", "top" );
-               mlt_properties_set( properties, "outline", "0" );
-
-               // Specify the processing method
+               mlt_properties_set( my_properties, "argument", arg ? arg: "#timecode#" );
+               mlt_properties_set( my_properties, "geometry", "0%/0%:100%x100%:100" );
+               mlt_properties_set( my_properties, "family", "Sans" );
+               mlt_properties_set( my_properties, "size", "48" );
+               mlt_properties_set( my_properties, "weight", "400" );
+               mlt_properties_set( my_properties, "fgcolour", "0x000000ff" );
+               mlt_properties_set( my_properties, "bgcolour", "0x00000020" );
+               mlt_properties_set( my_properties, "olcolour", "0x00000000" );
+               mlt_properties_set( my_properties, "pad", "0" );
+               mlt_properties_set( my_properties, "halign", "left" );
+               mlt_properties_set( my_properties, "valign", "top" );
+               mlt_properties_set( my_properties, "outline", "0" );
+
+               mlt_properties_set_int( my_properties, "_filter_private", 1 );
+
                filter->process = filter_process;
        }
-       else // filter or watermark failed for some reason
+       else
        {
                if( filter )
                {
-                       mlt_filter_close(filter);
+                       mlt_filter_close( filter );
                }
 
-               if( watermark )
+               if( transition )
                {
-                       mlt_filter_close(watermark);
+                       mlt_transition_close( transition );
+               }
+
+               if( producer )
+               {
+                       mlt_producer_close( producer );
                }
 
                filter = NULL;
        }
-
        return filter;
 }
index e7b574cadd51e0f51cad6b82a3e56bfd532f3d6e..81891d88307b55aae1b1a1bd0b08708fc2a01219 100644 (file)
@@ -75,11 +75,10 @@ static int filter_scale( mlt_frame this, uint8_t **image, mlt_image_format *form
        case mlt_image_rgb24a:
        case mlt_image_opengl:
        {
-               // Create the output image
-               uint8_t *output = mlt_pool_alloc( size );
-
                if ( strcmp( interps, "none" ) && ( iwidth != owidth || iheight != oheight ) )
                {
+                       // Create the output image
+                       uint8_t *output = mlt_pool_alloc( size );
                        GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( *image, GDK_COLORSPACE_RGB,
                                ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ), 8, iwidth, iheight,
                                iwidth * bpp, NULL, NULL );
index deb8bd27c354c3020833a9ea315a418dee9692f3..4969dd2025d6575d9e1222beead30e45bdd21a37 100644 (file)
@@ -123,7 +123,7 @@ static PangoFT2FontMap *fontmap = NULL;
 
 mlt_producer producer_pango_init( const char *filename )
 {
-       producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
+       producer_pango this = calloc( 1, sizeof( struct producer_pango_s ) );
        if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
        {
                mlt_producer producer = &this->parent;
@@ -154,8 +154,10 @@ mlt_producer producer_pango_init( const char *filename )
                mlt_properties_set( properties, "style", "normal" );
                mlt_properties_set( properties, "encoding", "UTF-8" );
                mlt_properties_set_int( properties, "weight", PANGO_WEIGHT_NORMAL );
+               mlt_properties_set_int( properties, "seekable", 1 );
 
                if ( filename == NULL || ( filename && ( !strcmp( filename, "" )
+                       || strstr( filename, "<producer>" )
                        // workaround for old kdenlive countdown generator
                        || strstr( filename, "&lt;producer&gt;" ) ) ) )
                {
@@ -167,7 +169,8 @@ mlt_producer producer_pango_init( const char *filename )
                        char *markup = copy;
                        if ( strstr( markup, "/+" ) )
                                markup = strstr( markup, "/+" ) + 2;
-                       ( *strrchr( markup, '.' ) ) = '\0';
+                       if ( strrchr( markup, '.' ) )
+                               ( *strrchr( markup, '.' ) ) = '\0';
                        while ( strchr( markup, '~' ) )
                                ( *strchr( markup, '~' ) ) = '\n';
                        mlt_properties_set( properties, "resource", filename );
@@ -215,7 +218,8 @@ mlt_producer producer_pango_init( const char *filename )
                                        if ( markup )
                                        {
                                                markup = realloc( markup, size );
-                                               strcat( markup, line );
+                                               if ( markup )
+                                                       strcat( markup, line );
                                        }
                                        else
                                        {
@@ -224,11 +228,14 @@ mlt_producer producer_pango_init( const char *filename )
                                }
                                fclose( f );
 
-                               if ( markup[ strlen( markup ) - 1 ] == '\n' ) 
+                               if ( markup && markup[ strlen( markup ) - 1 ] == '\n' )
                                        markup[ strlen( markup ) - 1 ] = '\0';
 
                                mlt_properties_set( properties, "resource", filename );
-                               mlt_properties_set( properties, "markup", ( markup == NULL ? "" : markup ) );
+                               if ( markup )
+                                       mlt_properties_set( properties, "markup", markup );
+                               else
+                                       mlt_properties_set( properties, "markup", "" );
                                free( markup );
                        }
                        else
@@ -305,7 +312,7 @@ static int iconv_utf8( mlt_properties properties, const char *prop_name, const c
        int result = -1;
        
        iconv_t cd = iconv_open( "UTF-8", encoding );
-       if ( cd != ( iconv_t )-1 )
+       if ( text && ( cd != ( iconv_t )-1 ) )
        {
                char *inbuf_p = text;
                size_t inbuf_n = strlen( text );
@@ -321,9 +328,9 @@ static int iconv_utf8( mlt_properties properties, const char *prop_name, const c
                        mlt_properties_set( properties, prop_name, "" );
 
                mlt_pool_release( outbuf );
-               iconv_close( cd );
                result = 0;
        }
+       iconv_close( cd );
        return result;
 }
 
@@ -364,14 +371,13 @@ static void refresh_image( mlt_frame frame, int width, int height )
        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 );
+                       mlt_geometry_prev_key( key_frames, &item, mlt_frame_original_position( frame ) );
                        sprintf( temp, "%d", item.frame );
                        markup = mlt_properties_get( contents, temp );
                }
@@ -442,8 +448,8 @@ static void refresh_image( mlt_frame frame, int width, int height )
                        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 ) );
+                       mlt_properties_set_int( producer_props, "meta.media.width", gdk_pixbuf_get_width( pixbuf ) );
+                       mlt_properties_set_int( producer_props, "meta.media.height", gdk_pixbuf_get_height( pixbuf ) );
 
                        // Store the width/height of the pixbuf temporarily
                        this->width = gdk_pixbuf_get_width( pixbuf );
@@ -484,8 +490,6 @@ static void refresh_image( mlt_frame frame, int width, int height )
        // 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" ) );
 }
 
 static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
@@ -536,6 +540,9 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 {
        producer_pango this = producer->child;
 
+       // Fetch the producers properties
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+
        // Generate a frame
        *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
 
@@ -547,7 +554,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
        // 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 );
@@ -556,7 +562,11 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
        // Set producer-specific frame properties
        mlt_properties_set_int( properties, "progressive", 1 );
-       mlt_properties_set_double( properties, "aspect_ratio", 1 );
+       double force_ratio = mlt_properties_get_double( producer_properties, "force_aspect_ratio" );
+       if ( force_ratio > 0.0 )
+               mlt_properties_set_double( properties, "aspect_ratio", force_ratio );
+       else
+               mlt_properties_set_double( properties, "aspect_ratio", 1.0);
 
        // Stack the get image callback
        mlt_frame_push_service( *frame, this );
index 5d512d54d64ce07da6ce617e1eaeba9e6293e085..bcf1531f330748f794e9f6afe592d4c04c04a024 100644 (file)
@@ -214,3 +214,9 @@ parameters:
     type: integer
     description: The last requested scaled image height.
     readonly: yes
+    
+  - identifier: force_aspect_ratio
+    title: Sample aspect ratio
+    type: float
+    description: Optionally override a (mis)detected aspect ratio
+    mutable: yes
index 73694fbbb972152db20ff47962cd5d14ecb7c071..351cd8e69c7ff79c7c60f22b63b93183738766eb 100644 (file)
@@ -22,6 +22,7 @@
 #include <framework/mlt_frame.h>
 #include <framework/mlt_cache.h>
 #include <framework/mlt_log.h>
+#include <framework/mlt_tokeniser.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #include "config.h"
@@ -39,7 +40,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <ctype.h>
 
+// this protects concurrent access to gdk_pixbuf
 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 typedef struct producer_pixbuf_s *producer_pixbuf;
@@ -55,26 +58,29 @@ struct producer_pixbuf_s
        int pixbuf_idx;
        int width;
        int height;
-       int alpha;
+       uint8_t *alpha;
        uint8_t *image;
        mlt_cache_item image_cache;
-       pthread_mutex_t mutex;
+       mlt_cache_item alpha_cache;
+       mlt_cache_item pixbuf_cache;
+       GdkPixbuf *pixbuf;
+       mlt_image_format format;
 };
 
-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 void load_filenames( producer_pixbuf self, mlt_properties producer_properties );
+static int refresh_pixbuf( producer_pixbuf self, mlt_frame frame );
 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 )
+       producer_pixbuf self = calloc( 1, sizeof( struct producer_pixbuf_s ) );
+       if ( self != NULL && mlt_producer_init( &self->parent, self ) == 0 )
        {
-               mlt_producer producer = &this->parent;
+               mlt_producer producer = &self->parent;
 
                // Get the properties interface
-               mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
+               mlt_properties properties = MLT_PRODUCER_PROPERTIES( &self->parent );
        
                // Callback registration
                producer->get_frame = producer_get_frame;
@@ -85,39 +91,39 @@ mlt_producer producer_pixbuf_init( char *filename )
                mlt_properties_set_int( properties, "ttl", 25 );
                mlt_properties_set_int( properties, "aspect_ratio", 1 );
                mlt_properties_set_int( properties, "progressive", 1 );
+               mlt_properties_set_int( properties, "seekable", 1 );
+                mlt_properties_set_int( properties, "loop", 1 );
 
                // Validate the resource
                if ( filename )
-                       load_filenames( this, properties );
-               if ( this->count )
+                       load_filenames( self, properties );
+               if ( self->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_properties_set_data( frame_properties, "producer_pixbuf", self, 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 );
+                               refresh_pixbuf( self, frame );
+                               mlt_cache_item_close( self->pixbuf_cache );
                                mlt_frame_close( frame );
                        }
                }
-               if ( this->width == 0 )
+               if ( self->width == 0 )
                {
                        producer_close( producer );
                        producer = NULL;
                }
                return producer;
        }
-       free( this );
+       free( self );
        return NULL;
 }
 
-static void load_filenames( producer_pixbuf this, mlt_properties producer_properties )
+static int load_svg( producer_pixbuf self, mlt_properties properties, const char *filename )
 {
-       char *filename = mlt_properties_get( producer_properties, "resource" );
-       this->filenames = mlt_properties_new( );
+       int result = 0;
 
        // Read xml string
        if ( strstr( filename, "<svg" ) )
@@ -130,28 +136,36 @@ static void load_filenames( producer_pixbuf this, mlt_properties producer_proper
                {
                        // Write the svg into the temp file
                        ssize_t remaining_bytes;
-                       char *xml = filename;
-                       
+                       const 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 );
+                       mlt_properties_set( self->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 );
+                       mlt_properties_set_data( properties, "__temporary_file__", fullname, 0, ( mlt_destructor )unlink, NULL );
+                       result = 1;
                }
        }
-       // Obtain filenames
-       else if ( strchr( filename, '%' ) != NULL )
+       return result;
+}
+
+static int load_sequence_sprintf( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with pattern
+       if ( strchr( filename, '%' ) != NULL )
        {
                // handle picture sequences
-               int i = mlt_properties_get_int( producer_properties, "begin" );
+               int i = mlt_properties_get_int( properties, "begin" );
                int gap = 0;
                char full[1024];
                int keyvalue = 0;
@@ -164,7 +178,7 @@ static void load_filenames( producer_pixbuf this, mlt_properties producer_proper
                        if ( stat( full, &buf ) == 0 )
                        {
                                sprintf( key, "%d", keyvalue ++ );
-                               mlt_properties_set( this->filenames, key, full );
+                               mlt_properties_set( self->filenames, key, full );
                                gap = 0;
                        }
                        else
@@ -172,10 +186,72 @@ static void load_filenames( producer_pixbuf this, mlt_properties producer_proper
                                gap ++;
                        }
                }
-               if ( mlt_properties_count( this->filenames ) > 0 )
-                       mlt_properties_set_int( producer_properties, "ttl", 1 );
+               if ( mlt_properties_count( self->filenames ) > 0 )
+               {
+                       mlt_properties_set_int( properties, "ttl", 1 );
+                       result = 1;
+               }
        }
-       else if ( strstr( filename, "/.all." ) != NULL )
+       return result;
+}
+
+static int load_sequence_deprecated( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+       const char *start;
+
+       // This approach is deprecated in favor of the begin querystring parameter.
+       // Obtain filenames with pattern containing a begin value, e.g. foo%1234d.png
+       if ( ( start = strchr( filename, '%' ) ) )
+       {
+               const char *end = ++start;
+               while ( isdigit( *end ) ) end++;
+               if ( end > start && ( end[0] == 'd' || end[0] == 'i' || end[0] == 'u' ) )
+               {
+                       int n = end - start;
+                       char *s = calloc( 1, n + 1 );
+                       strncpy( s, start, n );
+                       mlt_properties_set( properties, "begin", s );
+                       free( s );
+                       s = calloc( 1, strlen( filename ) + 2 );
+                       strncpy( s, filename, start - filename );
+                       sprintf( s + ( start - filename ), ".%d%s", n, end );
+                       result = load_sequence_sprintf( self, properties, s );
+                       free( s );
+               }
+       }
+       return result;
+}
+
+static int load_sequence_querystring( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with pattern and begin value in query string
+       if ( strchr( filename, '%' ) && strchr( filename, '?' ) )
+       {
+               // Split filename into pattern and query string
+               char *s = strdup( filename );
+               char *querystring = strrchr( s, '?' );
+               *querystring++ = '\0';
+               if ( strstr( filename, "begin=" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin=" ) + 6 );
+               else if ( strstr( filename, "begin:" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin:" ) + 6 );
+               // Coerce to an int value so serialization does not have any extra query string cruft
+               mlt_properties_set_int( properties, "begin", mlt_properties_get_int( properties, "begin" ) );
+               result = load_sequence_sprintf( self, properties, s );
+               free( s );
+       }
+       return result;
+}
+
+static int load_folder( producer_pixbuf self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with folder
+       if ( strstr( filename, "/.all." ) != NULL )
        {
                char wildcard[ 1024 ];
                char *dir_name = strdup( filename );
@@ -184,49 +260,107 @@ static void load_filenames( producer_pixbuf this, mlt_properties producer_proper
                *( strstr( dir_name, "/.all." ) + 1 ) = '\0';
                sprintf( wildcard, "*%s", extension );
 
-               mlt_properties_dir_list( this->filenames, dir_name, wildcard, 1 );
+               mlt_properties_dir_list( self->filenames, dir_name, wildcard, 1 );
 
                free( dir_name );
+               result = 1;
        }
-       else
+       return result;
+}
+
+static void load_filenames( producer_pixbuf self, mlt_properties properties )
+{
+       char *filename = mlt_properties_get( properties, "resource" );
+       self->filenames = mlt_properties_new( );
+
+       if (!load_svg( self, properties, filename ) &&
+               !load_sequence_querystring( self, properties, filename ) &&
+               !load_sequence_sprintf( self, properties, filename ) &&
+               !load_sequence_deprecated( self, properties, filename ) &&
+               !load_folder( self, properties, filename ) )
        {
-               mlt_properties_set( this->filenames, "0", filename );
+               mlt_properties_set( self->filenames, "0", filename );
        }
-
-       this->count = mlt_properties_count( this->filenames );
+       self->count = mlt_properties_count( self->filenames );
 }
 
-static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int height )
+static GdkPixbuf* reorient_with_exif( producer_pixbuf self, int image_idx, GdkPixbuf *pixbuf )
 {
-       // Obtain properties of frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+#ifdef USE_EXIF
+       mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( &self->parent );
+       ExifData *d = exif_data_new_from_file( mlt_properties_get_value( self->filenames, image_idx ) );
+       ExifEntry *entry;
+       int exif_orientation = 0;
 
-       // Obtain the producer
-       mlt_producer producer = &this->parent;
+       /* get orientation and rotate image accordingly if necessary */
+       if (d)
+       {
+               if ( ( entry = exif_content_get_entry ( d->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION ) ) )
+                       exif_orientation = exif_get_short (entry->data, exif_data_get_byte_order (d));
 
-       // Obtain properties of producer
-       mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
+               /* Free the EXIF data */
+               exif_data_unref(d);
+       }
 
-       // 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;
+       // Remember EXIF value, might be useful for someone
+       mlt_properties_set_int( producer_props, "_exif_orientation" , exif_orientation );
 
-       // 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;
+       if ( exif_orientation > 1 )
+       {
+               GdkPixbuf *processed = NULL;
+               GdkPixbufRotation matrix = GDK_PIXBUF_ROTATE_NONE;
+
+               // Rotate image according to exif data
+               switch ( exif_orientation ) {
+                 case 2:
+                         processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+                         break;
+                 case 3:
+                         matrix = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
+                         processed = pixbuf;
+                         break;
+                 case 4:
+                         processed = gdk_pixbuf_flip ( pixbuf, FALSE );
+                         break;
+                 case 5:
+                         matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
+                         processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+                         break;
+                 case 6:
+                         matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
+                         processed = pixbuf;
+                         break;
+                 case 7:
+                         matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
+                         processed = gdk_pixbuf_flip ( pixbuf, TRUE );
+                         break;
+                 case 8:
+                         matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
+                         processed = pixbuf;
+                         break;
+               }
+               if ( processed )
+               {
+                       pixbuf = gdk_pixbuf_rotate_simple( processed, matrix );
+                       g_object_unref( processed );
+               }
+       }
+#endif
+       return pixbuf;
+}
 
-       // 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 );
+static int refresh_pixbuf( producer_pixbuf self, mlt_frame frame )
+{
+       // Obtain properties of frame and producer
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_producer producer = &self->parent;
+       mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
 
        // Check if user wants us to reload the image
        if ( mlt_properties_get_int( producer_props, "force_reload" ) )
        {
-               pixbuf = NULL;
-               this->image = NULL;
+               self->pixbuf = NULL;
+               self->image = NULL;
                mlt_properties_set_int( producer_props, "force_reload", 0 );
        }
 
@@ -234,144 +368,91 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int
        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" );
+       mlt_position position = mlt_frame_original_position( frame );
        position += mlt_producer_get_in( producer );
 
        // Image index
-       int image_idx = ( int )floor( ( double )position / ttl ) % this->count;
+        int loop = mlt_properties_get_int( producer_props, "loop" );
+        int current_idx;
+        if (loop) {
+               current_idx = ( int )floor( ( double )position / ttl ) % self->count;
+        } else {
+               current_idx = MIN(( double )position / ttl, self->count - 1);
+        }
 
        // 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 );
-               }
+       sprintf( image_key, "%d", current_idx );
 
-               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_int( cached_props, "alpha" );
-
-                       if ( width != 0 && ( width != this->width || height != this->height ) )
-                               this->image = NULL;
-               }
-       }
        int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
-       
-    // 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->pixbuf_idx )
-               pixbuf = NULL;
-       mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "image %p pixbuf %p idx %d image_idx %d pixbuf_idx %d width %d\n",
-               this->image, pixbuf, image_idx, this->image_idx, this->pixbuf_idx, width );
-       if ( !pixbuf || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
+
+       if ( current_idx != self->pixbuf_idx )
+               self->pixbuf = NULL;
+       if ( !self->pixbuf || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
        {
-               this->image = NULL;
-               pixbuf = gdk_pixbuf_new_from_file( mlt_properties_get_value( this->filenames, image_idx ), &error );
+               GError *error = NULL;
 
-               if ( pixbuf )
+               self->image = NULL;
+               pthread_mutex_lock( &g_mutex );
+               self->pixbuf = gdk_pixbuf_new_from_file( mlt_properties_get_value( self->filenames, current_idx ), &error );
+               if ( self->pixbuf )
                {
-#ifdef USE_EXIF
                        // Read the exif value for this file
-                       if ( disable_exif == 0) {
-                               ExifData *d = exif_data_new_from_file( mlt_properties_get_value( this->filenames, image_idx ) );
-                               ExifEntry *entry;
-                               int exif_orientation = 0;
-
-                               /* get orientation and rotate image accordingly if necessary */
-                               if (d) {
-                                       if ( ( entry = exif_content_get_entry ( d->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION ) ) )
-                                               exif_orientation = exif_get_short (entry->data, exif_data_get_byte_order (d));
-
-                                       /* Free the EXIF data */
-                                       exif_data_unref(d);
-                               }
-                               
-                               // Remember EXIF value, might be useful for someone
-                               mlt_properties_set_int( producer_props, "_exif_orientation" , exif_orientation );
-
-                               if ( exif_orientation > 1 )
-                               {
-                                       GdkPixbuf *processed = NULL;
-                                       GdkPixbufRotation matrix = GDK_PIXBUF_ROTATE_NONE;
-
-                                       // Rotate image according to exif data
-                                       switch ( exif_orientation ) {
-                                         case 2:
-                                             processed = gdk_pixbuf_flip ( pixbuf, TRUE );
-                                             break;
-                                         case 3:
-                                             matrix = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
-                                             processed = pixbuf;
-                                             break;
-                                         case 4:
-                                             processed = gdk_pixbuf_flip ( pixbuf, FALSE );
-                                             break;
-                                         case 5:
-                                             matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
-                                             processed = gdk_pixbuf_flip ( pixbuf, TRUE );
-                                             break;
-                                         case 6:
-                                             matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
-                                             processed = pixbuf;
-                                             break;
-                                         case 7:
-                                             matrix = GDK_PIXBUF_ROTATE_CLOCKWISE;
-                                             processed = gdk_pixbuf_flip ( pixbuf, TRUE );
-                                             break;
-                                         case 8:
-                                             matrix = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
-                                             processed = pixbuf;
-                                             break;
-                                       }
-                                       if ( processed )
-                                               pixbuf = gdk_pixbuf_rotate_simple( processed, matrix );
-                               }
-                       }
-#endif
+                       if ( !disable_exif )
+                               self->pixbuf = reorient_with_exif( self, current_idx, self->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" );
-                       this->pixbuf_idx = image_idx;
+                       mlt_cache_item_close( self->pixbuf_cache );
+                       mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf", self->pixbuf, 0, ( mlt_destructor )g_object_unref );
+                       self->pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
+                       self->pixbuf_idx = current_idx;
+
+                       // Store the width/height of the pixbuf temporarily
+                       self->width = gdk_pixbuf_get_width( self->pixbuf );
+                       self->height = gdk_pixbuf_get_height( self->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_properties_set_int( producer_props, "meta.media.width", self->width );
+                       mlt_properties_set_int( producer_props, "meta.media.height", self->height );
                        mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
                        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 );
                }
+               pthread_mutex_unlock( &g_mutex );
        }
 
+       // Set width/height of frame
+       mlt_properties_set_int( properties, "width", self->width );
+       mlt_properties_set_int( properties, "height", self->height );
+
+       return current_idx;
+}
+
+static void refresh_image( producer_pixbuf self, mlt_frame frame, mlt_image_format format, int width, int height )
+{
+       // Obtain properties of frame and producer
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_producer producer = &self->parent;
+
+       // Get index and pixbuf
+       int current_idx = refresh_pixbuf( self, frame );
+
+       // optimization for subsequent iterations on single picture
+       if ( current_idx != self->image_idx || width != self->width || height != self->height )
+               self->image = NULL;
+       mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "image %p pixbuf %p idx %d current_idx %d pixbuf_idx %d width %d\n",
+               self->image, self->pixbuf, current_idx, self->image_idx, self->pixbuf_idx, width );
+
        // If we have a pixbuf and we need an image
-       if ( pixbuf && width > 0 && !this->image )
+       if ( self->pixbuf && ( !self->image || ( format != mlt_image_none && format != self->format ) ) )
        {
                char *interps = mlt_properties_get( properties, "rescale.interp" );
                int interp = GDK_INTERP_BILINEAR;
 
-               if ( strcmp( interps, "nearest" ) == 0 )
+               if ( !interps ) {
+                       // Keep bilinear by default
+               }
+               else if ( strcmp( interps, "nearest" ) == 0 )
                        interp = GDK_INTERP_NEAREST;
                else if ( strcmp( interps, "tiles" ) == 0 )
                        interp = GDK_INTERP_TILES;
@@ -379,24 +460,27 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int
                        interp = GDK_INTERP_HYPER;
 
                // Note - the original pixbuf is already safe and ready for destruction
-               pixbuf = gdk_pixbuf_scale_simple( pixbuf, width, height, interp );
+               pthread_mutex_lock( &g_mutex );
+               GdkPixbuf* pixbuf = gdk_pixbuf_scale_simple( self->pixbuf, width, height, interp );
 
                // Store width and height
-               this->width = width;
-               this->height = height;
-               
+               self->width = width;
+               self->height = height;
+
                // Allocate/define image
-               this->alpha = gdk_pixbuf_get_has_alpha( pixbuf );
+               int has_alpha = gdk_pixbuf_get_has_alpha( pixbuf );
                int src_stride = gdk_pixbuf_get_rowstride( pixbuf );
-               int dst_stride = this->width * ( this->alpha ? 4 : 3 );
+               int dst_stride = self->width * ( has_alpha ? 4 : 3 );
                int image_size = dst_stride * ( height + 1 );
-               this->image = mlt_pool_alloc( image_size );
+               self->image = mlt_pool_alloc( image_size );
+               self->alpha = NULL;
+               self->format = has_alpha ? mlt_image_rgb24a : mlt_image_rgb24;
 
                if ( src_stride != dst_stride )
                {
-                       int y = this->height;
+                       int y = self->height;
                        uint8_t *src = gdk_pixbuf_get_pixels( pixbuf );
-                       uint8_t *dst = this->image;
+                       uint8_t *dst = self->image;
                        while ( y-- )
                        {
                                memcpy( dst, src, dst_stride );
@@ -406,88 +490,110 @@ static void refresh_image( producer_pixbuf this, mlt_frame frame, int width, int
                }
                else
                {
-                       memcpy( this->image, gdk_pixbuf_get_pixels( pixbuf ), src_stride * height );
+                       memcpy( self->image, gdk_pixbuf_get_pixels( pixbuf ), src_stride * height );
                }
-               if ( !use_cache )
-                       mlt_cache_item_close( this->image_cache );
-               mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", this->image, image_size, mlt_pool_release );
-               this->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
-               this->image_idx = image_idx;
+               pthread_mutex_unlock( &g_mutex );
 
-               // Finished with pixbuf now
-               g_object_unref( pixbuf );
+               // Convert image to requested format
+               if ( format != mlt_image_none && format != self->format )
+               {
+                       uint8_t *buffer = NULL;
 
-               // Ensure we update the cache when we need to
-               update_cache = use_cache;
-       }
+                       // First, set the image so it can be converted when we get it
+                       mlt_frame_replace_image( frame, self->image, self->format, width, height );
+                       mlt_frame_set_image( frame, self->image, image_size, mlt_pool_release );
+                       self->format = format;
 
-       // 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 );
-       }
+                       // get_image will do the format conversion
+                       mlt_frame_get_image( frame, &buffer, &format, &width, &height, 0 );
 
-       // 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" ) );
+                       // cache copies of the image and alpha buffers
+                       if ( buffer )
+                       {
+                               image_size = mlt_image_format_size( format, width, height, NULL );
+                               self->image = mlt_pool_alloc( image_size );
+                               memcpy( self->image, buffer, image_size );
+                       }
+                       if ( ( buffer = mlt_frame_get_alpha_mask( frame ) ) )
+                       {
+                               self->alpha = mlt_pool_alloc( width * height );
+                               memcpy( self->alpha, buffer, width * 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_frame_set_image( cached, this->image, this->width * ( this->alpha ? 4 : 3 ) * this->height, mlt_pool_release );
-               mlt_properties_set_int( cached_props, "alpha", this->alpha );
-               mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL );
+               // Update the cache
+               mlt_cache_item_close( self->image_cache );
+               mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", self->image, image_size, mlt_pool_release );
+               self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
+               self->image_idx = current_idx;
+               mlt_cache_item_close( self->alpha_cache );
+               self->alpha_cache = NULL;
+               if ( self->alpha )
+               {
+                       mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", self->alpha, width * height, mlt_pool_release );
+                       self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
+               }
+
+               // Finished with pixbuf now
+               g_object_unref( pixbuf );
        }
 
-       pthread_mutex_unlock( &g_mutex );
+       // Set width/height of frame
+       mlt_properties_set_int( properties, "width", self->width );
+       mlt_properties_set_int( properties, "height", self->height );
 }
 
 static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
 {
        int error = 0;
        
-       // Obtain properties of frame
+       // Obtain properties of frame and producer
        mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       producer_pixbuf self = mlt_properties_get_data( properties, "producer_pixbuf", NULL );
+       mlt_producer producer = &self->parent;
 
-       // Obtain the producer for this frame
-       producer_pixbuf this = mlt_properties_get_data( properties, "producer_pixbuf", NULL );
-
+       // Use the width and height suggested by the rescale filter because we can do our own scaling.
        *width = mlt_properties_get_int( properties, "rescale_width" );
        *height = mlt_properties_get_int( properties, "rescale_height" );
 
-       mlt_service_lock( MLT_PRODUCER_SERVICE( &this->parent ) );
+       // Restore pixbuf and image
+       mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) );
+       self->pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
+       self->pixbuf = mlt_cache_item_data( self->pixbuf_cache, NULL );
+       self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" );
+       self->image = mlt_cache_item_data( self->image_cache, NULL );
+       self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" );
+       self->alpha = mlt_cache_item_data( self->alpha_cache, NULL );
 
        // Refresh the image
-       refresh_image( this, frame, *width, *height );
+       refresh_image( self, frame, *format, *width, *height );
 
        // Get width and height (may have changed during the refresh)
-       *width = this->width;
-       *height = this->height;
-       *format = this->alpha ? mlt_image_rgb24a : mlt_image_rgb24;
+       *width = self->width;
+       *height = self->height;
+       *format = self->format;
 
        // 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 ( self->image )
        {
                // Clone the image
-               int image_size = this->width * this->height * ( this->alpha ? 4 :3 );
+               int image_size = mlt_image_format_size( self->format, self->width, self->height, NULL );
                uint8_t *image_copy = mlt_pool_alloc( image_size );
-               memcpy( image_copy, this->image, image_size );
+               memcpy( image_copy, self->image, image_size );
                // Now update properties so we free the copy after
                mlt_frame_set_image( frame, image_copy, image_size, mlt_pool_release );
                // We're going to pass the copy on
                *buffer = image_copy;
-               mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "%dx%d (%s)\n",
-                       this->width, this->height, mlt_image_format_name( *format ) );
+               mlt_log_debug( MLT_PRODUCER_SERVICE( &self->parent ), "%dx%d (%s)\n",
+                       self->width, self->height, mlt_image_format_name( *format ) );
+               // Clone the alpha channel
+               if ( self->alpha )
+               {
+                       image_copy = mlt_pool_alloc( self->width * self->height );
+                       memcpy( image_copy, self->alpha, self->width * self->height );
+                       mlt_frame_set_alpha( frame, image_copy, self->width * self->height, mlt_pool_release );
+               }
        }
        else
        {
@@ -495,9 +601,10 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        }
 
        // Release references and locks
-       pthread_mutex_unlock( &this->mutex );
-       mlt_cache_item_close( this->image_cache );
-       mlt_service_unlock( MLT_PRODUCER_SERVICE( &this->parent ) );
+       mlt_cache_item_close( self->pixbuf_cache );
+       mlt_cache_item_close( self->image_cache );
+       mlt_cache_item_close( self->alpha_cache );
+       mlt_service_unlock( MLT_PRODUCER_SERVICE( &self->parent ) );
 
        return error;
 }
@@ -505,33 +612,33 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
 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;
+       producer_pixbuf self = 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 );
+       if ( self->filenames == NULL && mlt_properties_get( producer_properties, "resource" ) != NULL )
+               load_filenames( self, producer_properties );
 
        // Generate a frame
        *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
 
-       if ( *frame != NULL && this->count > 0 )
+       if ( *frame != NULL && self->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 );
+               mlt_properties_set_data( properties, "producer_pixbuf", self, 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 );
+               // Refresh the pixbuf
+               self->pixbuf_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.pixbuf" );
+               self->pixbuf = mlt_cache_item_data( self->pixbuf_cache, NULL );
+               refresh_pixbuf( self, *frame );
+               mlt_cache_item_close( self->pixbuf_cache );
 
                // Set producer-specific frame properties
                mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) );
@@ -554,11 +661,10 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
 static void producer_close( mlt_producer parent )
 {
-       producer_pixbuf this = parent->child;
-       pthread_mutex_destroy( &this->mutex );
+       producer_pixbuf self = parent->child;
        parent->close = NULL;
        mlt_service_cache_purge( MLT_PRODUCER_SERVICE(parent) );
        mlt_producer_close( parent );
-       mlt_properties_close( this->filenames );
-       free( this );
+       mlt_properties_close( self->filenames );
+       free( self );
 }
index c04766e8b49e9f4c996be0f7909bb89f2ec9b2f3..edd1073f48841aeceb11e545ecd5ebf72912cbe0 100644 (file)
@@ -2,7 +2,7 @@ schema_version: 0.1
 type: producer
 identifier: pixbuf
 title: GDK-PixBuf
-version: 1
+version: 2
 copyright: Ushodaya Enterprises Limited
 creator: Dan Dennedy
 license: LGPLv2.1
@@ -23,13 +23,17 @@ parameters:
     type: string
     description: >
         The name of a graphics file loadable by a gdk-pixbuf loader. 
-        See /usr/lib/gdk-pixbuf/loaders.
+        See the output of gdk-pixbuf-query-loaders.
         Definitely png, jpeg, tiff, pnm, and xpm will work.
         
-        If "%" in filename, the filename is used with sprintf generate a 
+        If "%" in filename, the filename is used with sprintf to generate a
         filename from a counter for multi-file/flipbook animation. The file 
         sequence ends when numeric discontinuity >100.
         
+        If the file sequence does not begin within the count of 100 you
+        can pass the begin property like a query string parameter, for
+        example: anim-%04d.png?begin=1000.
+        
         If filename contains "/.all.", suffix with an extension to load all 
         pictures with matching extension from a directory.
         
@@ -59,13 +63,13 @@ parameters:
     mutable: yes
     widget: spinner
     
-  - identifier: real_width
+  - identifier: meta.media.width
     title: Real width
     type: integer
     description: The original, unscaled width of the rendered image.
     readonly: yes
     
-  - identifier: real_height
+  - identifier: meta.media.height
     title: Real height
     type: integer
     description: The original, unscaled height of the rendered image.
@@ -98,3 +102,18 @@ parameters:
     minimum: 0
     maximum: 1
     widget: checkbox
+
+  - identifier: force_aspect_ratio
+    title: Sample aspect ratio
+    type: float
+    description: Optionally override a (mis)detected aspect ratio
+    mutable: yes
+
+  - identifier: loop
+    title: Loop sequence of images indefinitively
+    description: when 1 (default) loop sequences of images, when 0, play them only once
+    type: integer
+    default: 1
+    minimum: 0
+    maximum: 1
+    widget: checkbox
index c929f52682d2202896aa316d6515a3a886e98df9..6f4a3a56793bc00f19cb619e107df8e8029a9c11 100644 (file)
@@ -19,7 +19,9 @@
  */
        .file   "scale_line_22_yuv_mmx.S"
        .version        "01.01"
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
        .section .note.GNU-stack,"",%progbits
+#endif
 
 .extern printf
 
@@ -31,7 +33,7 @@ MSG: .ascii "scale_line_22_yuv_mmx: %d %d\n"
        .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:
index 5932a47852f10727f2526c9579d86e91db70d674..dba6b7b7320d1236db03dab8db5b9125f753bc70 100644 (file)
@@ -14,6 +14,7 @@ GPL_OBJS = jack_rack.o \
        plugin_mgr.o \
        plugin_settings.o \
        process.o \
+       producer_ladspa.o \
        filter_jackrack.o \
        filter_ladspa.o
 
@@ -27,11 +28,11 @@ ifdef GPL
 OBJS += $(GPL_OBJS)
 CFLAGS += -DGPL
 CFLAGS += `pkg-config --cflags libxml-2.0`
-CFLAGS += `pkg-config --cflags glib-2.0`
+CFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --cflags glib-2.0`
 
 LDFLAGS += $(LIBDL)
 LDFLAGS += `pkg-config --libs libxml-2.0`
-LDFLAGS += `pkg-config --libs glib-2.0`
+LDFLAGS += `pkg-config $(PKGCONFIG_PREFIX) --libs glib-2.0`
 LDFLAGS += -lm
 
 YML_FILES = *.yml
@@ -58,14 +59,14 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/jackrack"
-       install -m 644 $(YML_FILES) "$(DESTDIR)$(datadir)/mlt/jackrack"
-       [ -f $(BLACKLIST) ] && install -m 644 $(BLACKLIST) "$(DESTDIR)$(datadir)/mlt/jackrack" || true
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/jackrack"
+       install -m 644 $(YML_FILES) "$(DESTDIR)$(mltdatadir)/jackrack"
+       [ -f $(BLACKLIST) ] && install -m 644 $(BLACKLIST) "$(DESTDIR)$(mltdatadir)/jackrack" || true
 
 uninstall:
-       rm "$(DESTDIR)$(libdir)/mlt/libmltjackrack$(LIBSUF)" 2> /dev/null || true
-       rm -rf "$(DESTDIR)$(datadir)/mlt/jackrack"
+       rm "$(DESTDIR)$(moduledir)/libmltjackrack$(LIBSUF)" 2> /dev/null || true
+       rm -rf "$(DESTDIR)$(mltdatadir)/jackrack"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 22f57615b27bf800ddc9fc9e957e09063c5f8f6c..fee51cb955d365192649f52aa523897e19b825b5 100755 (executable)
@@ -1,7 +1,15 @@
 #!/bin/sh
 
-if [ "$help" != "1" ]
+if [ "$help" = "1" ]
 then
+       cat << EOF
+JACK Rack options:
+
+  --gtk2-prefix=path      - Override the gtk+-2.0 prefix for pkg-config
+
+EOF
+
+else
 
        pkg-config jack
        disable_jack=$?
@@ -23,6 +31,14 @@ then
                fi
                disable_ladspa=`[ -f "$ladspa_prefix/include/ladspa.h" ] && echo 0 || echo 1`
                echo GPL=1 > config.mak
+
+               for i in "$@"
+               do
+                       case $i in
+                               --gtk2-prefix=* )       pkgconfig_prefix="${i#--gtk2-prefix=}" ;;
+                       esac
+               done
+               [ "$pkgconfig_prefix" != "" ] && echo "PKGCONFIG_PREFIX=--define-variable=prefix=\"$pkgconfig_prefix\"" >> config.mak
        fi
 
        if [ "$disable_jack" = "1" -o "$disable_xml2" = "1" -o "$disable_ladspa" = "1" ]
index ce18604e88ac703164e9b54e56d12a6cf2e83613..97d8658a304190764ff2f698c391e9f46027ff89 100644 (file)
@@ -240,6 +240,8 @@ static int jack_process( jack_nframes_t frames, void * data )
                char *dest = jack_port_get_buffer( self->ports[i], frames );
 
                jack_ringbuffer_read( self->ringbuffers[i], dest, ring_size < jack_size ? ring_size : jack_size );
+               if ( ring_size < jack_size )
+                       memset( dest + ring_size, 0, jack_size - ring_size );
        }
 
        return error;
@@ -285,9 +287,10 @@ static void initialise_jack_ports( consumer_jack self )
                        if ( !ports )
                                ports = jack_get_ports( self->jack, NULL, NULL, JackPortIsPhysical | JackPortIsInput );
                        if ( ports )
-                               strcpy( con_name, ports[i] );
+                               strncpy( con_name, ports[i], sizeof( con_name ));
                        else
                                snprintf( con_name, sizeof( con_name ), "system:playback_%d", i + 1);
+                       con_name[ sizeof( con_name ) - 1 ] = '\0';
                }
                mlt_log_verbose( NULL, "JACK connect %s to %s\n", mlt_name, con_name );
                jack_connect( self->jack, mlt_name, con_name );
@@ -303,8 +306,10 @@ static int consumer_play_audio( consumer_jack self, mlt_frame frame, int init_au
        mlt_audio_format afmt = mlt_audio_float;
 
        // Set the preferred params of the test card signal
+       double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame), "_speed" );
        int channels = mlt_properties_get_int( properties, "channels" );
        int frequency = mlt_properties_get_int( properties, "frequency" );
+       int scrub = mlt_properties_get_int( properties, "scrub_audio" );
        int samples = mlt_sample_calculator( mlt_properties_get_double( properties, "fps" ), frequency, self->counter++ );
        float *buffer;
 
@@ -324,12 +329,15 @@ static int consumer_play_audio( consumer_jack self, mlt_frame frame, int init_au
                init_audio = 0;
        }
 
-       if ( init_audio == 0 )
+       if ( init_audio == 0 && ( speed == 1.0 || speed == 0.0 ) )
        {
                int i;
                size_t mlt_size = samples * sizeof(float);
                float volume = mlt_properties_get_double( properties, "volume" );
 
+               if ( !scrub && speed == 0.0 )
+                       volume = 0.0;
+
                if ( volume != 1.0 )
                {
                        float *p = buffer;
@@ -477,7 +485,10 @@ static void *consumer_thread( void *arg )
        int64_t playtime = 0;
        struct timespec tm = { 0, 100000 };
 //     int last_position = -1;
+
+       pthread_mutex_lock( &self->refresh_mutex );
        self->refresh_count = 0;
+       pthread_mutex_unlock( &self->refresh_mutex );
 
        // Loop until told not to
        while( self->running )
index abef3aea569422f2bd757ddc95f6464f20a65650..1d9e48ee91847b8459c7793d69daa0e5657ad4ef 100644 (file)
@@ -15,20 +15,44 @@ parameters:
     type: integer
     minimum: 1
     default: 2
+
   - identifier: out_1
     title: Send L
     type: string
+
   - identifier: out_2
     title: Send R
     type: string
+
   - identifier: volume
     title: Volume
     type: float
     minimum: 0.0
     default: 1.0
+
   - identifier: refresh
     description: >
       Applications should set this to update the video frame when paused.
     type: integer
     minimum: 0
     maximum: 1
+
+  - identifier: audio_off
+    title: Audio off
+    type: integer
+    description: If 1, disable audio output
+    mutable: yes
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
+
+  - identifier: scrub_audio
+    title: Audio scrubbing
+    type: integer
+    description: If enabled, sound is played even when the speed is not normal.
+    mutable: yes
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
index 7ba3bf8585723efbae3557902e7eb3e7f4ccf539..6f09c9550fcc9009a610b1d0abe7352f9e9ffcf2 100644 (file)
@@ -35,6 +35,7 @@ extern mlt_consumer consumer_jack_init( mlt_profile profile, mlt_service_type ty
 
 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 );
+extern mlt_producer producer_ladspa_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 
 plugin_mgr_t *g_jackrack_plugin_mgr = NULL;
 #endif
@@ -42,8 +43,16 @@ plugin_mgr_t *g_jackrack_plugin_mgr = NULL;
 static mlt_properties metadata( mlt_service_type type, const char *id, char *data )
 {
        char file[ PATH_MAX ];
-       snprintf( file, PATH_MAX, "%s/jackrack/%s",
+       if( type == filter_type )
+       {
+               snprintf( file, PATH_MAX, "%s/jackrack/%s",
                          mlt_environment( "MLT_DATA" ), strncmp( id, "ladspa.", 7 ) ? data : "filter_ladspa.yml" );
+       }
+       else
+       {
+               snprintf( file, PATH_MAX, "%s/jackrack/%s",
+                         mlt_environment( "MLT_DATA" ), strncmp( id, "ladspa.", 7 ) ? data : "producer_ladspa.yml" );
+       }
        mlt_properties result = mlt_properties_parse_yaml( file );
 
 #ifdef GPL
@@ -114,15 +123,19 @@ static mlt_properties metadata( mlt_service_type type, const char *id, char *dat
                                if ( LADSPA_IS_HINT_LOGARITHMIC( hint_descriptor ) )
                                        mlt_properties_set( p, "scale", "log" );
                        }
-                       p = mlt_properties_new();
-                       snprintf( key, sizeof(key), "%d", i );
-                       mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL );
-                       mlt_properties_set( p, "identifier", "wetness" );
-                       mlt_properties_set( p, "title", "Wet/Dry" );
-                       mlt_properties_set( p, "type", "float" );
-                       mlt_properties_set_double( p, "default", 1 );
-                       mlt_properties_set_double( p, "minimum", 0 );
-                       mlt_properties_set_double( p, "maximum", 1 );
+
+                       if( type == filter_type )
+                       {
+                               p = mlt_properties_new();
+                               snprintf( key, sizeof(key), "%d", i );
+                               mlt_properties_set_data( params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL );
+                               mlt_properties_set( p, "identifier", "wetness" );
+                               mlt_properties_set( p, "title", "Wet/Dry" );
+                               mlt_properties_set( p, "type", "float" );
+                               mlt_properties_set_double( p, "default", 1 );
+                               mlt_properties_set_double( p, "minimum", 0 );
+                               mlt_properties_set_double( p, "maximum", 1 );
+                       }
                }
        }
 #endif
@@ -142,8 +155,18 @@ MLT_REPOSITORY
                char *s = malloc( strlen( "ladpsa." ) + 21 );
 
                sprintf( s, "ladspa.%lu", desc->id );
-               MLT_REGISTER( filter_type, s, filter_ladspa_init );
-               MLT_REGISTER_METADATA( filter_type, s, metadata, NULL );
+
+               if( desc->has_input )
+               {
+                       MLT_REGISTER( filter_type, s, filter_ladspa_init );
+                       MLT_REGISTER_METADATA( filter_type, s, metadata, NULL );
+               }
+               else
+               {
+                       MLT_REGISTER( producer_type, s, producer_ladspa_init );
+                       MLT_REGISTER_METADATA( producer_type, s, metadata, NULL );
+               }
+
                free( s );
        }
        mlt_factory_register_for_clean_up( g_jackrack_plugin_mgr, (mlt_destructor) plugin_mgr_destroy );
index 4ec111647afe80c7ae19fec07e16b2f2a2e90922..43898d5590aa302cc6d8c61e2d7d93e6d9f3658e 100644 (file)
@@ -93,14 +93,14 @@ static int jack_sync( jack_transport_state_t state, jack_position_t *jack_pos, v
 
 static void on_jack_start( mlt_properties owner, mlt_properties properties )
 {
-       fprintf(stderr, "%s\n", __FUNCTION__);
+       mlt_log_verbose( NULL, "%s\n", __FUNCTION__ );
        jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
        jack_transport_start( jack_client );
 }
 
 static void on_jack_stop( mlt_properties owner, mlt_properties properties )
 {
-       fprintf(stderr, "%s\n", __FUNCTION__);
+       mlt_log_verbose( NULL, "%s\n", __FUNCTION__ );
        jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
        jack_transport_stop( jack_client );
 }
@@ -108,19 +108,12 @@ static void on_jack_stop( mlt_properties owner, mlt_properties properties )
 static void on_jack_seek( mlt_properties owner, mlt_filter filter, mlt_position *position )
 {
        mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
-
-
+       mlt_log_verbose( MLT_FILTER_SERVICE(filter), "%s: %d\n", __FUNCTION__, *position );
        mlt_properties_set_int( properties, "_sync_guard", 1 );
-       mlt_properties_set_position( properties, "_jack_seek", *position );
-       return;
-
-
        mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
        jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
        jack_nframes_t jack_frame = jack_get_sample_rate( jack_client );
        jack_frame *= *position / mlt_profile_fps( profile );
-
-       fprintf(stderr, "%s: %d\n", __FUNCTION__, *position);
        jack_transport_locate( jack_client, jack_frame );
 }
 
@@ -173,11 +166,6 @@ static void initialise_jack_ports( mlt_properties properties )
                sizeof( float *) * channels, mlt_pool_release, NULL );
        mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers,
                sizeof( float *) * channels, mlt_pool_release, NULL );
-
-       // Start Jack processing - required before registering ports
-       pthread_mutex_lock( &g_activate_mutex );
-       jack_activate( jack_client );
-       pthread_mutex_unlock( &g_activate_mutex  );
        
        // Register Jack ports
        for ( i = 0; i < channels; i++ )
@@ -203,6 +191,11 @@ static void initialise_jack_ports( mlt_properties properties )
                }
        }
        
+       // Start Jack processing
+       pthread_mutex_lock( &g_activate_mutex );
+       jack_activate( jack_client );
+       pthread_mutex_unlock( &g_activate_mutex  );
+
        // Establish connections
        for ( i = 0; i < channels; i++ )
        {
@@ -271,6 +264,8 @@ static int jack_process (jack_nframes_t frames, void * data)
                }
                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 );
+               if ( ring_size < jack_size )
+                       memset( &jack_output_buffers[i][ring_size], 0, jack_size - ring_size );
                
                // Return audio through in port
                jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
@@ -304,6 +299,18 @@ static int jack_process (jack_nframes_t frames, void * data)
                }
        }
 
+       // Often jackd does not send the stopped event through the JackSyncCallback
+       jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
+       jack_position_t jack_pos;
+       jack_transport_state_t state = jack_transport_query( jack_client, &jack_pos );
+       int transport_state = mlt_properties_get_int( properties, "_transport_state" );
+       if ( state != transport_state )
+       {
+               mlt_properties_set_int( properties, "_transport_state", state );
+               if ( state == JackTransportStopped )
+                       jack_sync( state, &jack_pos, filter );
+       }
+
        return err;
 }
 
@@ -365,19 +372,9 @@ static int jackrack_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                        jack_ringbuffer_read( input_buffers[j], (char*)( q + j * *samples ), size );
        }
 
-       // Do JACK seeking if requested
+       // help jack_sync() indicate when we are rolling
        mlt_position pos = mlt_frame_get_position( frame );
        mlt_properties_set_position( filter_properties, "_last_pos", pos );
-       if ( pos == mlt_properties_get_position( filter_properties, "_jack_seek" ) )
-       {
-               jack_client_t *jack_client = mlt_properties_get_data( filter_properties, "jack_client", NULL );
-               jack_position_t jack_pos;
-               jack_transport_query( jack_client, &jack_pos );
-               double fps = mlt_profile_fps( mlt_service_profile( MLT_FILTER_SERVICE(filter) ) );
-               jack_nframes_t jack_frame = jack_pos.frame_rate * pos / fps;
-               jack_transport_locate( jack_client, jack_frame );
-               mlt_properties_set_position( filter_properties, "_jack_seek", -1 );
-       }
 
        return 0;
 }
@@ -419,12 +416,20 @@ mlt_filter filter_jackrack_init( mlt_profile profile, mlt_service_type type, con
        mlt_filter this = mlt_filter_new( );
        if ( this != NULL )
        {
-               char name[14];
-               
+               char name[16];
+               char *jack_client_name;
+               jack_status_t status = 0;
+
                snprintf( name, sizeof( name ), "mlt%d", getpid() );
-               jack_client_t *jack_client = jack_client_open( name, JackNullOption, NULL );
+               jack_client_t *jack_client = jack_client_open( name, JackNullOption, &status, NULL );
                if ( jack_client )
                {
+                       if ( status & JackNameNotUnique ) 
+                       {
+                               jack_client_name = jack_get_client_name ( jack_client );
+                               strcpy( name, jack_client_name );
+                       }
+
                        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 ) );
index 75c35aa9405be0b7ed4b37aafde838846d5024a9..3d4f777d618a909e1cda94e6078cbd2579de966d 100644 (file)
@@ -133,7 +133,10 @@ jack_rack_add_plugin (jack_rack_t * jack_rack, plugin_t * plugin)
         }
       saved_plugin = NULL;
     }
-       
+
+   if ( !saved_plugin )
+       return;
+
   /* initialize plugin parameters */
   plugin->enabled = settings_get_enabled (saved_plugin->settings);
   plugin->wet_dry_enabled = settings_get_wet_dry_enabled (saved_plugin->settings);
index 0baa5835e247dfa75a1069450ec73740541e893a..88512ccaec6b874b8c57a37140358407e8760492 100644 (file)
@@ -69,6 +69,7 @@ plugin_desc_init (plugin_desc_t * pd)
   pd->control_port_indicies = NULL;
   pd->aux_channels = 0;
   pd->aux_are_input = TRUE;
+  pd->has_input = TRUE;
 }
 
 static void
@@ -220,6 +221,11 @@ plugin_desc_set_port_counts (plugin_desc_t * pd)
   
   if (icount == ocount)
     pd->channels = icount;
+  else if( icount == 0 )
+    {
+      pd->channels = ocount;
+      pd->has_input = FALSE;
+    }
   else
     { /* deal with auxilliary ports */
       unsigned long ** port_indicies;
index 31b7fe52313b6667c024634815898d2167af766f..ff511f0a8f3c4aa53b5798a8a8712f956bbb7f87 100644 (file)
@@ -58,6 +58,8 @@ struct _plugin_desc
 
   unsigned long            control_port_count;
   unsigned long *          control_port_indicies;
+
+  gboolean                 has_input;
 };
 
 plugin_desc_t * plugin_desc_new ();
index b3128cdf900f9af87acdfaf6f4e4b205ea05065e..92ea74a9eac82e3d0e2bbf28c1d509ac2404ae1a 100644 (file)
@@ -60,7 +60,7 @@ plugin_is_valid (const LADSPA_Descriptor * descriptor)
         ocount++;
     }
   
-  if (icount == 0 || ocount == 0)
+  if (ocount == 0)
     return FALSE;
   
   return TRUE;
@@ -80,7 +80,7 @@ plugin_mgr_get_object_file_plugins (plugin_mgr_t * plugin_mgr, const char * file
   int err;
   
   /* open the object file */
-  dl_handle = dlopen (filename, RTLD_LAZY);
+  dl_handle = dlopen (filename, RTLD_NOW);
   if (!dl_handle)
     {
       mlt_log_info( NULL, "%s: error opening shared object file '%s': %s\n",
index 88c00e8f55915a64150118848f0e5b117e4c0c88..6d29571a1c7d2ef166e2f2f3d9382b92b0a848d5 100644 (file)
@@ -206,7 +206,8 @@ connect_chain (process_info_t * procinfo, jack_nframes_t frames)
     }
 
   /* input buffers for first plugin */
-  plugin_connect_input_ports (first_enabled, procinfo->jack_input_buffers);
+  if( plugin->desc->has_input )
+    plugin_connect_input_ports (first_enabled, procinfo->jack_input_buffers);
 }
 
 void
@@ -313,13 +314,15 @@ int process_ladspa (process_info_t * procinfo, jack_nframes_t frames,
   
   for (channel = 0; channel < procinfo->channels; channel++)
     {
-      procinfo->jack_input_buffers[channel] = inputs[channel];
-      if (!procinfo->jack_input_buffers[channel])
+      if(get_first_enabled_plugin (procinfo)->desc->has_input)
         {
-          mlt_log_verbose( NULL, "%s: no jack buffer for input port %ld\n", __FUNCTION__, channel);
-          return 1;
+          procinfo->jack_input_buffers[channel] = inputs[channel];
+          if (!procinfo->jack_input_buffers[channel])
+            {
+              mlt_log_verbose( NULL, "%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])
         {
diff --git a/src/modules/jackrack/producer_ladspa.c b/src/modules/jackrack/producer_ladspa.c
new file mode 100644 (file)
index 0000000..29fc794
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * producer_ladspa.c -- LADSPA plugin producer
+ * Copyright (C) 2013 Ushodaya Enterprises Limited
+ * Author: Brian Matherly <pez4brian@yahoo.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 <framework/mlt_producer.h>
+#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string.h>
+
+#include "jack_rack.h"
+
+#define BUFFER_LEN 10000
+
+/** One-time initialization of jack rack.
+*/
+
+static jack_rack_t* initialise_jack_rack( mlt_properties properties, int channels )
+{
+       jack_rack_t *jackrack = NULL;
+       unsigned long plugin_id = mlt_properties_get_int64( properties, "_pluginid" );
+
+       // Start JackRack
+       if ( plugin_id )
+       {
+               // Create JackRack without Jack client name so that it only uses LADSPA
+               jackrack = jack_rack_new( NULL, channels );
+               mlt_properties_set_data( properties, "_jackrack", jackrack, 0,
+                       (mlt_destructor) jack_rack_destroy, NULL );
+
+               // Load one LADSPA plugin by its UniqueID
+               plugin_desc_t *desc = plugin_mgr_get_any_desc( jackrack->plugin_mgr, plugin_id );
+               plugin_t *plugin;
+
+               if ( desc && ( plugin = jack_rack_instantiate_plugin( jackrack, desc ) ) )
+               {
+                       LADSPA_Data value;
+                       int index, c;
+
+                       plugin->enabled = TRUE;
+                       plugin->wet_dry_enabled = FALSE;
+                       for ( index = 0; index < desc->control_port_count; index++ )
+                       {
+                               // Apply the control port values
+                               char key[20];
+                               value = plugin_desc_get_default_control_value( desc, index, sample_rate );
+                               snprintf( key, sizeof(key), "%d", index );
+                               if ( mlt_properties_get( properties, key ) )
+                                       value = mlt_properties_get_double( properties, key );
+                               for ( c = 0; c < plugin->copies; c++ )
+                                       plugin->holders[c].control_memory[index] = value;
+                       }
+                       process_add_plugin( jackrack->procinfo, plugin );
+               }
+               else
+               {
+                       mlt_log_error( properties, "failed to load plugin %lu\n", plugin_id );
+               }
+       }
+
+       return jackrack;
+}
+
+static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       // Get the producer service
+       mlt_producer producer = mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "_producer_ladspa", NULL );
+       mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer );
+       int size = 0;
+       LADSPA_Data** output_buffers = NULL;
+       int i = 0;
+
+       // Initialize LADSPA if needed
+       jack_rack_t *jackrack = mlt_properties_get_data( producer_properties, "_jackrack", NULL );
+       if ( !jackrack )
+       {
+               sample_rate = *frequency; // global inside jack_rack
+               jackrack = initialise_jack_rack( producer_properties, *channels );
+       }
+
+       if( jackrack )
+       {
+               // Correct the returns if necessary
+               *samples = *samples <= 0 ? 1920 : *samples;
+               *channels = *channels <= 0 ? 2 : *channels;
+               *frequency = *frequency <= 0 ? 48000 : *frequency;
+               *format = mlt_audio_float;
+
+               // Calculate the size of the buffer
+               size = *samples * *channels * sizeof( float );
+
+               // Allocate the buffer
+               *buffer = mlt_pool_alloc( size );
+
+               // Initialize the LADSPA output buffer.
+               output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data* ) * *channels );
+               for ( i = 0; i < *channels; i++ )
+               {
+                       output_buffers[i] = (LADSPA_Data*) *buffer + i * *samples;
+               }
+
+               // Do LADSPA processing
+               process_ladspa( jackrack->procinfo, *samples, NULL, output_buffers );
+               mlt_pool_release( output_buffers );
+
+               // Set the buffer for destruction
+               mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
+       }
+
+       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 ) );
+
+       // Check that we created a frame and initialize it
+       if ( *frame != NULL )
+       {
+               // Obtain properties of frame
+               mlt_properties frame_properties = MLT_FRAME_PROPERTIES( *frame );
+
+               // Update timecode on the frame we're creating
+               mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
+
+               // Save the producer to be used in get_audio
+               mlt_properties_set_data( frame_properties, "_producer_ladspa", producer, 0, NULL, NULL );
+
+               // Push the get_audio method
+               mlt_frame_push_audio( *frame, producer_get_audio );
+       }
+
+       // Calculate the next time code
+       mlt_producer_prepare_next( producer );
+
+       return 0;
+}
+
+/** Destructor for the producer.
+*/
+
+static void producer_close( mlt_producer producer )
+{
+       producer->close = NULL;
+       mlt_producer_close( producer );
+       free( producer );
+}
+
+/** Constructor for the producer.
+*/
+
+mlt_producer producer_ladspa_init( mlt_profile profile, mlt_service_type type, const char* id, char* arg )
+{
+       // Create a new producer object
+       mlt_producer producer = mlt_producer_new( profile );
+
+       if ( producer != NULL )
+       {
+               mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
+
+               producer->get_frame = producer_get_frame;
+               producer->close = ( mlt_destructor )producer_close;
+
+               // Save the plugin ID.
+               if ( !strncmp( id, "ladspa.", 7 ) )
+               {
+                       mlt_properties_set( properties, "_pluginid", id + 7 );
+               }
+
+               // Make sure the plugin ID is valid.
+               unsigned long plugin_id = mlt_properties_get_int64( properties, "_pluginid" );
+               if( plugin_id < 1000 || plugin_id > 0x00FFFFFF )
+               {
+                       producer_close( producer );
+                       producer = NULL;
+               }
+       }
+       return producer;
+}
diff --git a/src/modules/jackrack/producer_ladspa.yml b/src/modules/jackrack/producer_ladspa.yml
new file mode 100644 (file)
index 0000000..7033dc9
--- /dev/null
@@ -0,0 +1,15 @@
+schema_version: 0.1
+type: producer
+identifier: ladspa
+title: LADSPA
+version: 1
+copyright: Copyright (C) 2013 Ushodaya Enterprises Limited
+license: GPLv2
+language: en
+creator: Brian Matherly
+tags:
+  - Audio
+description: Generate audio using LADSPA plugins.
+notes: >
+  Automatically adapts to the number of channels and sampling rate of the consumer.
+
index eecaa5849cedd36f89e037b69c3ffc2523ceb719..eabc4e76b756178321e11613d98396ecc8e1c1ca 100644 (file)
@@ -32,9 +32,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/kdenlive"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/kdenlive"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/kdenlive"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/kdenlive"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 375205794da54301be3b78de65b8e366ddaf4b9c..9c0b489893602f09232af071bddad40c2710436d 100755 (executable)
@@ -37,7 +37,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
        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 pos = mlt_properties_get_position( properties, "frame" ) + mlt_producer_get_in( mlt_frame_get_original_producer( frame ) );
        mlt_position currentpos = mlt_filter_get_position( filter, frame );
 
        int do_freeze = 0;
@@ -55,19 +55,18 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                if ( !freeze_frame || mlt_properties_get_position( properties, "_frame" ) != pos )
                {
                        // freeze_frame has not been fetched yet or is not useful, so fetch it and cache it.
-                       mlt_producer producer = mlt_frame_get_original_producer(frame);
+                       // get parent producer
+                       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
                        mlt_producer_seek( producer, pos );
 
                        // Get the frame
                        mlt_service_get_frame( mlt_producer_service(producer), &freeze_frame, 0 );
 
                        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( frame ) );
                        mlt_properties_set_int( freeze_properties, "progressive", mlt_properties_get_int( props, "progressive" ) );
                        mlt_properties_set_int( freeze_properties, "consumer_deinterlace", mlt_properties_get_int( props, "consumer_deinterlace" ) || mlt_properties_get_int( properties, "deinterlace" ) );
-                       mlt_properties_set_double( freeze_properties, "output_ratio", mlt_properties_get_double( props, "output_ratio" ) );
                        mlt_properties_set_data( properties, "freeze_frame", freeze_frame, 0, ( mlt_destructor )mlt_frame_close, NULL );
                        mlt_properties_set_position( properties, "_frame", pos );
                }
index d41148ecaa50eff5fc413ff152ee83c08a0c9981..3e4b3b3d6a817381d96d45843abd20a405216ac0 100644 (file)
@@ -152,7 +152,6 @@ static int framebuffer_get_image( mlt_frame frame, uint8_t **image, mlt_image_fo
         uint8_t *first_alpha = mlt_properties_get_data( first_frame_properties, "alpha", NULL );
        if ( !first_image )
        {
-               mlt_properties_set_double( first_frame_properties, "consumer_aspect_ratio", mlt_properties_get_double( frame_properties, "consumer_aspect_ratio" ) );
                mlt_properties_set( first_frame_properties, "rescale.interp", mlt_properties_get( frame_properties, "rescale.interp" ) );
 
                int error = mlt_frame_get_image( first_frame, &first_image, format, width, height, writable );
@@ -200,10 +199,11 @@ static int framebuffer_get_image( mlt_frame frame, uint8_t **image, mlt_image_fo
 
 static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
 {
-       // Construct a new frame
-       *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
-       if( frame != NULL )
+       if ( frame )
        {
+               // Construct a new frame
+               *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
+
                // Stack the producer and producer's get image
                mlt_frame_push_service( *frame, (void*) index );
                mlt_frame_push_service( *frame, producer );
@@ -238,8 +238,8 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                // Give the returned frame temporal identity
                mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
 
-               mlt_properties_set_int( frame_properties, "real_width", mlt_properties_get_int( properties, "width" ) );
-               mlt_properties_set_int( frame_properties, "real_height", mlt_properties_get_int( properties, "height" ) );
+               mlt_properties_set_int( frame_properties, "meta.media.width", mlt_properties_get_int( properties, "width" ) );
+               mlt_properties_set_int( frame_properties, "meta.media.height", mlt_properties_get_int( properties, "height" ) );
                mlt_properties_pass_list( frame_properties, properties, "width, height" );
        }
 
@@ -252,7 +252,14 @@ mlt_producer producer_framebuffer_init( mlt_profile profile, mlt_service_type ty
        if ( !arg ) return NULL;
        mlt_producer producer = NULL;
        producer = calloc( 1, sizeof( struct mlt_producer_s ) );
-       mlt_producer_init( producer, NULL );
+       if ( !producer )
+               return NULL;
+
+       if ( mlt_producer_init( producer, NULL ) )
+       {
+               free( producer );
+               return NULL;
+       }
 
        // Wrap loader
        mlt_producer real_producer;
@@ -314,6 +321,28 @@ mlt_producer producer_framebuffer_init( mlt_profile profile, mlt_service_type ty
                {
                        double real_length = ( (double)  mlt_producer_get_length( real_producer ) ) / speed;
                        mlt_properties_set_position( properties, "length", real_length );
+                       mlt_properties real_properties = MLT_PRODUCER_PROPERTIES( real_producer );
+                       const char* service = mlt_properties_get( real_properties, "mlt_service" );
+                       if ( service && !strcmp( service, "avformat" ) )
+                       {
+                               int n = mlt_properties_count( real_properties );
+                               int i;
+                               for ( i = 0; i < n; i++ )
+                               {
+                                       if ( strstr( mlt_properties_get_name( real_properties, i ), "stream.frame_rate" ) )
+                                       {
+                                               double source_fps = mlt_properties_get_double( real_properties, mlt_properties_get_name( real_properties, i ) );
+                                               if ( source_fps > mlt_profile_fps( profile ) )
+                                               {
+                                                       mlt_properties_set_double( real_properties, "force_fps", source_fps * speed );
+                                                       mlt_properties_set_position( real_properties, "length", real_length );
+                                                       mlt_properties_set_position( real_properties, "out", real_length - 1 );
+                                                       speed = 1.0;
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
                }
                mlt_properties_set_position( properties, "out", mlt_producer_get_length( producer ) - 1 );
 
index 984838613452a49372169d91b052309b2f0d8428..71b3b1a9be941de391c65a1601158277568c0e96 100644 (file)
@@ -42,7 +42,7 @@ clean:
                rm -f $(OBJS) $(TARGET) $(CPPOBJS)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
 
 ifneq ($(wildcard .depend),)
 include .depend
index d07b83e8f0cd29190b77ec065ec5c27ff3962db9..04c5176c8458dfd881847af9ba412e7a3adc3901 100644 (file)
@@ -88,6 +88,9 @@ AVIFile::AVIFile() : RIFFFile(),
        }
        idx1 = new AVISimpleIndex;
        memset( idx1, 0, sizeof( AVISimpleIndex ) );
+       memset( dmlh, 0, sizeof( dmlh ) );
+       memset( &mainHdr, 0, sizeof( mainHdr ) );
+       memset( &streamHdr, 0, sizeof( streamHdr ) );
 }
 
 
@@ -133,6 +136,9 @@ AVIFile::AVIFile( const AVIFile& avi ) : RIFFFile( avi )
 
        isUpdateIdx1 = avi.isUpdateIdx1;
 
+       odml_list = 0;
+       dmlh_chunk = 0;
+       memset( &streamHdr, 0, sizeof( streamHdr ) );
 }
 
 
@@ -995,7 +1001,9 @@ bool AVIFile::isOpenDML( void )
 }
 
 AVI1File::AVI1File() : AVIFile()
-{}
+{
+       memset( &dvinfo, 0, sizeof( dvinfo ) );
+}
 
 
 AVI1File::~AVI1File()
index 244ba24186b8b56dbcda1f33374cde97e3948ebd..697c7e6c15a780b41f7e0882b45eb5cdd57bccf7 100644 (file)
@@ -117,6 +117,10 @@ FileHandler::FileHandler() : done( false ), autoSplit( false ), maxFrameCount( 9
                framesWritten( 0 ), filename( "" )
 {
        /* empty body */
+       timeStamp = 0;
+       everyNthFrame = 0;
+       framesToSkip = 0;
+       maxFileSize = 0;
 }
 
 
@@ -338,6 +342,7 @@ bool FileHandler::WriteFrame( const Frame& frame )
 RawHandler::RawHandler() : fd( -1 )
 {
        extension = ".dv";
+       numBlocks = 0;
 }
 
 
@@ -406,7 +411,8 @@ bool RawHandler::Open( const char *s )
                return false;
        if ( read( fd, data, 4 ) < 0 )
                return false;
-       lseek( fd, 0, SEEK_SET );
+       if ( lseek( fd, 0, SEEK_SET ) < 0 )
+               return false;
        numBlocks = ( ( data[ 3 ] & 0x80 ) == 0 ) ? 250 : 300;
        filename = s;
        return true;
@@ -438,6 +444,7 @@ AVIHandler::AVIHandler( int format ) : avi( NULL ), aviFormat( format ), isOpenD
        extension = ".avi";
        for ( int c = 0; c < 4; c++ )
                audioChannels[ c ] = NULL;
+       memset( &dvinfo, 0, sizeof( dvinfo ) );
 }
 
 
@@ -505,14 +512,14 @@ bool AVIHandler::Create( const string& filename )
 
        case AVI_DV1_FORMAT:
                fail_null( avi = new AVI1File );
-               if ( avi->Create( filename.c_str() ) == false )
+               if ( !avi || 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 )
+               if ( !avi || avi->Create( filename.c_str() ) == false )
                        return false;
                //if ( GetOpenDML() )
                        //avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
index 7f94a9e78f149e350c2d0bda90128a6a8ca02930..6e0ef767d50a038bd702c1b974fb132cf060822c 100644 (file)
@@ -47,7 +47,7 @@ mlt_producer producer_kino_init( mlt_profile profile, mlt_service_type type, con
 
        if ( kino_wrapper_open( wrapper, filename ) )
        {
-               producer_kino this = calloc( sizeof( struct producer_kino_s ), 1 );
+               producer_kino this = calloc( 1, sizeof( struct producer_kino_s ) );
 
                if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
                {
index efd91d61c0967710d1a4f952786b0429719a5782..fff59edb6c26299b92a41ff6dd754afa84a29002 100644 (file)
@@ -65,7 +65,14 @@ FOURCC make_fourcc( const char *s )
 
 
 RIFFDirEntry::RIFFDirEntry()
-{}
+{
+       type = 0;
+       name = 0;
+       length = 0;
+       offset = 0;
+       parent = 0;
+       written = 0;
+}
 
 
 RIFFDirEntry::RIFFDirEntry ( FOURCC t, FOURCC n, int l, int o, int p ) : type( t ), name( n ), length( l ), offset( o ), parent( p ), written( 0 )
@@ -530,11 +537,12 @@ void RIFFFile::ParseRIFF( void )
 {
        FOURCC type;
        DWORD length;
-       off_t filesize;
+       off_t filesize = 0;
        off_t pos;
        int container = AddDirectoryEntry( make_fourcc( "FILE" ), make_fourcc( "FILE" ), 0, RIFF_NO_PARENT );
 
        pos = lseek( fd, 0, SEEK_SET );
+       fail_if( pos == -1 );
 
        /* calculate file size from RIFF header instead from physical file. */
 
index 6dc3df4fe7b5c8c2b763d8d55dc364a716274f43..143cb9d6ee217dd0aeb086dc7136d2f3f052e5d7 100755 (executable)
@@ -32,9 +32,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/linsys"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/linsys"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/linsys"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/linsys"
 
 ifneq ($(wildcard .depend),)
 include .depend
index ef4ac37ff07c454551cc723f1fd5c6b4964bd0b1..8e7cec5e8f243265cc4e3a69a778ff91e12991ce 100644 (file)
@@ -211,7 +211,7 @@ int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, uint8_t * target_rgb);
 mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg) {
 
        // Create the consumer object
-       consumer_SDIstream this = calloc(sizeof(struct consumer_SDIstream_s), 1);
+       consumer_SDIstream this = calloc( 1, sizeof(struct consumer_SDIstream_s) );
 
        // If malloc and consumer init ok
        if (this != NULL && mlt_consumer_init(&this->parent, this, profile) == 0) {
@@ -359,7 +359,9 @@ static void *consumer_thread(void *arg) {
 
        // Set additional device file defaults
        struct stat st;
-       int fd = stat(this->device_file_video, &st);
+       int fd = -1;
+       if (this->device_file_video)
+               fd = stat(this->device_file_video, &st);
        if (fd == -1) {
                if (this->device_file_video)
                        free(this->device_file_video);
@@ -376,7 +378,8 @@ static void *consumer_thread(void *arg) {
                } else {
                        close(fd);
                }
-       } else if (strstr(this->device_file_video, "sdivideotx")) {
+       } else if (this->device_file_video &&
+                       strstr(this->device_file_video, "sdivideotx")) {
                if (this->device_file_audio)
                        free(this->device_file_audio);
                this->device_file_audio = strdup("/dev/sdiaudiotx0");
@@ -392,7 +395,7 @@ static void *consumer_thread(void *arg) {
                } else {
                        this->blanking = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES( consumer ), "blanking");
                }
-       } else if (strstr(this->device_file_video, "sdivideotx")) {
+       } else if (this->device_file_video && strstr(this->device_file_video, "sdivideotx")) {
                this->blanking = 0;
        } else {
                // set default value without HD board, also with blanking
@@ -419,7 +422,8 @@ static void *consumer_thread(void *arg) {
        this->audio_format.sample_rate = 48000;
        this->pix_fmt = mlt_image_yuv422;
 
-       if (!sdi_init(this->device_file_video, this->device_file_audio, this->blanking, mlt_service_profile((mlt_service) consumer), &this->audio_format)) {
+       if (this->device_file_video && this->device_file_audio &&
+               !sdi_init(this->device_file_video, this->device_file_audio, this->blanking, mlt_service_profile((mlt_service) consumer), &this->audio_format)) {
                mlt_log_fatal( MLT_CONSUMER_SERVICE(consumer), "failed to initialize\n" );
                mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-fatal-error", NULL );
        }
index 87bd56416ad8725e2e1cfe4639a6a59a0fca030c..928be548719e6f192124dd01aebbd6c30c082c23 100644 (file)
@@ -349,9 +349,9 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
        }
 
        if (info.blanking) {
-               printf("SDI frame size: %li\n", sdi_frame_size);
+               printf("SDI frame size: %"PRIu64"\n", sdi_frame_size);
        } else {
-               printf("Frame size for active video: %li\n", sdi_frame_size);
+               printf("Frame size for active video: %"PRIu64"\n", sdi_frame_size);
        }
 
        /**
@@ -420,8 +420,8 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
                                // Buffer size
                                // audio buffer per frame (Bytes) = sample rate / frame rate * ( sample size / 1Byte ) x channels
                                value = itoa(
-                                               audio_format->sample_rate / (myProfile->frame_rate_num / myProfile->frame_rate_den) * sample_size / 8
-                                                               * audio_format->channels);
+                                               (uint64_t) audio_format->sample_rate / ( (uint64_t) myProfile->frame_rate_num / (uint64_t) myProfile->frame_rate_den) * (uint64_t) sample_size / 8
+                                                               * (uint64_t) audio_format->channels);
                                setSDIAudioProperties(SETTING_BUFFER_SIZE_AUDIO, value, device_audio);
                                free(value);
 
index 34b1c5ae3199e7f1c2197ecae09711e6dd1169ec..ed51482226326fa3930abc45e795752809dc180b 100644 (file)
@@ -17,7 +17,7 @@ clean:
        rm -f luma 
 
 install:       all
-       install -d $(DESTDIR)$(datadir)/mlt/lumas/PAL
-       install -d $(DESTDIR)$(datadir)/mlt/lumas/NTSC
-       install -m 644 PAL/* $(DESTDIR)$(datadir)/mlt/lumas/PAL
-       install -m 644 NTSC/* $(DESTDIR)$(datadir)/mlt/lumas/NTSC
+       install -d $(DESTDIR)$(mltdatadir)/lumas/PAL
+       install -d $(DESTDIR)$(mltdatadir)/lumas/NTSC
+       install -m 644 PAL/* $(DESTDIR)$(mltdatadir)/lumas/PAL
+       install -m 644 NTSC/* $(DESTDIR)$(mltdatadir)/lumas/NTSC
index 088961229c35ab91a6fed3ad574d0c80f0b24a5c..ddd39c78e3725e930f1bc36eb82908465205d564 100644 (file)
@@ -367,11 +367,31 @@ int main( int argc, char **argv )
                else if ( !strcmp( argv[ arg ], "-type" ) )
                        this.type = atoi( argv[ ++ arg ] );
                else if ( !strcmp( argv[ arg ], "-w" ) )
-                       this.w = atoi( argv[ ++ arg ] );
+               {
+                       int tmp = atoi( argv[ ++ arg ] );
+                       // TODO: is there an upper bound?
+                       if ( tmp )
+                               this.w = tmp;
+                       else
+                               return 1;
+               }
                else if ( !strcmp( argv[ arg ], "-h" ) )
-                       this.h = atoi( argv[ ++ arg ] );
+               {
+                       int tmp = atoi( argv[ ++ arg ] );
+                       // TODO: is there an upper bound?
+                       if ( tmp )
+                               this.h = tmp;
+                       else return 1;
+               }
                else if ( !strcmp( argv[ arg ], "-bands" ) )
-                       this.bands = atoi( argv[ ++ arg ] );
+               {
+                       int tmp = atoi( argv[ ++ arg ] );
+                       // TODO: is there an upper bound?
+                       if ( tmp >= 0 )
+                               this.bands = tmp;
+                       else
+                               return 1;
+               }
                else if ( !strcmp( argv[ arg ], "-rband" ) )
                        this.rband = atoi( argv[ ++ arg ] );
                else if ( !strcmp( argv[ arg ], "-hmirror" ) )
index 822868e25d49e9d896e570c5b90cde2a03bf2320..0d142750e4e4061af2c1d0d1495fcd9373feced3 100644 (file)
@@ -31,9 +31,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/motion_est"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/motion_est"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/motion_est"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/motion_est"
 
 test: $(TARGET)
        ~/mlt-devel/mlt/src/melt/melt -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
index f65e16c1bc069dd5ae86e0fa70a852e86b462abf..e6caff199b499973fd0121f570c20a50cfea2d12 100644 (file)
@@ -180,8 +180,36 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
        {
                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, "_serialize" ) == 1 )
+       {
+               // Add the vector change to the list
+               mlt_geometry key_frames = mlt_properties_get_data( filter_properties, "motion_vector_list", NULL );
+               if ( !key_frames )
+               {
+                       key_frames = mlt_geometry_init();
+                       mlt_properties_set_data( filter_properties, "motion_vector_list", key_frames, 0,
+                                                (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise );
+                       if ( key_frames )
+                               mlt_geometry_set_length( key_frames, mlt_filter_get_length2( filter, frame ) );
+               }
+               if ( key_frames )
+               {
+                       struct mlt_geometry_item_s item;
+                       item.frame = (int) mlt_frame_get_position( frame );
+                       item.key = 1;
+                       item.x = boundry.x;
+                       item.y = boundry.y;
+                       item.w = boundry.w;
+                       item.h = boundry.h;
+                       item.mix = 0;
+                       item.f[0] = item.f[1] = item.f[2] = item.f[3] = 1;
+                       item.f[4] = 0;
+                       mlt_geometry_insert( key_frames, &item );
+               }
+       }
+       
        if( mlt_properties_get_int( filter_properties, "obscure" ) == 1 )
        {
                mlt_filter obscure = mlt_properties_get_data( filter_properties, "_obscure", NULL );
@@ -274,15 +302,14 @@ 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 );
-
-
+       mlt_properties properties = MLT_FILTER_PROPERTIES( this );
 
        /* apply the motion estimation filter */
-       mlt_filter motion_est = mlt_properties_get_data( MLT_FILTER_PROPERTIES(this), "_motion_est", NULL ); 
+       mlt_filter motion_est = mlt_properties_get_data( properties, "_motion_est", NULL ); 
+       /* Pass motion_est properties */
+       mlt_properties_pass( MLT_FILTER_PROPERTIES( motion_est ), properties, "motion_est." );
        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 );
@@ -291,12 +318,12 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
        /* 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 );
+               mlt_filter vismv = mlt_properties_get_data( properties, "_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_properties_set_data( properties, "_vismv", vismv, 0, (mlt_destructor)mlt_filter_close, NULL );
                }
 
                mlt_filter_process( vismv, frame );
@@ -304,12 +331,12 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame 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 );
+               mlt_filter obscure = mlt_properties_get_data( properties, "_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_properties_set_data( properties, "_obscure", obscure, 0, (mlt_destructor)mlt_filter_close, NULL );
                }
 
                mlt_filter_process( obscure, frame );
index d2dff28402960da64f61e99e35495ee8accf21ed..282ace27cacbdd3a3df82a4def11235220f70002 100644 (file)
@@ -891,6 +891,23 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
        /* 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 )
+       {
+               char *property = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "bounding" );
+               if ( property )
+               {
+                       mlt_geometry geometry = mlt_geometry_init( );
+                       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE(filter) );
+                       if ( geometry )
+                       {
+                               mlt_geometry_parse( geometry, property, 0, profile->width, profile->height );
+                               bounds = calloc( 1, sizeof(*bounds) );
+                               mlt_properties_set_data( MLT_FILTER_PROPERTIES(filter), "bounds", bounds, sizeof(*bounds), free, NULL );
+                               mlt_geometry_fetch( geometry, bounds, 0 );
+                       }
+               }
+       }
+
        if( bounds != NULL ) {
                // translate pixel units (from bounds) to macroblock units
                // make sure whole macroblock stays within bounds
@@ -935,10 +952,30 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                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 properties = MLT_FILTER_PROPERTIES( filter );
+                       mlt_log_verbose( MLT_FILTER_SERVICE(filter), "shot change: %d\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;
+
+                       // Add the shot change to the list
+                       mlt_geometry key_frames = mlt_properties_get_data( properties, "shot_change_list", NULL );
+                       if ( !key_frames )
+                       {
+                               key_frames = mlt_geometry_init();
+                               mlt_properties_set_data( properties, "shot_change_list", key_frames, 0,
+                                       (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise );
+                               if ( key_frames )
+                                       mlt_geometry_set_length( key_frames, mlt_filter_get_length2( filter, frame ) );
+                       }
+                       if ( key_frames )
+                       {
+                               struct mlt_geometry_item_s item;
+                               item.frame = (int) c->current_frame_position;
+                               item.x = c->comparison_average;
+                               item.f[0] = 1;
+                               item.f[1] = item.f[2] = item.f[3] = item.f[4] = 0;
+                               mlt_geometry_insert( key_frames, &item );
+                       }
                }
                else {
                        c->former_vectors_valid = 1;
index 7e3a4cfffe3e1e8ec7922d5e5292d86e0ccad017..ba6f3c81a40b603525673e00b14db4255831bdb9 100644 (file)
@@ -275,6 +275,8 @@ static int slowmotion_get_image( mlt_frame this, uint8_t **image, mlt_image_form
 
 static int slowmotion_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
 {
+       if ( !frame )
+               return 1;
        // Construct a new frame
        *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) );
 
index 38624578b15a9f3a96ee4b890e4fe9c8ddca4b16..5a4758a95ebb3368eb954c38aec44664553e608c 100644 (file)
@@ -7,6 +7,7 @@ include ../../../config.mak
 TARGET = ../libmltnormalize$(LIBSUF)
 
 OBJS = factory.o \
+          filter_audiolevel.o \
           filter_volume.o 
 
 SRCS := $(OBJS:.o=.c)
@@ -26,9 +27,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/normalize"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/normalize"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/normalize"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/normalize"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 1dda79b02536ffd7bf7c2acca9d276e56095174f..ac02263d19587d96ec961ae19b183b0f076a293c 100644 (file)
@@ -22,6 +22,7 @@
 #include <limits.h>
 #include <framework/mlt.h>
 
+extern mlt_filter filter_audiolevel_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_volume_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 
 static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
@@ -33,6 +34,8 @@ static mlt_properties metadata( mlt_service_type type, const char *id, void *dat
 
 MLT_REPOSITORY
 {
+       MLT_REGISTER( filter_type, "audiolevel", filter_audiolevel_init );
        MLT_REGISTER( filter_type, "volume", filter_volume_init );
+       MLT_REGISTER_METADATA( filter_type, "audiolevel", metadata, "filter_audiolevel.yml" );
        MLT_REGISTER_METADATA( filter_type, "volume", metadata, "filter_volume.yml" );
 }
diff --git a/src/modules/normalize/filter_audiolevel.c b/src/modules/normalize/filter_audiolevel.c
new file mode 100644 (file)
index 0000000..fa8be07
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * filter_audiolevel.c -- get the audio level of each channel
+ * Copyright (C) 2002 Steve Harris
+ * Copyright (C) 2010 Marco Gittler <g.marco@freenet.de>
+ * Copyright (C) 2012 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 <framework/mlt_log.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+#define AMPTODBFS(n) (log10(n) * 20.0)
+
+//----------------------------------------------------------------------------
+// IEC standard dB scaling -- as borrowed from meterbridge (c) Steve Harris
+
+static inline double IEC_Scale(double dB)
+{
+       double fScale = 1.0f;
+
+       if (dB < -70.0f)
+               fScale = 0.0f;
+       else if (dB < -60.0f)                 //  0.0  ..   2.5
+               fScale = (dB + 70.0f) * 0.0025f;
+       else if (dB < -50.0f)                 //  2.5  ..   7.5
+               fScale = (dB + 60.0f) * 0.005f + 0.025f;
+       else if (dB < -40.0)                  //  7.5  ..  15.0
+               fScale = (dB + 50.0f) * 0.0075f + 0.075f;
+       else if (dB < -30.0f)                 // 15.0  ..  30.0
+               fScale = (dB + 40.0f) * 0.015f + 0.15f;
+       else if (dB < -20.0f)                 // 30.0  ..  50.0
+               fScale = (dB + 30.0f) * 0.02f + 0.3f;
+       else if (dB < -0.001f || dB > 0.001f) // 50.0  .. 100.0
+               fScale = (dB + 20.0f) * 0.025f + 0.5f;
+
+       return fScale;
+}
+
+static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       mlt_filter filter = mlt_frame_pop_audio( frame );
+       int iec_scale = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "iec_scale" );
+       *format = mlt_audio_s16;
+       int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+       if ( error || !buffer ) return error;
+
+       int num_channels = *channels;
+       int num_samples = *samples > 200 ? 200 : *samples;
+       int num_oversample = 0;
+       int c, s;
+       char key[ 50 ];
+       int16_t *pcm = (int16_t*) *buffer;
+
+       for ( c = 0; c < *channels; c++ )
+       {
+               long val = 0;
+               double level = 0.0;
+
+               for ( s = 0; s < num_samples; s++ )
+               {
+                       int sample = abs( pcm[c + s * num_channels] / 128 );
+                       val += sample;
+                       if ( sample == 128 )
+                               num_oversample++;
+                       else
+                               num_oversample = 0;
+                       // 10 samples @max => show max signal
+                       if ( num_oversample > 10 )
+                       {
+                               level = 1.0;
+                               break;
+                       }
+                       // if 3 samples over max => 1 peak over 0 db (0 dB = 40.0)
+                       if ( num_oversample > 3 )
+                               level = 41.0/42.0;
+               }
+               // max amplitude = 40/42, 3to10  oversamples=41, more then 10 oversamples=42
+               if ( level == 0.0 )
+                       level = val / num_samples * 40.0/42.0 / 127.0;
+               if ( iec_scale )
+                       level = IEC_Scale( AMPTODBFS( level ) );
+               sprintf( key, "meta.media.audio_level.%d", c );
+               mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), key, level );
+               sprintf( key, "_audio_level.%d", c );
+               mlt_properties_set_double( MLT_FILTER_PROPERTIES( filter ), key, level );
+               mlt_log_debug( MLT_FILTER_SERVICE( filter ), "channel %d level %f\n", c, level );
+       }
+
+       return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
+{
+       mlt_frame_push_audio( frame, filter );
+       mlt_frame_push_audio( frame, filter_get_audio );
+       return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_audiolevel_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = mlt_filter_new();
+       if ( filter )
+       {
+               filter->process = filter_process;
+               mlt_properties_set_int( MLT_FILTER_PROPERTIES(filter), "iec_scale", 1 );
+       }
+       return filter;
+}
diff --git a/src/modules/normalize/filter_audiolevel.yml b/src/modules/normalize/filter_audiolevel.yml
new file mode 100644 (file)
index 0000000..2592847
--- /dev/null
@@ -0,0 +1,38 @@
+schema_version: 0.1
+type: filter
+identifier: audiolevel
+title: Audio Levels
+version: 1
+copyright: Dan Dennedy, Marco Gittler, and Steve Harris
+creator: Dan Dennedy
+contributor:
+  - Marco Gittler
+  - Steve Harris
+license: GPLv2
+language: en
+description: Compute the audio amplitude.
+notes: >
+  This filter provides the amplitude level as a percentage value in floating point.
+  This does not do any "slowing" of the data by averaging out peaks and
+  troughs of short duration like a VU meter.
+  Applications can also get this data on the frame as meta.media.audio_level.<N>
+  where <N> is the channel number starting with 0.
+tags:
+  - Audio
+parameters:
+  - identifier: iec_scale
+    title: Use IEC 60268-18 Scale
+    type: integer
+    minimum: 0
+    maximum: 1
+    default: 1
+    widget: checkbox
+
+  - identifier: _audio_level.<N>
+    description: >
+        <N> is the channel number starting with 0.
+        This is updated on every frame with audio.
+    readonly: yes
+    type: float
+    minimum: 0
+    maximum: 1
index ad503b7f9c3cfa1231e89d8887e8370be67b9eca..8b0ccd6059dde0db3ca81ad380eb30af33474441 100644 (file)
@@ -100,7 +100,7 @@ static inline double get_smoothed_data( double *buf, int count )
                        j++;
                }
        }
-       smoothed /= j;
+       if (j) smoothed /= j;
 //     fprintf( stderr, "smoothed over %d values, result %f\n", j, smoothed );
 
        return smoothed;
@@ -445,7 +445,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 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 );
+       mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( this != NULL && mlt_filter_init( this, NULL ) == 0 )
        {
                mlt_properties properties = MLT_FILTER_PROPERTIES( this );
index e7e200be28111af565eb7176709b6353f6f2e9d6..9b5e3b0b7832e7c1fd9ebaa4c7f903eaef375bd9 100644 (file)
@@ -31,10 +31,10 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d $(DESTDIR)$(datadir)/mlt/oldfilm
-       install -m 644 *.svg "$(DESTDIR)$(datadir)/mlt/oldfilm"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/oldfilm"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d $(DESTDIR)$(mltdatadir)/oldfilm
+       install -m 644 *.svg "$(DESTDIR)$(mltdatadir)/oldfilm"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/oldfilm"
 
 
 ifneq ($(wildcard .depend),)
index b20f4391b990031d22db570895b23fea697df909..da331badac19117cbbf0fb0fc65e0d99ac30f63c 100644 (file)
@@ -123,7 +123,6 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                                
                                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" );
@@ -140,8 +139,8 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                                                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_data ( properties , savename , savepic , sizeof(savepic) , mlt_pool_release, NULL );
+                                               mlt_properties_set_data ( properties , savename1 , savealpha , sizeof(savealpha)  ,  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 );
@@ -164,9 +163,6 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 
                int h = *height;
                int w = *width;
-               if (maxcount==0)
-                       return 0;
-
                int im=rand()%maxcount;
                
                while (im-- ){
index f525480924e3b93150815ea69b92d783c9a39e95..23313101daf364eac1ed9a3fe309bebd55575929 100644 (file)
@@ -36,7 +36,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                int h = *height;
                int w = *width;
 
-               int width_line = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "width" );
+               int line_width = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "line_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" ) ;
@@ -44,7 +44,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                char buf[256];
                char typebuf[256];
                
-               if (!width_line)
+               if ( line_width < 1 )
                        return 0;
 
                double position = mlt_filter_get_progress( filter, this );
@@ -55,7 +55,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                while (num--){
                        int type=(rand()%3)+1;
                        int x1=(double)w*rand()/RAND_MAX;
-                       int dx=rand()%width_line;
+                       int dx=rand()%line_width;
                        int x=0,y=0;
                        int ystart=rand()%h;
                        int yend=rand()%h;
@@ -125,8 +125,8 @@ mlt_filter filter_lines_init( mlt_profile profile, mlt_service_type type, const
        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 ), "line_width", 2 );
+               mlt_properties_set_int( 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 ) ;
        }
index 5f13c51caa9dbc81119ae312f3183259b81dce5d..ee7dd1895540fd4345a6c2f9464f8b265423a563 100644 (file)
@@ -2,7 +2,7 @@ schema_version: 0.1
 type: filter # consumer, filter, producer, or transition
 identifier: lines
 title: Scratchlines
-version: 0.2.5
+version: 0.2.6
 copyright: Copyright (C) 2008 Marco Gittler
 license: GPL
 language: en
@@ -20,7 +20,7 @@ bugs: # this can be just for documentation, or the tool may disclose it to help
   - need to do some speed improvement.
 
 parameters:
-  - identifier: width
+  - identifier: line_width
     title: Width of line
     type: integer
     description: Linewidth in picture
diff --git a/src/modules/opengl/Makefile b/src/modules/opengl/Makefile
new file mode 100644 (file)
index 0000000..10276a9
--- /dev/null
@@ -0,0 +1,77 @@
+CFLAGS += -I../..
+
+LDFLAGS += -L../../framework -lmlt -lm
+
+include ../../../config.mak
+
+TARGET = ../libmltopengl$(LIBSUF)
+
+OBJS = factory.o
+
+CPPOBJS = fbo_input.o
+CPPOBJS += filter_glsl_manager.o
+CPPOBJS += filter_movit_blur.o
+CPPOBJS += filter_movit_convert.o
+CPPOBJS += filter_movit_crop.o
+CPPOBJS += filter_deconvolution_sharpen.o
+CPPOBJS += filter_movit_diffusion.o
+CPPOBJS += filter_movit_glow.o
+CPPOBJS += filter_lift_gamma_gain.o
+CPPOBJS += filter_movit_mirror.o
+CPPOBJS += filter_movit_opacity.o
+CPPOBJS += filter_movit_rect.o
+CPPOBJS += filter_movit_resample.o
+CPPOBJS += filter_movit_resize.o
+CPPOBJS += filter_movit_saturation.o
+CPPOBJS += filter_movit_vignette.o
+CPPOBJS += filter_white_balance.o
+CPPOBJS += mlt_movit_input.o
+CPPOBJS += transition_movit_mix.o
+CPPOBJS += transition_movit_overlay.o
+
+CXXFLAGS += -Wno-deprecated $(CFLAGS)
+CXXFLAGS += `pkg-config --cflags movit 2> /dev/null`
+
+SHADERDIR = `pkg-config --variable=shaderdir movit`
+CXXFLAGS += -DSHADERDIR=\"$(SHADERDIR)\"
+
+LDFLAGS += -L../../mlt++ -lmlt++
+
+ifeq ($(targetos), MinGW)
+       CXXFLAGS += `pkg-config --cflags glew`
+       LDFLAGS += -lmovit `pkg-config --libs-only-L glew` -lglew32 -lopengl32
+else
+       LDFLAGS += `pkg-config --libs movit 2> /dev/null`
+ifeq ($(targetos), Darwin)
+       CXXFLAGS += -FOpenGL
+       LDFLAGS += -framework OpenGL
+else
+       OBJS += consumer_xgl.o
+       LDFLAGS += -lpthread -lGL -lX11
+endif
+endif
+
+SRCS := $(OBJS:.o=.c) $(CPPOBJS:.o=.cpp)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS) $(CPPOBJS)
+               $(CXX) $(SHFLAGS) -o $@ $(OBJS) $(CPPOBJS) $(LDFLAGS)
+
+depend:        $(SRCS)
+               $(CXX) -MM $(CXXFLAGS) $^ 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"
+       install -d "$(DESTDIR)$(datadir)/mlt/opengl/movit"
+       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/opengl"
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/src/modules/opengl/configure b/src/modules/opengl/configure
new file mode 100755 (executable)
index 0000000..3065ba1
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ "$help" != "1" ]
+then
+       if ! $(pkg-config movit)
+       then
+               echo "- movit not found: disabling"
+               touch ../disable-opengl
+               exit 0
+       fi
+
+       echo > config.mak
+       case $targetos in
+       Darwin)
+               ;;
+       MinGW)
+               ;;
+       *)
+               ;;
+       esac
+       exit 0
+fi
diff --git a/src/modules/opengl/consumer_xgl.c b/src/modules/opengl/consumer_xgl.c
new file mode 100644 (file)
index 0000000..0cd6bc4
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * consumer_xgl.c
+ * Copyright (C) 2012 Christophe Thommeret
+ * Author: Christophe Thommeret <hftom@free.fr>
+ * Based on Nehe's GLX port by Mihael.Vrbanec@stud.uni-karlsruhe.de
+ * http://nehe.gamedev.net/
+ *
+ * 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
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include <GL/glx.h>
+
+#include <X11/keysym.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+#include <framework/mlt.h>
+
+
+#define STARTWIDTH 1280
+#define STARTHEIGHT 720
+
+
+extern int XInitThreads();
+
+
+
+typedef struct consumer_xgl_s *consumer_xgl;
+
+struct consumer_xgl_s
+{
+       struct mlt_consumer_s parent;
+       mlt_properties properties;
+       mlt_deque queue;
+       pthread_t thread;
+       int joined;
+       int running;
+       int playing;
+       int xgl_started;
+};
+
+
+typedef struct
+{
+       pthread_t thread;
+       int running;
+} thread_video;
+
+
+typedef struct
+{
+       int width;
+       int height;
+       double aspect_ratio;
+       GLuint texture;
+       pthread_mutex_t mutex;
+       int new;
+       mlt_frame mlt_frame_ref;
+} frame_new;
+
+
+typedef struct
+{
+       int width;
+       int height;
+       GLuint fbo;
+       GLuint texture;
+} fbo;
+
+
+typedef struct
+{
+       Display *dpy;
+    int screen;
+    Window win;
+    GLXContext ctx;
+} HiddenContext;
+
+
+typedef struct
+{
+    Display *dpy;
+    int screen;
+    Window win;
+    GLXContext ctx;
+    XSetWindowAttributes attr;
+    int x, y;
+    unsigned int width, height;
+    unsigned int depth;
+} GLWindow;
+
+
+static GLWindow GLWin;
+static HiddenContext hiddenctx;
+
+static frame_new new_frame;
+static fbo fb;
+static thread_video vthread;
+static consumer_xgl xgl;
+static mlt_filter glsl_manager;
+
+
+
+static void* video_thread( void *arg );
+
+static void update()
+{
+       int _width = GLWin.width;
+       int _height = GLWin.height;
+       GLfloat left, right, top, bottom;
+       GLfloat war = (GLfloat)_width/(GLfloat)_height;
+
+       if ( war < new_frame.aspect_ratio ) {
+               left = -1.0;
+               right = 1.0;
+               top = war / new_frame.aspect_ratio;
+               bottom = -war / new_frame.aspect_ratio;
+       }
+       else {
+               top = 1.0;
+               bottom = -1.0;
+               left = -new_frame.aspect_ratio / war;
+               right = new_frame.aspect_ratio / war;
+       }
+
+       glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+       glLoadIdentity();
+
+       glPushMatrix();
+
+       glTranslatef( _width/2, _height/2, 0 );
+       glScalef( _width/2, _height/2, 1.0 );
+
+       glBindTexture( GL_TEXTURE_2D, fb.texture );
+
+       glBegin( GL_QUADS );
+               glTexCoord2f( 0.0f, 0.0f ); glVertex2f( left, top );
+               glTexCoord2f( 0.0f, 1.0f ); glVertex2f( left, bottom );
+               glTexCoord2f( 1.0f, 1.0f ); glVertex2f( right, bottom );
+               glTexCoord2f( 1.0f, 0.0f ); glVertex2f( right, top );
+       glEnd();
+
+       glPopMatrix();
+       
+       glXSwapBuffers( GLWin.dpy, GLWin.win );
+       
+       if ( !vthread.running ) {
+               pthread_create( &vthread.thread, NULL, video_thread, NULL );
+               vthread.running = 1;
+       }
+}
+
+
+
+static void show_frame()
+{
+       if ( (fb.width != new_frame.width) || (fb.height != new_frame.height) ) {
+               glDeleteFramebuffers( 1, &fb.fbo );
+               glDeleteTextures( 1, &fb.texture );
+               fb.fbo = 0;
+               fb.width = new_frame.width;
+               fb.height = new_frame.height;
+               glGenFramebuffers( 1, &fb.fbo );
+               glGenTextures( 1, &fb.texture );
+               glBindTexture( GL_TEXTURE_2D, fb.texture );
+               glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, fb.width, fb.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
+               glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+               glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+               glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+               glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+               glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo );
+               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.texture, 0 );
+               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       }
+
+       glPushAttrib(GL_VIEWPORT_BIT);
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+       
+       glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo );
+       
+       glViewport( 0, 0, new_frame.width, new_frame.height );
+       glMatrixMode( GL_PROJECTION );
+       glLoadIdentity();
+       glOrtho( 0.0, new_frame.width, 0.0, new_frame.height, -1.0, 1.0 );
+       glMatrixMode( GL_MODELVIEW );
+       glLoadIdentity();
+
+       glActiveTexture( GL_TEXTURE0 );
+    glBindTexture( GL_TEXTURE_2D, new_frame.texture );
+
+       glBegin( GL_QUADS );
+               glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
+               glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, new_frame.height );
+               glTexCoord2f( 1.0f, 1.0f ); glVertex2f( new_frame.width, new_frame.height );
+               glTexCoord2f( 1.0f, 0.0f ); glVertex2f( new_frame.width, 0.0f );
+       glEnd();
+
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       mlt_events_fire( MLT_CONSUMER_PROPERTIES(&xgl->parent), "consumer-frame-show", new_frame.mlt_frame_ref, NULL );
+       mlt_frame_close( new_frame.mlt_frame_ref );
+       new_frame.mlt_frame_ref = NULL;
+
+       glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glMatrixMode(GL_MODELVIEW);
+    glPopAttrib();
+       
+       update();
+       
+       new_frame.new = 0;
+}
+
+
+
+void* video_thread( void *arg )
+{
+       mlt_frame next = NULL;
+       mlt_consumer consumer = &xgl->parent;
+       mlt_properties consumer_props = MLT_CONSUMER_PROPERTIES( consumer );
+       struct timeval start, end;
+       double duration = 0;
+       
+       gettimeofday( &start, NULL );
+       
+       while ( vthread.running )
+       {
+               // Get a frame from the attached producer
+               next = mlt_consumer_rt_frame( consumer );
+
+               if ( !mlt_properties_get_int( MLT_FILTER_PROPERTIES( glsl_manager ), "glsl_supported" ) ) {
+                       mlt_log_error( MLT_CONSUMER_SERVICE(consumer), "OpenGL Shading Language is not supported on this machine.\n" );
+                       xgl->running = 0;
+                       break;
+               }
+
+               // Ensure that we have a frame
+               if ( next )
+               {
+                       mlt_properties properties =  MLT_FRAME_PROPERTIES( next );
+                       if ( mlt_properties_get_int( properties, "rendered" ) == 1 )
+                       {
+                               // Get the image, width and height
+                               mlt_image_format vfmt = mlt_image_glsl_texture;
+                               int width = 0, height = 0;
+                               GLuint *image = 0;
+                               int error = mlt_frame_get_image( next, (uint8_t**) &image, &vfmt, &width, &height, 0 );
+                               if ( !error && image && width && height && !new_frame.new ) {
+                                       new_frame.width = width;
+                                       new_frame.height = height;
+                                       new_frame.texture = *image;
+                                       new_frame.mlt_frame_ref = next;
+                                       new_frame.aspect_ratio = ((double)width / (double)height) * mlt_properties_get_double( properties, "aspect_ratio" );
+                                       new_frame.new = 1;
+                                       
+                                       int loop = 200;
+                                       while ( new_frame.new && --loop )
+                                               usleep( 500 );
+                               }
+                               else
+                               {
+                                       mlt_frame_close( next );
+                               }
+                               new_frame.new = 0;
+                               
+                               gettimeofday( &end, NULL );
+                               duration = 1000000.0 / mlt_properties_get_double( consumer_props, "fps" );
+                               duration -= ( end.tv_sec * 1000000 + end.tv_usec ) - ( start.tv_sec * 1000000 + start.tv_usec );
+                               if ( duration > 0 )
+                                       usleep( (int)duration );
+                               gettimeofday( &start, NULL );
+                       }
+                       else
+                       {
+                               mlt_frame_close( next );
+                               static int dropped = 0;
+                               mlt_log_info( MLT_CONSUMER_SERVICE(consumer), "dropped video frame %d\n", ++dropped );
+                       }
+               }
+               else
+                       usleep( 1000 );
+       }
+       mlt_consumer_stopped( consumer );
+       
+       return NULL;
+}
+
+
+
+static void resizeGLScene()
+{
+       glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+       
+       if ( GLWin.height == 0 )
+               GLWin.height = 1;
+       if ( GLWin.width == 0 )
+               GLWin.width = 1;
+       glViewport( 0, 0, GLWin.width, GLWin.height );
+       glMatrixMode( GL_PROJECTION );
+       glLoadIdentity();
+       glOrtho( 0.0, GLWin.width, 0.0, GLWin.height, -1.0, 1.0 );
+       glMatrixMode( GL_MODELVIEW );
+
+       update();
+}
+
+
+
+static void initGL( void )
+{
+       glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+       
+       glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+       glClearDepth( 1.0f );
+       glDepthFunc( GL_LEQUAL );
+       glEnable( GL_DEPTH_TEST );
+       glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+       glEnable( GL_BLEND );
+       glShadeModel( GL_SMOOTH );
+       glEnable( GL_TEXTURE_2D );
+       glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+       typedef int (*GLXSWAPINTERVALSGI) ( int );
+       GLXSWAPINTERVALSGI mglXSwapInterval = (GLXSWAPINTERVALSGI)glXGetProcAddressARB( (const GLubyte*)"glXSwapIntervalSGI" );
+       if ( mglXSwapInterval )
+               mglXSwapInterval( 1 );
+
+       fb.fbo = 0;
+       fb.width = STARTWIDTH;
+       fb.height = STARTHEIGHT;
+       glGenFramebuffers( 1, &fb.fbo );
+       glGenTextures( 1, &fb.texture );
+       glBindTexture( GL_TEXTURE_2D, fb.texture );
+       glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, fb.width, fb.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
+       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+       glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo );
+       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.texture, 0 );
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       
+       resizeGLScene();
+}
+
+
+
+static void createGLWindow()
+{
+       const char* title = "OpenGL consumer";
+       int width = STARTWIDTH;
+       int height = STARTHEIGHT;
+       
+       int attrListSgl[] = { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8,
+               GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 16, None };
+
+       int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8,
+               GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 16, None };
+
+       XVisualInfo *vi;
+       Colormap cmap;
+       Atom wmDelete;
+       Window winDummy;
+       unsigned int borderDummy;
+
+       GLWin.dpy = XOpenDisplay( 0 );
+       GLWin.screen = DefaultScreen( GLWin.dpy );
+
+       vi = glXChooseVisual( GLWin.dpy, GLWin.screen, attrListDbl );
+       if ( !vi )
+               vi = glXChooseVisual( GLWin.dpy, GLWin.screen, attrListSgl );
+
+       GLWin.ctx = glXCreateContext( GLWin.dpy, vi, 0, GL_TRUE );
+
+       cmap = XCreateColormap( GLWin.dpy, RootWindow( GLWin.dpy, vi->screen ), vi->visual, AllocNone );
+       GLWin.attr.colormap = cmap;
+       GLWin.attr.border_pixel = 0;
+
+       GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
+       GLWin.win = XCreateWindow( GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), 0, 0, width, height,
+               0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr );
+       wmDelete = XInternAtom( GLWin.dpy, "WM_DELETE_WINDOW", True );
+       XSetWMProtocols( GLWin.dpy, GLWin.win, &wmDelete, 1 );
+       XSetStandardProperties( GLWin.dpy, GLWin.win, title, title, None, NULL, 0, NULL );
+       XMapRaised( GLWin.dpy, GLWin.win );
+
+       glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+       XGetGeometry( GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
+               &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth );
+
+       // Verify GLSL works on this machine
+       hiddenctx.ctx = glXCreateContext( GLWin.dpy, vi, GLWin.ctx, GL_TRUE );
+       if ( hiddenctx.ctx ) {
+               hiddenctx.dpy = GLWin.dpy;
+               hiddenctx.screen = GLWin.screen;
+               hiddenctx.win = RootWindow( hiddenctx.dpy, hiddenctx.screen );
+       }
+
+       initGL();
+}
+
+
+
+static void killGLWindow()
+{              
+       if ( GLWin.ctx ) {
+               if ( !glXMakeCurrent( GLWin.dpy, None, NULL ) ) {
+                       printf("Error releasing drawing context : killGLWindow\n");
+               }
+               glXDestroyContext( GLWin.dpy, GLWin.ctx );
+               GLWin.ctx = NULL;
+       }
+       
+       if ( hiddenctx.ctx )
+               glXDestroyContext( hiddenctx.dpy, hiddenctx.ctx );
+
+       XCloseDisplay( GLWin.dpy );
+}
+
+
+
+static void run()
+{
+       XEvent event;
+
+       while ( xgl->running ) {
+               while ( XPending( GLWin.dpy ) > 0 ) {
+                       XNextEvent( GLWin.dpy, &event );
+                       switch ( event.type ) {
+                               case Expose:
+                                       if ( event.xexpose.count != 0 )
+                                               break;
+                                       break;
+                               case ConfigureNotify:
+                                       if ( (event.xconfigure.width != GLWin.width) || (event.xconfigure.height != GLWin.height) ) {
+                                               GLWin.width = event.xconfigure.width;
+                                               GLWin.height = event.xconfigure.height;
+                                               resizeGLScene();
+                                       }
+                                       break;
+                               case KeyPress:
+                                       switch ( XLookupKeysym( &event.xkey, 0 ) ) {
+                                               case XK_Escape:                                                                 
+                                                       xgl->running = 0;
+                                                       break;
+                                               default: {
+                                                       mlt_producer producer = mlt_properties_get_data( xgl->properties, "transport_producer", NULL );
+                                                       char keyboard[ 2 ] = " ";
+                                                       void (*callback)( mlt_producer, char * ) = mlt_properties_get_data( xgl->properties, "transport_callback", NULL );
+                                                       if ( callback != NULL && producer != NULL )
+                                                       {
+                                                               keyboard[ 0 ] = ( char )XLookupKeysym( &event.xkey, 0 );
+                                                               callback( producer, keyboard );
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                               case ClientMessage:
+                                       if ( *XGetAtomName( GLWin.dpy, event.xclient.message_type ) == *"WM_PROTOCOLS" )
+                                               xgl->running = 0;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               
+               if ( new_frame.new )
+                       show_frame();
+               else
+                       usleep( 1000 );
+       }
+}
+
+
+
+void start_xgl( consumer_xgl consumer )
+{
+       xgl = consumer;
+       
+       pthread_mutex_init( &new_frame.mutex, NULL );
+       new_frame.aspect_ratio = 16.0 / 9.0;
+       new_frame.new = 0;
+       new_frame.width = STARTWIDTH;
+       new_frame.height = STARTHEIGHT;
+       new_frame.mlt_frame_ref = NULL;
+       
+       vthread.running = 0;
+       xgl->xgl_started = 1;
+
+       createGLWindow();
+       run();
+       if ( vthread.running ) {
+               vthread.running = 0;
+               pthread_join( vthread.thread, NULL );
+       }
+       xgl->running = 0;
+}
+
+static void on_consumer_thread_started( mlt_properties owner, HiddenContext* context )
+{
+       // Initialize this thread's OpenGL state
+       glXMakeCurrent( context->dpy, context->win, context->ctx );
+       mlt_events_fire( MLT_FILTER_PROPERTIES(glsl_manager), "init glsl", NULL );
+}
+
+/** 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 * );
+
+
+
+/** This is what will be called by the factory - anything can be passed in
+       via the argument, but keep it simple.
+*/
+
+mlt_consumer consumer_xgl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       // Create the consumer object
+       consumer_xgl this = calloc( sizeof( struct consumer_xgl_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 );
+
+               // Default scaler
+               mlt_properties_set( this->properties, "rescale", "bilinear" );
+               mlt_properties_set( this->properties, "deinterlace_method", "onefield" );
+
+               // default image format
+               mlt_properties_set( this->properties, "mlt_image_format", "glsl" );
+
+               // Default buffer for low latency
+               mlt_properties_set_int( this->properties, "buffer", 1 );
+
+               // Ensure we don't join on a non-running object
+               this->joined = 1;
+               this->xgl_started = 0;
+
+               // Allow thread to be started/stopped
+               parent->start = consumer_start;
+               parent->stop = consumer_stop;
+               parent->is_stopped = consumer_is_stopped;
+
+               // "init glsl" is required to instantiate glsl filters.
+               glsl_manager = mlt_factory_filter( profile, "glsl.manager", NULL );
+               if ( glsl_manager ) {
+                       mlt_events_listen( this->properties, &hiddenctx, "consumer-thread-started", (mlt_listener) on_consumer_thread_started );
+               } else {
+                       mlt_consumer_close( parent );
+                       parent = NULL;
+               }
+
+               // Return the consumer produced
+               return parent;
+       }
+
+       // malloc or consumer init failed
+       free( this );
+
+       // Indicate failure
+       return NULL;
+}
+
+
+
+int consumer_start( mlt_consumer parent )
+{
+       consumer_xgl this = parent->child;
+
+       if ( !this->running )
+       {
+               consumer_stop( parent );
+
+               this->running = 1;
+               this->joined = 0;
+
+               pthread_create( &this->thread, NULL, consumer_thread, this );
+       }
+
+       return 0;
+}
+
+
+
+int consumer_stop( mlt_consumer parent )
+{
+       // Get the actual object
+       consumer_xgl this = parent->child;
+       
+       if ( this->running && this->joined == 0 )
+       {
+               // Kill the thread and clean up
+               this->joined = 1;
+               this->running = 0;
+
+               if ( this->thread )
+                       pthread_join( this->thread, NULL );
+       }
+
+       return 0;
+}
+
+
+
+int consumer_is_stopped( mlt_consumer parent )
+{
+       consumer_xgl this = parent->child;
+       return !this->running;
+}
+
+
+
+static void *consumer_thread( void *arg )
+{
+       // Identify the arg
+       consumer_xgl this = arg;
+
+       XInitThreads();
+       start_xgl( this );
+
+       return NULL;
+}
+
+
+
+/** Callback to allow override of the close method.
+*/
+
+static void consumer_close( mlt_consumer parent )
+{
+       // Get the actual object
+       consumer_xgl this = parent->child;
+
+       // Stop the consumer
+       ///mlt_consumer_stop( parent );
+       mlt_filter_close( glsl_manager );
+
+       // Now clean up the rest
+       mlt_consumer_close( parent );
+
+       // Close the queue
+       mlt_deque_close( this->queue );
+
+       if ( this->xgl_started )
+               killGLWindow();
+
+       // Finally clean up this
+       free( this );
+}
diff --git a/src/modules/opengl/factory.c b/src/modules/opengl/factory.c
new file mode 100644 (file)
index 0000000..b67273c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 Dan Dennedy <dan@dennedy.org>
+ * factory.c -- the factory method interfaces
+ *
+ * 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 <limits.h>
+#include <framework/mlt.h>
+
+
+
+extern mlt_consumer consumer_xgl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_glsl_manager_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_blur_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_convert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_deconvolution_sharpen_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_diffusion_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_glow_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_lift_gamma_gain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_opacity_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_rect_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_resample_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_resize_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_saturation_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_movit_vignette_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_white_balance_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_transition transition_movit_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_transition transition_movit_overlay_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+
+static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
+{
+       char file[ PATH_MAX ];
+       snprintf( file, PATH_MAX, "%s/opengl/%s", mlt_environment( "MLT_DATA" ), (char*) data );
+       return mlt_properties_parse_yaml( file );
+}
+
+MLT_REPOSITORY
+{
+#if !defined(__DARWIN__) && !defined(WIN32)
+       MLT_REGISTER( consumer_type, "xgl", consumer_xgl_init );
+#endif
+       MLT_REGISTER( filter_type, "glsl.manager", filter_glsl_manager_init );
+       MLT_REGISTER( filter_type, "movit.blur", filter_movit_blur_init );
+       MLT_REGISTER( filter_type, "movit.convert", filter_movit_convert_init );
+       MLT_REGISTER( filter_type, "movit.crop", filter_movit_crop_init );
+       MLT_REGISTER( filter_type, "movit.diffusion", filter_movit_diffusion_init );
+       MLT_REGISTER( filter_type, "movit.glow", filter_movit_glow_init );
+       MLT_REGISTER( filter_type, "movit.lift_gamma_gain", filter_lift_gamma_gain_init );
+       MLT_REGISTER( filter_type, "movit.mirror", filter_movit_mirror_init );
+       MLT_REGISTER( filter_type, "movit.opacity", filter_movit_opacity_init );
+       MLT_REGISTER( filter_type, "movit.rect", filter_movit_rect_init );
+       MLT_REGISTER( filter_type, "movit.resample", filter_movit_resample_init );
+       MLT_REGISTER( filter_type, "movit.resize", filter_movit_resize_init );
+       MLT_REGISTER( filter_type, "movit.saturation", filter_movit_saturation_init );
+       MLT_REGISTER( filter_type, "movit.sharpen", filter_deconvolution_sharpen_init );
+       MLT_REGISTER( filter_type, "movit.vignette", filter_movit_vignette_init );
+       MLT_REGISTER( filter_type, "movit.white_balance", filter_white_balance_init );
+       MLT_REGISTER( transition_type, "movit.mix", transition_movit_mix_init );
+       MLT_REGISTER( transition_type, "movit.overlay", transition_movit_overlay_init );
+
+       MLT_REGISTER_METADATA( filter_type, "movit.blur", metadata, "filter_movit_blur.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.diffusion", metadata, "filter_movit_diffusion.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.glow", metadata, "filter_movit_glow.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.lift_gamma_gain", metadata, "filter_lift_gamma_gain.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.mirror", metadata, "filter_movit_mirror.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.opacity", metadata, "filter_movit_opacity.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.rect", metadata, "filter_movit_rect.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.saturation", metadata, "filter_movit_saturation.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.sharpen", metadata, "filter_deconvolution_sharpen.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.vignette", metadata, "filter_movit_vignette.yml" );
+       MLT_REGISTER_METADATA( filter_type, "movit.white_balance", metadata, "filter_white_balance.yml" );
+       MLT_REGISTER_METADATA( transition_type, "movit.mix", metadata, "transition_movit_mix.yml" );
+       MLT_REGISTER_METADATA( transition_type, "movit.overlay", metadata, "transition_movit_overlay.yml" );
+}
diff --git a/src/modules/opengl/fbo_input.cpp b/src/modules/opengl/fbo_input.cpp
new file mode 100644 (file)
index 0000000..fafe333
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * fbo_input.cpp
+ * Copyright (C) 2013 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 "fbo_input.h"
+#include <movit/util.h>
+
+// comes from unexported effect_util.h
+extern void set_uniform_int(GLuint glsl_program_num, const std::string &prefix, const std::string &key, int value);
+
+FBOInput::FBOInput(unsigned width, unsigned height)
+       : texture_num(0)
+       , needs_mipmaps(false)
+       , width(width)
+       , height(height)
+{
+       register_int("needs_mipmaps", &needs_mipmaps);
+}
+
+void FBOInput::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
+{
+       glActiveTexture(GL_TEXTURE0 + *sampler_num);
+       check_error();
+       glBindTexture(GL_TEXTURE_2D, texture_num);
+       check_error();
+
+       // Bind it to a sampler.
+       set_uniform_int(glsl_program_num, prefix, "tex", *sampler_num);
+       ++*sampler_num;
+}
+
+std::string FBOInput::output_fragment_shader()
+{
+       return read_file("flat_input.frag");
+//     return "uniform sampler2D PREFIX(tex); vec4 FUNCNAME(vec2 tc) { return texture2D(PREFIX(tex), tc); }\n";
+}
diff --git a/src/modules/opengl/fbo_input.h b/src/modules/opengl/fbo_input.h
new file mode 100644 (file)
index 0000000..0000e03
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * fbo_input.h
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef FBO_INPUT_H
+#define FBO_INPUT_H
+
+#include <movit/input.h>
+
+class FBOInput : public Input
+{
+public:
+       FBOInput(unsigned width, unsigned height);
+
+       virtual std::string effect_type_id() const { return "FBOInput"; }
+       void finalize() {}
+       bool can_output_linear_gamma() const { return false; }
+       AlphaHandling alpha_handling() const { return OUTPUT_POSTMULTIPLIED_ALPHA; }
+       std::string output_fragment_shader();
+       void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
+       unsigned get_width() const { return width; }
+       unsigned get_height() const { return height; }
+       Colorspace get_color_space() const { return COLORSPACE_sRGB; }
+       GammaCurve get_gamma_curve() const { return GAMMA_sRGB; }
+       void set_texture(GLuint texture) {
+               texture_num = texture;
+       }
+
+private:
+       GLuint texture_num;
+       int needs_mipmaps;
+       unsigned width, height;
+};
+
+#endif // FBO_INPUT_H
diff --git a/src/modules/opengl/filter_deconvolution_sharpen.cpp b/src/modules/opengl/filter_deconvolution_sharpen.cpp
new file mode 100644 (file)
index 0000000..546c489
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * filter_deconvolution_sharpen.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/deconvolution_sharpen_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       GlslManager::add_effect( filter, frame, new DeconvolutionSharpenEffect() );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_int( "matrix_size", mlt_properties_get_int( filter_props, "matrix_size" ) );
+                       ok |= effect->set_float( "circle_radius", mlt_properties_get_double( filter_props, "circle_radius" ) );
+                       ok |= effect->set_float( "gaussian_radius", mlt_properties_get_double( filter_props, "gaussian_radius" ) );
+                       ok |= effect->set_float( "correlation", mlt_properties_get_double( filter_props, "correlation" ) );
+                       ok |= effect->set_float( "noise", mlt_properties_get_double( filter_props, "noise" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_deconvolution_sharpen_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set_int( properties, "matrix_size", 5 );
+               mlt_properties_set_double( properties, "circle_radius", 2.0 );
+               mlt_properties_set_double( properties, "gaussian_radius", 0.0 );
+               mlt_properties_set_double( properties, "correlation", 0.95 );
+               mlt_properties_set_double( properties, "noise", 0.01 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_deconvolution_sharpen.yml b/src/modules/opengl/filter_deconvolution_sharpen.yml
new file mode 100644 (file)
index 0000000..825fc52
--- /dev/null
@@ -0,0 +1,53 @@
+schema_version: 0.1
+type: filter
+identifier: movit.sharpen
+title: Deconvolution Sharpen (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  Deconvolution Sharpen is a filter that sharpens by way of deconvolution
+  (i.e., trying to reverse the blur kernel, as opposed to just boosting high
+  frequencies), more specifically by FIR Wiener filters. It is the same
+  algorithm as used by the (now largely abandoned) Refocus plug-in for GIMP,
+  and I suspect the same as in Photoshop's “Smart Sharpen” filter.
+  The effect gives generally better results than unsharp masking, but can be very
+  GPU intensive, and requires a fair bit of tweaking to get good results without
+  ringing and/or excessive noise.
+
+parameters:
+  - identifier: matrix_size
+    title: Matrix Size
+    type: integer
+    minimum: 0
+    maximum: 10
+    default: 5
+
+  - identifier: circle_radius
+    title: Circle Radius
+    type: float
+    minimum: 0
+    default: 2
+
+  - identifier: gaussian_radius
+    title: Gaussian Radius
+    type: float
+    minimum: 0
+    default: 0
+
+  - identifier: correlation
+    title: Correlation
+    type: float
+    minimum: 0
+    default: 0.95
+
+  - identifier: noise
+    title: Noise Level
+    type: float
+    minimum: 0
+    default: 0.01
+
diff --git a/src/modules/opengl/filter_glsl_manager.cpp b/src/modules/opengl/filter_glsl_manager.cpp
new file mode 100644 (file)
index 0000000..bb17b33
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * filter_glsl_manager.cpp
+ * Copyright (C) 2011-2012 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2013 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 <stdlib.h>
+#include <string>
+#include "glsl_manager.h"
+#include <movit/init.h>
+#include <movit/effect_chain.h>
+#include "mlt_movit_input.h"
+#include "mlt_flip_effect.h"
+#include <mlt++/MltEvent.h>
+#include <mlt++/MltProducer.h>
+
+extern "C" {
+#include <framework/mlt_factory.h>
+}
+
+void deleteManager(GlslManager *p)
+{
+       delete p;
+}
+
+GlslManager::GlslManager()
+       : Mlt::Filter( mlt_filter_new() )
+       , pbo(0)
+{
+       mlt_filter filter = get_filter();
+       if ( filter ) {
+               // Set the mlt_filter child in case we choose to override virtual functions.
+               filter->child = this;
+               mlt_properties_set_data(mlt_global_properties(), "glslManager", this, 0,
+                       (mlt_destructor) deleteManager, NULL);
+
+               mlt_events_register( get_properties(), "init glsl", NULL );
+               listen("init glsl", this, (mlt_listener) GlslManager::onInit);
+       }
+}
+
+GlslManager::~GlslManager()
+{
+       mlt_log_debug(get_service(), "%s\n", __FUNCTION__);
+       while (fbo_list.peek_back())
+               delete (glsl_fbo) fbo_list.pop_back();
+       while (texture_list.peek_back())
+               delete (glsl_texture) texture_list.pop_back();
+       delete pbo;
+}
+
+GlslManager* GlslManager::get_instance()
+{
+       return (GlslManager*) mlt_properties_get_data(mlt_global_properties(), "glslManager", 0);
+}
+
+glsl_fbo GlslManager::get_fbo(int width, int height)
+{
+       for (int i = 0; i < fbo_list.count(); ++i) {
+               glsl_fbo fbo = (glsl_fbo) fbo_list.peek(i);
+               if (!fbo->used && (fbo->width == width) && (fbo->height == height)) {
+                       fbo->used = 1;
+                       return fbo;
+               }
+       }
+       GLuint fb = 0;
+       glGenFramebuffers(1, &fb);
+       if (!fb)
+               return NULL;
+
+       glsl_fbo fbo = new glsl_fbo_s;
+       if (!fbo) {
+               glDeleteFramebuffers(1, &fb);
+               return NULL;
+       }
+       fbo->fbo = fb;
+       fbo->width = width;
+       fbo->height = height;
+       fbo->used = 1;
+       fbo_list.push_back(fbo);
+       return fbo;
+}
+
+void GlslManager::release_fbo(glsl_fbo fbo)
+{
+       fbo->used = 0;
+}
+
+glsl_texture GlslManager::get_texture(int width, int height, GLint internal_format)
+{
+       for (int i = 0; i < texture_list.count(); ++i) {
+               glsl_texture tex = (glsl_texture) texture_list.peek(i);
+               if (!tex->used && (tex->width == width) && (tex->height == height) && (tex->internal_format == internal_format)) {
+                       glBindTexture(GL_TEXTURE_2D, tex->texture);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+                       glBindTexture( GL_TEXTURE_2D, 0);
+                       tex->used = 1;
+                       return tex;
+               }
+       }
+       GLuint tex = 0;
+       glGenTextures(1, &tex);
+       if (!tex)
+               return NULL;
+
+       glsl_texture gtex = new glsl_texture_s;
+       if (!gtex) {
+               glDeleteTextures(1, &tex);
+               return NULL;
+       }
+       glBindTexture( GL_TEXTURE_2D, tex );
+       glTexImage2D( GL_TEXTURE_2D, 0, internal_format, width, height, 0, internal_format, GL_UNSIGNED_BYTE, NULL );
+    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+    glBindTexture( GL_TEXTURE_2D, 0 );
+
+       gtex->texture = tex;
+       gtex->width = width;
+       gtex->height = height;
+       gtex->internal_format = internal_format;
+       gtex->used = 1;
+       texture_list.push_back(gtex);
+       return gtex;
+}
+
+void GlslManager::release_texture(glsl_texture texture)
+{
+       texture->used = 0;
+}
+
+glsl_pbo GlslManager::get_pbo(int size)
+{
+       if (!pbo) {
+               GLuint pb = 0;
+               glGenBuffers(1, &pb);
+               if (!pb)
+                       return NULL;
+
+               pbo = new glsl_pbo_s;
+               if (!pbo) {
+                       glDeleteBuffers(1, &pb);
+                       return NULL;
+               }
+               pbo->pbo = pb;
+       }
+       if (size > pbo->size) {
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo->pbo);
+               glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, size, NULL, GL_STREAM_DRAW);
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+               pbo->size = size;
+       }
+       return pbo;
+}
+
+void GlslManager::onInit( mlt_properties owner, GlslManager* filter )
+{
+       mlt_log_debug( filter->get_service(), "%s\n", __FUNCTION__ );
+#ifdef WIN32
+       std::string path = std::string(mlt_environment("MLT_APPDIR")).append("\\share\\movit");
+#elif defined(__DARWIN__) && defined(RELOCATABLE)
+       std::string path = std::string(mlt_environment("MLT_APPDIR")).append("/share/movit");
+#else
+       std::string path = std::string(getenv("MLT_MOVIT_PATH") ? getenv("MLT_MOVIT_PATH") : SHADERDIR);
+#endif
+       ::init_movit( path, mlt_log_get_level() == MLT_LOG_DEBUG? MOVIT_DEBUG_ON : MOVIT_DEBUG_OFF );
+       filter->set( "glsl_supported", movit_initialized );
+}
+
+void GlslManager::onServiceChanged( mlt_properties owner, mlt_service aservice )
+{
+       Mlt::Service service( aservice );
+       service.lock();
+       service.set( "movit chain", NULL, 0 );
+       service.set( "movit input", NULL, 0 );
+       // Destroy the effect list.
+       GlslManager::get_instance()->set( service.get( "_unique_id" ), NULL, 0 );
+       service.unlock();
+}
+
+void GlslManager::onPropertyChanged( mlt_properties owner, mlt_service service, const char* property )
+{
+       if ( property && std::string( property ) == "disable" )
+               onServiceChanged( owner, service );
+}
+
+extern "C" {
+
+mlt_filter filter_glsl_manager_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       GlslManager* g = GlslManager::get_instance();
+       if (g)
+               g->inc_ref();
+       else
+               g = new GlslManager();
+       return g->get_filter();
+}
+
+} // extern "C"
+
+Mlt::Properties GlslManager::effect_list( Mlt::Service& service )
+{
+       char *unique_id =  service.get( "_unique_id" );
+       mlt_properties properties = (mlt_properties) get_data( unique_id );
+       if ( !properties ) {
+               properties = mlt_properties_new();
+               set( unique_id, properties, 0, (mlt_destructor) mlt_properties_close );
+       }
+       Mlt::Properties p( properties );
+       return p;
+}
+
+static void deleteChain( EffectChain* chain )
+{
+       delete chain;
+}
+
+bool GlslManager::init_chain( mlt_service aservice )
+{
+       bool error = true;
+       Mlt::Service service( aservice );
+       EffectChain* chain = (EffectChain*) service.get_data( "movit chain" );
+       if ( !chain ) {
+               mlt_profile profile = mlt_service_profile( aservice );
+               Input* input = new MltInput( profile->width, profile->height );
+               chain = new EffectChain( profile->display_aspect_num, profile->display_aspect_den );
+               chain->add_input( input );
+               service.set( "movit chain", chain, 0, (mlt_destructor) deleteChain );
+               service.set( "movit input", input, 0 );
+               service.set( "_movit finalized", 0 );
+               service.listen( "service-changed", aservice, (mlt_listener) GlslManager::onServiceChanged );
+               service.listen( "property-changed", aservice, (mlt_listener) GlslManager::onPropertyChanged );
+               error = false;
+       }
+       return error;
+}
+
+EffectChain* GlslManager::get_chain( mlt_service service )
+{
+       return (EffectChain*) mlt_properties_get_data( MLT_SERVICE_PROPERTIES(service), "movit chain", NULL );
+}
+
+MltInput *GlslManager::get_input( mlt_service service )
+{
+       return (MltInput*) mlt_properties_get_data( MLT_SERVICE_PROPERTIES(service), "movit input", NULL );
+}
+
+void GlslManager::reset_finalized( mlt_service service )
+{
+       mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_movit finalized", 0 );
+}
+
+Effect* GlslManager::get_effect( mlt_filter filter, mlt_frame frame )
+{
+       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       return (Effect*) GlslManager::get_instance()->effect_list( producer ).get_data( unique_id );
+}
+
+Effect* GlslManager::add_effect( mlt_filter filter, mlt_frame frame, Effect* effect )
+{
+       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+       EffectChain* chain = (EffectChain*) producer.get_data( "movit chain" );
+       chain->add_effect( effect );
+       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
+       return effect;
+}
+
+Effect* GlslManager::add_effect( mlt_filter filter, mlt_frame frame, Effect* effect, Effect* input_b )
+{
+       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+       EffectChain* chain = (EffectChain*) producer.get_data( "movit chain" );
+       chain->add_effect( effect, chain->last_added_effect(),
+               input_b? input_b : chain->last_added_effect() );
+       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
+       return effect;
+}
+
+void GlslManager::render( mlt_service service, void* chain, GLuint fbo, int width, int height )
+{
+       EffectChain* effect_chain = (EffectChain*) chain;
+       mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
+       if ( !mlt_properties_get_int( properties, "_movit finalized" ) ) {
+               mlt_properties_set_int( properties, "_movit finalized", 1 );
+               effect_chain->add_effect( new Mlt::VerticalFlip() );
+               effect_chain->finalize();
+       }
+       effect_chain->render_to_fbo( fbo, width, height );
+}
+
+void GlslManager::lock_service( mlt_frame frame )
+{
+       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+       producer.lock();
+}
+
+void GlslManager::unlock_service( mlt_frame frame )
+{
+       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+       producer.unlock();
+}
diff --git a/src/modules/opengl/filter_lift_gamma_gain.cpp b/src/modules/opengl/filter_lift_gamma_gain.cpp
new file mode 100644 (file)
index 0000000..8129063
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * filter_lift_gamma_gain.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/lift_gamma_gain_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new LiftGammaGainEffect );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       RGBTriplet triplet(
+                               mlt_properties_get_double( filter_props, "lift_r" ),
+                               mlt_properties_get_double( filter_props, "lift_g" ),
+                               mlt_properties_get_double( filter_props, "lift_b" )
+                       );
+                       bool ok = effect->set_vec3( "lift", (float*) &triplet );
+                       triplet.r = mlt_properties_get_double( filter_props, "gamma_r" );
+                       triplet.g = mlt_properties_get_double( filter_props, "gamma_g" );
+                       triplet.b = mlt_properties_get_double( filter_props, "gamma_b" );
+                       ok |= effect->set_vec3( "gamma", (float*) &triplet );
+                       triplet.r = mlt_properties_get_double( filter_props, "gain_r" );
+                       triplet.g = mlt_properties_get_double( filter_props, "gain_g" );
+                       triplet.b = mlt_properties_get_double( filter_props, "gain_b" );
+                       ok |= effect->set_vec3( "gain", (float*) &triplet );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_lift_gamma_gain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set_double( properties, "lift_r", 0.0 );
+               mlt_properties_set_double( properties, "lift_g", 0.0 );
+               mlt_properties_set_double( properties, "lift_b", 0.0 );
+               mlt_properties_set_double( properties, "gamma_r", 1.0 );
+               mlt_properties_set_double( properties, "gamma_g", 1.0 );
+               mlt_properties_set_double( properties, "gamma_b", 1.0 );
+               mlt_properties_set_double( properties, "gain_r", 1.0 );
+               mlt_properties_set_double( properties, "gain_g", 1.0 );
+               mlt_properties_set_double( properties, "gain_b", 1.0 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_lift_gamma_gain.yml b/src/modules/opengl/filter_lift_gamma_gain.yml
new file mode 100644 (file)
index 0000000..09dfed2
--- /dev/null
@@ -0,0 +1,80 @@
+schema_version: 0.1
+type: filter
+identifier: movit.lift_gamma_gain
+title: Lift, Gamma, and Gain (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  A simple lift/gamma/gain effect, used for color grading.
+notes: >
+  Very roughly speaking, lift=shadows, gamma=midtones and gain=highlights,
+  although all parameters affect the entire curve. Mathematically speaking,
+  it is a bit unusual to look at gamma as a color, but it works pretty well
+  in practice.
+  The classic formula is: output = (gain * (x + lift * (1-x)))^(1/gamma).
+  The lift is actually a case where we actually would _not_ want linear light;
+  since black by definition becomes equal to the lift color, we want lift to
+  be pretty close to black, but in linear light that means lift affects the
+  rest of the curve relatively little. Thus, we actually convert to gamma 2.2
+  before lift, and then back again afterwards. (Gain and gamma are,
+  up to constants, commutative with the de-gamma operation.)
+
+parameters:
+  - identifier: lift_r
+    title: Lift Red
+    type: float
+    minimum: 0.0
+    default: 0.0
+
+  - identifier: lift_g
+    title: Lift Green
+    type: float
+    minimum: 0.0
+    default: 0.0
+
+  - identifier: lift_b
+    title: Lift Blue
+    type: float
+    minimum: 0.0
+    default: 0.0
+
+  - identifier: gamma_r
+    title: Gamma Red
+    type: float
+    minimum: 0.0
+    default: 1.0
+
+  - identifier: gamma_g
+    title: Gamma Green
+    type: float
+    minimum: 0.0
+    default: 1.0
+
+  - identifier: gamma_b
+    title: Gamma Blue
+    type: float
+    minimum: 0.0
+    default: 1.0
+
+  - identifier: gain_r
+    title: Gain Red
+    type: float
+    minimum: 0.0
+    default: 1.0
+
+  - identifier: gain_g
+    title: Gain Green
+    type: float
+    minimum: 0.0
+    default: 1.0
+
+  - identifier: gain_b
+    title: Gain Blue
+    type: float
+    minimum: 0.0
+    default: 1.0
diff --git a/src/modules/opengl/filter_movit_blur.cpp b/src/modules/opengl/filter_movit_blur.cpp
new file mode 100644 (file)
index 0000000..5c66e97
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * filter_movit_blur.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/blur_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new BlurEffect() );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_float( "radius", mlt_properties_get_double( filter_props, "radius" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_blur_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set_double( properties, "radius", 3 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_blur.yml b/src/modules/opengl/filter_movit_blur.yml
new file mode 100644 (file)
index 0000000..3109af7
--- /dev/null
@@ -0,0 +1,22 @@
+schema_version: 0.1
+type: filter
+identifier: movit.blur
+title: Blur (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  A separable 2D blur implemented by a combination of mipmap filtering
+  and convolution (essentially giving a convolution with a piecewise linear
+  approximation to the true impulse response).
+
+parameters:
+  - identifier: radius
+    title: Radius
+    type: float
+    minimum: 0
+    default: 3
diff --git a/src/modules/opengl/filter_movit_convert.cpp b/src/modules/opengl/filter_movit_convert.cpp
new file mode 100644 (file)
index 0000000..a9b7612
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * filter_movit_convert.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/effect_chain.h>
+#include <movit/util.h>
+#include "mlt_movit_input.h"
+#include <mlt++/MltProducer.h>
+#include "mlt_flip_effect.h"
+
+static void yuv422_to_yuv422p( uint8_t *yuv422, uint8_t *yuv422p, int width, int height )
+{
+       uint8_t *Y = yuv422p;
+       uint8_t *U = Y + width * height;
+       uint8_t *V = U + width * height / 2;
+       int n = width * height / 2 + 1;
+       while ( --n ) {
+               *Y++ = *yuv422++;
+               *U++ = *yuv422++;
+               *Y++ = *yuv422++;
+               *V++ = *yuv422++;
+       }
+}
+
+static int convert_on_cpu( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format )
+{
+       int error = 0;
+       mlt_filter cpu_csc = (mlt_filter) mlt_properties_get_data( MLT_FRAME_PROPERTIES( frame ), "cpu_csc", NULL );
+       if ( cpu_csc ) {
+               int (* save_fp )( mlt_frame self, uint8_t **image, mlt_image_format *input, mlt_image_format output )
+                       = frame->convert_image;
+               frame->convert_image = NULL;
+               mlt_filter_process( cpu_csc, frame );
+               error = frame->convert_image( frame, image, format, output_format );
+               frame->convert_image = save_fp;
+       } else {
+               error = 1;
+       }
+       return error;
+}
+
+static void delete_chain( EffectChain* chain )
+{
+       delete chain;
+}
+
+static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format )
+{
+       // Nothing to do!
+       if ( *format == output_format )
+               return 0;
+
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+
+       mlt_log_debug( NULL, "filter_movit_convert: %s -> %s\n",
+               mlt_image_format_name( *format ), mlt_image_format_name( output_format ) );
+
+       // Use CPU if glsl not initialized or not supported.
+       GlslManager* glsl = GlslManager::get_instance();
+       if ( !glsl || !glsl->get_int("glsl_supported" ) )
+               return convert_on_cpu( frame, image, format, output_format );
+
+       // Do non-GL image conversions on a CPU-based image converter.
+       if ( *format != mlt_image_glsl && output_format != mlt_image_glsl && output_format != mlt_image_glsl_texture )
+               return convert_on_cpu( frame, image, format, output_format );
+
+       int error = 0;
+       int width = mlt_properties_get_int( properties, "width" );
+       int height = mlt_properties_get_int( properties, "height" );
+       int img_size = mlt_image_format_size( *format, width, height, NULL );
+       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+       mlt_service service = MLT_PRODUCER_SERVICE(producer);
+       GlslManager::get_instance()->lock_service( frame );
+       EffectChain* chain = GlslManager::get_chain( service );
+       MltInput* input = GlslManager::get_input( service );
+
+       if ( !chain || !input ) {
+               GlslManager::get_instance()->unlock_service( frame );
+               return 2;
+       }
+
+       if ( *format != mlt_image_glsl ) {
+               bool finalize_chain = false;
+               if ( output_format == mlt_image_glsl_texture ) {
+                       // We might already have a texture from a previous conversion from mlt_image_glsl.
+                       glsl_texture texture = (glsl_texture) mlt_properties_get_data( properties, "movit.convert.texture", NULL );
+                       // XXX: requires a special property set on the frame by the app for now
+                       // because we do not have reliable way to clear the texture property
+                       // when a downstream filter has changed image.
+                       if ( texture && mlt_properties_get_int( properties, "movit.convert.use_texture") ) {
+                               *image = (uint8_t*) &texture->texture;
+                               mlt_frame_set_image( frame, *image, 0, NULL );
+                               mlt_properties_set_int( properties, "format", output_format );
+                               *format = output_format;
+                               GlslManager::get_instance()->unlock_service( frame );
+                               return error;
+                       } else {
+                               // Use a separate chain to convert image in RAM to OpenGL texture.
+                               // Use cached chain if available and compatible.
+                               Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
+                               chain = (EffectChain*) producer.get_data( "movit.convert.chain" );
+                               input = (MltInput*) producer.get_data( "movit.convert.input" );
+                               int w = producer.get_int( "movit.convert.width" );
+                               int h = producer.get_int( "movit.convert.height" );
+                               mlt_image_format f = (mlt_image_format) producer.get_int( "movit.convert.format" );
+                               if ( !chain || width != w || height != h || output_format != f ) {
+                                       chain = new EffectChain( width, height );
+                                       input = new MltInput( width, height );
+                                       chain->add_input( input );
+                                       chain->add_effect( new Mlt::VerticalFlip() );
+                                       finalize_chain = true;
+                                       producer.set( "movit.convert.chain", chain, 0, (mlt_destructor) delete_chain );
+                                       producer.set( "movit.convert.width", width );
+                                       producer.set( "movit.convert.height", height );
+                                       producer.set( "movit.convert.width", output_format );
+                               }
+                       }
+               }
+               if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) { 
+                       input->useFlatInput( chain, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, width, height );
+                       input->set_pixel_data( *image );
+               }
+               else if ( *format == mlt_image_rgb24 ) {
+                       input->useFlatInput( chain, FORMAT_RGB, width, height );
+                       input->set_pixel_data( *image );
+               }
+               else if ( *format == mlt_image_yuv420p ) {
+                       ImageFormat image_format;
+                       YCbCrFormat ycbcr_format;
+                       if ( 709 == mlt_properties_get_int( properties, "colorspace" ) ) {
+                               image_format.color_space = COLORSPACE_REC_709;
+                               image_format.gamma_curve = GAMMA_REC_709;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_709;
+                       } else if ( 576 == mlt_properties_get_int( properties, "height" ) ) {
+                               image_format.color_space = COLORSPACE_REC_601_625;
+                               image_format.gamma_curve = GAMMA_REC_601;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_601;
+                       } else {
+                               image_format.color_space = COLORSPACE_REC_601_525;
+                               image_format.gamma_curve = GAMMA_REC_601;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_601;
+                       }
+                       ycbcr_format.full_range = mlt_properties_get_int( properties, "force_full_luma" );
+                       ycbcr_format.chroma_subsampling_x = ycbcr_format.chroma_subsampling_y = 2;
+                       // TODO: make new frame properties set by producers
+                       ycbcr_format.cb_x_position = ycbcr_format.cr_x_position = 0.0f;
+                       ycbcr_format.cb_y_position = ycbcr_format.cr_y_position = 0.5f;
+                       input->useYCbCrInput( chain, image_format, ycbcr_format, width, height );
+                       input->set_pixel_data( *image );
+               }
+               else if ( *format == mlt_image_yuv422 ) {
+                       ImageFormat image_format;
+                       YCbCrFormat ycbcr_format;
+                       if ( 709 == mlt_properties_get_int( properties, "colorspace" ) ) {
+                               image_format.color_space = COLORSPACE_REC_709;
+                               image_format.gamma_curve = GAMMA_REC_709;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_709;
+                       } else if ( 576 == height ) {
+                               image_format.color_space = COLORSPACE_REC_601_625;
+                               image_format.gamma_curve = GAMMA_REC_601;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_601;
+                       } else {
+                               image_format.color_space = COLORSPACE_REC_601_525;
+                               image_format.gamma_curve = GAMMA_REC_601;
+                               ycbcr_format.luma_coefficients = YCBCR_REC_601;
+                       }
+                       ycbcr_format.full_range = mlt_properties_get_int( properties, "force_full_luma" );
+                       ycbcr_format.chroma_subsampling_x = 2;
+                       ycbcr_format.chroma_subsampling_y = 1;
+                       // TODO: make new frame properties set by producers
+                       ycbcr_format.cb_x_position = ycbcr_format.cr_x_position = 0.0f;
+                       ycbcr_format.cb_y_position = ycbcr_format.cr_y_position = 0.5f;
+                       input->useYCbCrInput( chain, image_format, ycbcr_format, width, height );
+                       
+                       // convert chunky to planar
+                       uint8_t* planar = (uint8_t*) mlt_pool_alloc( img_size );
+                       yuv422_to_yuv422p( *image, planar, width, height );
+                       input->set_pixel_data( planar );
+                       mlt_frame_set_image( frame, planar, img_size, mlt_pool_release );
+               }
+               // Finalize the separate conversion chain if needed.
+               if ( finalize_chain )
+                       chain->finalize();
+       }
+
+       if ( output_format != mlt_image_glsl ) {
+               glsl_fbo fbo = glsl->get_fbo( width, height );
+
+               if ( output_format == mlt_image_glsl_texture ) {
+                       glsl_texture texture = glsl->get_texture( width, height, GL_RGBA );
+
+                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+                       check_error();
+                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+
+                       GlslManager::render( service, chain, fbo->fbo, width, height );
+
+                       glFinish();
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+
+                       *image = (uint8_t*) &texture->texture;
+                       mlt_frame_set_image( frame, *image, 0, NULL );
+                       mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
+                               (mlt_destructor) GlslManager::release_texture, NULL );
+                       mlt_properties_set_int( properties, "format", output_format );
+                       *format = output_format;
+               }
+               else {
+                       // Use a PBO to hold the data we read back with glReadPixels()
+                       // (Intel/DRI goes into a slow path if we don't read to PBO)
+                       GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
+                               GL_RGBA : GL_RGB;
+                       img_size = width * height * ( gl_format == GL_RGB? 3 : 4 );
+                       glsl_pbo pbo = glsl->get_pbo( img_size );
+                       glsl_texture texture = glsl->get_texture( width, height, gl_format );
+
+                       if ( fbo && pbo && texture ) {
+                               // Set the FBO
+                               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+                               check_error();
+                               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+                               check_error();
+                               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                               check_error();
+
+                               GlslManager::render( service, chain, fbo->fbo, width, height );
+       
+                               // Read FBO into PBO
+                               glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
+                               check_error();
+                               glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
+                               check_error();
+                               glReadPixels( 0, 0, width, height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
+                               check_error();
+       
+                               // Copy from PBO
+                               uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
+                               check_error();
+                               *image = (uint8_t*) mlt_pool_alloc( img_size );
+                               mlt_frame_set_image( frame, *image, img_size, mlt_pool_release );
+                               memcpy( *image, buf, img_size );
+
+                               if ( output_format == mlt_image_yuv422 || output_format == mlt_image_yuv420p ) {
+                                       *format = mlt_image_rgb24;
+                                       error = convert_on_cpu( frame, image, format, output_format );
+                               }
+       
+                               // Release PBO and FBO
+                               glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
+                               check_error();
+                               glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
+                               check_error();
+                               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                               check_error();
+                               glBindTexture( GL_TEXTURE_2D, 0 );
+                               check_error();
+                               mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
+                                       (mlt_destructor) GlslManager::release_texture, NULL);
+       
+                               mlt_properties_set_int( properties, "format", output_format );
+                               *format = output_format;
+                       }
+                       else {
+                               error = 1;
+                       }
+               }
+               if ( fbo ) GlslManager::release_fbo( fbo );
+       }
+       else {
+               mlt_properties_set_int( properties, "format", output_format );
+               *format = output_format;
+       }
+       GlslManager::get_instance()->unlock_service( frame );
+
+       return error;
+}
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       // Set a default colorspace on the frame if not yet set by the producer.
+       // The producer may still change it during get_image.
+       // This way we do not have to modify each producer to set a valid colorspace.
+       mlt_properties properties = MLT_FRAME_PROPERTIES(frame);
+       if ( mlt_properties_get_int( properties, "colorspace" ) <= 0 )
+               mlt_properties_set_int( properties, "colorspace", mlt_service_profile( MLT_FILTER_SERVICE(filter) )->colorspace );
+
+       frame->convert_image = convert_image;
+
+       mlt_filter cpu_csc = (mlt_filter) mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "cpu_csc", NULL );
+       mlt_properties_inc_ref( MLT_FILTER_PROPERTIES(cpu_csc) );
+       mlt_properties_set_data( properties, "cpu_csc", cpu_csc, 0,
+               (mlt_destructor) mlt_filter_close, NULL );
+
+       return frame;
+}
+
+static mlt_filter create_filter( mlt_profile profile, char *effect )
+{
+       mlt_filter filter = NULL;
+       char *id = strdup( effect );
+       char *arg = strchr( id, ':' );
+       if ( arg != NULL )
+               *arg ++ = '\0';
+
+       // The swscale and avcolor_space filters require resolution as arg to test compatibility
+       if ( !strcmp( effect, "avcolor_space" ) )
+               arg = (char*) profile->width;
+
+       filter = mlt_factory_filter( profile, id, arg );
+       if ( filter )
+               mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_loader", 1 );
+       free( id );
+       return filter;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_convert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) )
+       {
+               mlt_filter cpu_csc = create_filter( profile, "avcolor_space" );
+               if ( !cpu_csc )
+                       cpu_csc = create_filter( profile, "imageconvert" );
+               if ( cpu_csc )
+                       mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "cpu_csc", cpu_csc, 0,
+                               (mlt_destructor) mlt_filter_close, NULL );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_crop.cpp b/src/modules/opengl/filter_movit_crop.cpp
new file mode 100644 (file)
index 0000000..d56eefe
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * filter_movit_crop.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/padding_effect.h>
+
+static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       int error = 0;
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
+       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
+       mlt_image_format requested_format = *format;
+
+       // Correct width/height if necessary
+       *width = mlt_properties_get_int( properties, "crop.original_width" );
+       *height = mlt_properties_get_int( properties, "crop.original_height" );
+       if ( *width == 0 || *height == 0 )
+       {
+               *width = mlt_properties_get_int( properties, "meta.media.width" );
+               *height = mlt_properties_get_int( properties, "meta.media.height" );
+       }
+       if ( *width == 0 || *height == 0 )
+       {
+               *width = profile->width;
+               *height = profile->height;
+       }
+       mlt_properties_set_int( properties, "rescale_width", *width );
+       mlt_properties_set_int( properties, "rescale_height", *height );
+
+       // Get the image as requested
+//     *format = (mlt_image_format) mlt_properties_get_int( MLT_PRODUCER_PROPERTIES(producer), "_movit image_format" );
+       *format = mlt_image_none;
+       error = mlt_frame_get_image( frame, image, format, width, height, writable );
+
+       // Skip processing if requested.
+       if ( requested_format == mlt_image_none )
+               return error;
+
+       if ( !error && *format != mlt_image_glsl && frame->convert_image ) {
+       // Pin the requested format to the first one returned.
+//             mlt_properties_set_int( MLT_PRODUCER_PROPERTIES(producer), "_movit image_format", *format );
+               error = frame->convert_image( frame, image, format, mlt_image_glsl );
+       }
+       if ( !error ) {
+               double left    = mlt_properties_get_double( properties, "crop.left" );
+               double right   = mlt_properties_get_double( properties, "crop.right" );
+               double top     = mlt_properties_get_double( properties, "crop.top" );
+               double bottom  = mlt_properties_get_double( properties, "crop.bottom" );
+               int owidth  = *width - left - right;
+               int oheight = *height - top - bottom;
+               owidth = owidth < 0 ? 0 : owidth;
+               oheight = oheight < 0 ? 0 : oheight;
+
+               mlt_log_debug( MLT_FILTER_SERVICE(filter), "%dx%d -> %dx%d\n", *width, *height, owidth, oheight);
+
+               GlslManager::get_instance()->lock_service( frame );
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( effect ) {
+                       bool ok = effect->set_int( "width", owidth );
+                       ok |= effect->set_int( "height", oheight );
+                       ok |= effect->set_float( "left", -left );
+                       ok |= effect->set_float( "top", -top );
+                       assert(ok);
+                       *width = owidth;
+                       *height = oheight;
+               }
+               GlslManager::get_instance()->unlock_service( frame );
+       }
+
+       return error;
+}
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+       if ( !GlslManager::init_chain( MLT_PRODUCER_SERVICE(producer) ) ) {
+               Effect* effect = GlslManager::add_effect( filter, frame, new PaddingEffect );
+               RGBATuple border_color( 0.0f, 0.0f, 0.0f, 1.0f );
+               bool ok = effect->set_vec4( "border_color", (float*) &border_color );
+               assert(ok);
+       }
+       mlt_frame_push_service( frame, filter );
+       mlt_frame_push_get_image( frame, get_image );
+       return frame;
+}
+
+extern "C"
+mlt_filter filter_movit_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               filter->process = process;
+       }
+       return filter;
+}
diff --git a/src/modules/opengl/filter_movit_diffusion.cpp b/src/modules/opengl/filter_movit_diffusion.cpp
new file mode 100644 (file)
index 0000000..31d705b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * filter_movit_diffusion.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/diffusion_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new DiffusionEffect() );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_float( "radius", mlt_properties_get_double( filter_props, "radius" ) );
+                       ok |= effect->set_float( "blurred_mix_amount", mlt_properties_get_double( filter_props, "mix" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_diffusion_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set_double( properties, "radius", 3.0 );
+               mlt_properties_set_double( properties, "mix", 0.3 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_diffusion.yml b/src/modules/opengl/filter_movit_diffusion.yml
new file mode 100644 (file)
index 0000000..e97d123
--- /dev/null
@@ -0,0 +1,35 @@
+schema_version: 0.1
+type: filter
+identifier: movit.diffusion
+title: Diffusion (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  There are many different effects that go under the name of "diffusion",
+  seemingly all of the inspired by the effect you get when you put a
+  diffusion filter in front of your camera lens. The effect most people
+  want is a general flattening/smoothing of the light, and reduction of
+  fine detail (most notably, blemishes in people's skin), without ruining
+  edges, which a regular blur would do.
+  We do a relatively simple version, sometimes known as "white diffusion",
+  where we first blur the picture, and then overlay it on the original
+  using the original as a matte.
+
+parameters:
+  - identifier: radius
+    title: Blur Radius
+    type: float
+    minimum: 0.0
+    default: 3.0
+
+  - identifier: mix
+    title: Blurriness
+    type: float
+    minimum: 0.0
+    maximum: 1.0
+    default: 0.3
diff --git a/src/modules/opengl/filter_movit_glow.cpp b/src/modules/opengl/filter_movit_glow.cpp
new file mode 100644 (file)
index 0000000..4026477
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * filter_movit_glow.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/glow_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new GlowEffect() );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_float( "radius", mlt_properties_get_double( filter_props, "radius" ) );
+                       ok |= effect->set_float( "blurred_mix_amount", mlt_properties_get_double( filter_props, "blur_mix" ) );
+                       ok |= effect->set_float( "highlight_cutoff", mlt_properties_get_double( filter_props, "highlight_cutoff" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_glow_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set_double( properties, "radius", 20.0 );
+               mlt_properties_set_double( properties, "blur_mix", 1.0 );
+               mlt_properties_set_double( properties, "highlight_cutoff", 0.2 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_glow.yml b/src/modules/opengl/filter_movit_glow.yml
new file mode 100644 (file)
index 0000000..258f683
--- /dev/null
@@ -0,0 +1,35 @@
+schema_version: 0.1
+type: filter
+identifier: movit.glow
+title: Glow (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  Cut out the highlights of the image (everything above a certain threshold),
+  blur them, and overlay them onto the original image.
+
+parameters:
+  - identifier: radius
+    title: Radius
+    type: float
+    minimum: 0.0
+    default: 20.0
+
+  - identifier: blur_mix
+    title: Highlight Blurriness
+    type: float
+    minimum: 0.0
+    maximum: 1.0
+    default: 1.0
+
+  - identifier: highlight_cutoff
+    title: Highlight Cutoff Threshold
+    type: float
+    minimum: 0.0
+    maximum: 1.0
+    default: 0.2
diff --git a/src/modules/opengl/filter_movit_mirror.cpp b/src/modules/opengl/filter_movit_mirror.cpp
new file mode 100644 (file)
index 0000000..8b6ab1f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * filter_movit_mirror.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/mirror_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       GlslManager::add_effect( filter, frame, new MirrorEffect() );
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
+
diff --git a/src/modules/opengl/filter_movit_mirror.yml b/src/modules/opengl/filter_movit_mirror.yml
new file mode 100644 (file)
index 0000000..123b343
--- /dev/null
@@ -0,0 +1,12 @@
+schema_version: 0.1
+type: filter
+identifier: movit.mirror
+title: Mirror (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+description: A simple horizontal mirroring.
+tags:
+  - Video
diff --git a/src/modules/opengl/filter_movit_opacity.cpp b/src/modules/opengl/filter_movit_opacity.cpp
new file mode 100644 (file)
index 0000000..8586182
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * filter_movit_opacity.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/mix_effect.h>
+
+static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
+       mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+       GlslManager::get_instance()->lock_service( frame );
+       Effect* effect = GlslManager::get_effect( filter, frame );
+       if ( effect ) {
+               bool ok = effect->set_float( "strength_first", mlt_properties_get_double( properties, "opacity" ) );
+               assert(ok);
+       }
+       GlslManager::get_instance()->unlock_service( frame );
+       *format = mlt_image_glsl;
+       return mlt_frame_get_image( frame, image, format, width, height, writable );
+}
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect ) {
+                       effect = GlslManager::add_effect( filter, frame, new MixEffect, 0 );
+                       assert(effect);
+                       bool ok = effect->set_float( "strength_first", 1.0f );
+                       ok |= effect->set_float( "strength_second", 0.0f );
+                       assert(ok);
+               }
+       }
+       mlt_frame_push_service( frame, filter );
+       mlt_frame_push_get_image( frame, get_image );
+       return frame;
+}
+
+extern "C"
+mlt_filter filter_movit_opacity_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set( properties, "opacity", arg? arg : "1" );
+               filter->process = process;
+       }
+       return filter;
+}
diff --git a/src/modules/opengl/filter_movit_opacity.yml b/src/modules/opengl/filter_movit_opacity.yml
new file mode 100644 (file)
index 0000000..fa82b60
--- /dev/null
@@ -0,0 +1,25 @@
+schema_version: 0.1
+type: filter
+identifier: movit.opacity
+title: Opacity (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: Adjust the opacity of an image through the alpha channel.
+notes: >
+  When used in some transitions this will cause this video to be mixed with
+  the other video. If the video this is applied to already has an alpha channel,
+  then this preserves that by multiplying the opacity level with the alpha channel.
+  This filter is especially handy when used in conjunction with movit.overlay.
+
+parameters:
+  - identifier: opacity
+    title: Opacity
+    type: float
+    minimum: 0
+    maximum: 1
+    default: 1
diff --git a/src/modules/opengl/filter_movit_rect.cpp b/src/modules/opengl/filter_movit_rect.cpp
new file mode 100644 (file)
index 0000000..004f2f7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * filter_movit_rect.cpp
+ * Copyright (C) 2013 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 "glsl_manager.h"
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       // Drive the resize and resample filters on the b_frame for these composite parameters
+       mlt_properties properties = MLT_FILTER_PROPERTIES(filter);
+       mlt_properties frame_props = MLT_FRAME_PROPERTIES(frame);
+       mlt_properties_set( frame_props, "resize.geometry", mlt_properties_get( properties, "geometry" ) );
+       mlt_properties_set( frame_props, "resize.fill", mlt_properties_get( properties, "fill" ) );
+       mlt_properties_set( frame_props, "resize.halign", mlt_properties_get( properties, "halign" ) );
+       mlt_properties_set( frame_props, "resize.valign", mlt_properties_get( properties, "valign" ) );
+       return frame;
+}
+
+extern "C"
+mlt_filter filter_movit_rect_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties_set( MLT_FILTER_PROPERTIES(filter), "geometry", arg );
+               mlt_properties_set_int( MLT_FILTER_PROPERTIES(filter), "fill", 1 );
+               filter->process = process;
+       }
+       return filter;
+}
diff --git a/src/modules/opengl/filter_movit_rect.yml b/src/modules/opengl/filter_movit_rect.yml
new file mode 100644 (file)
index 0000000..a077927
--- /dev/null
@@ -0,0 +1,60 @@
+schema_version: 0.1
+type: filter
+identifier: movit.rect
+title: Position and Size (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  Change the coordinates and scale to fit within a rectangle.
+
+parameters:
+  - identifier: geometry
+    title: Rectangle
+    type: geometry
+    description: > 
+      Keyframable rectangle specification.
+    mutable: yes
+
+  - identifier: fill
+    title: Upscale to Fill
+    description: >
+      Determines whether the image will be scaled up to fill the rectangle
+      or whether the size will be constrained to 100% of the profile
+      resolution.
+    type: integer
+    default: 1
+    minimum: 0
+    maximum: 1
+    mutable: yes
+    widget: checkbox
+
+  - identifier: halign
+    title: Horizontal alignment
+    description: >
+      Set the horizontal alignment within the geometry rectangle.
+    type: string
+    default: left
+    values:
+      - left
+      - center
+      - right
+    mutable: yes
+    widget: combo
+
+  - identifier: valign
+    title: Vertical alignment
+    description: >
+      Set the vertical alignment within the geometry rectangle.
+    type: string
+    default: top
+    values:
+      - top
+      - middle
+      - bottom
+    mutable: yes
+    widget: combo
diff --git a/src/modules/opengl/filter_movit_resample.cpp b/src/modules/opengl/filter_movit_resample.cpp
new file mode 100644 (file)
index 0000000..3375b28
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * filter_movit_resample.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/resample_effect.h>
+
+static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       int error = 0;
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
+       mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
+       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
+
+       // Correct width/height if necessary
+       if ( *width == 0 || *height == 0 )
+       {
+               *width = profile->width;
+               *height = profile->height;
+       }
+
+       int iwidth = *width;
+       int iheight = *height;
+       double factor = mlt_properties_get_double( filter_properties, "factor" );
+       factor = factor > 0 ? factor : 1.0;
+       int owidth = *width * factor;
+       int oheight = *height * factor;
+
+       // If meta.media.width/height exist, we want that as minimum information
+       if ( mlt_properties_get_int( properties, "meta.media.width" ) )
+       {
+               iwidth = mlt_properties_get_int( properties, "meta.media.width" );
+               iheight = mlt_properties_get_int( properties, "meta.media.height" );
+       }
+
+       mlt_properties_set_int( properties, "rescale_width", *width );
+       mlt_properties_set_int( properties, "rescale_height", *height );
+
+       // Deinterlace if height is changing to prevent fields mixing on interpolation
+       if ( iheight != oheight )
+               mlt_properties_set_int( properties, "consumer_deinterlace", 1 );
+
+       // Get the image as requested
+       if ( *format != mlt_image_none )
+               *format = mlt_image_glsl;
+       error = mlt_frame_get_image( frame, image, format, &iwidth, &iheight, writable );
+       if ( !error ) {
+               GlslManager::get_instance()->lock_service( frame );
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( effect ) {
+                       bool ok = effect->set_int( "width", owidth );
+                       ok |= effect->set_int( "height", oheight );
+                       assert(ok);
+                       *width = owidth;
+                       *height = oheight;
+               }
+               GlslManager::get_instance()->unlock_service( frame );
+       }
+
+       return error;
+}
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !GlslManager::get_effect( filter, frame ) )
+               GlslManager::add_effect( filter, frame, new ResampleEffect );
+       mlt_frame_push_service( frame, filter );
+       mlt_frame_push_get_image( frame, get_image );
+       return frame;
+}
+
+extern "C"
+mlt_filter filter_movit_resample_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               filter->process = process;
+       }
+       return filter;
+}
diff --git a/src/modules/opengl/filter_movit_resize.cpp b/src/modules/opengl/filter_movit_resize.cpp
new file mode 100644 (file)
index 0000000..cb1c542
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * filter_movit_resize.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/init.h>
+#include <movit/padding_effect.h>
+
+static float alignment_parse( char* align )
+{
+       int ret = 0.0f;
+
+       if ( align == NULL );
+       else if ( isdigit( align[ 0 ] ) )
+               ret = atoi( align );
+       else if ( align[ 0 ] == 'c' || align[ 0 ] == 'm' )
+               ret = 1.0f;
+       else if ( align[ 0 ] == 'r' || align[ 0 ] == 'b' )
+               ret = 2.0f;
+
+       return ret;
+}
+
+static struct mlt_geometry_item_s get_geometry( mlt_profile profile, mlt_filter filter, mlt_frame frame )
+{
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+       struct mlt_geometry_item_s item;
+       mlt_geometry geometry = (mlt_geometry) mlt_properties_get_data( filter_props, "geometry", NULL );
+       char *string = mlt_properties_get( properties, "resize.geometry" );
+       int length = mlt_filter_get_length2( filter, frame );
+
+       if ( !geometry ) {
+               geometry = mlt_geometry_init();
+               mlt_properties_set_data( filter_props, "geometry", geometry, 0,
+                       (mlt_destructor) mlt_geometry_close, NULL );
+               mlt_geometry_parse( geometry, string, length, profile->width, profile->height );
+       } else {
+               mlt_geometry_refresh( geometry, string, length, profile->width, profile->height );
+       }
+
+       mlt_geometry_fetch( geometry, &item, mlt_filter_get_position( filter, frame ) );
+
+       if ( !mlt_properties_get_int( properties, "resize.fill" ) ) {
+               int x = mlt_properties_get_int( properties, "meta.media.width" );
+               item.w = item.w > x ? x : item.w;
+               x = mlt_properties_get_int( properties, "meta.media.height" );
+               item.h = item.h > x ? x : item.h;
+       }
+
+       return item;
+}
+
+static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       int error = 0;
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
+       mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
+
+       // Retrieve the aspect ratio
+       double aspect_ratio = mlt_frame_get_aspect_ratio( frame );
+       double consumer_aspect = mlt_profile_sar( profile );
+
+       // Correct Width/height if necessary
+       if ( *width == 0 || *height == 0 )
+       {
+               *width = profile->width;
+               *height = profile->height;
+       }
+
+       // Assign requested width/height from our subordinate
+       int owidth = *width;
+       int oheight = *height;
+
+       // Use a geometry to compute position and size
+       struct mlt_geometry_item_s geometry_item;
+       geometry_item.x = geometry_item.y = 0.0f;
+       geometry_item.distort = 0;
+       if ( mlt_properties_get( properties, "resize.geometry" ) ) {
+               geometry_item = get_geometry( profile, filter, frame );
+               owidth = lrintf( geometry_item.w );
+               oheight = lrintf( geometry_item.h );
+       }
+
+       // Check for the special case - no aspect ratio means no problem :-)
+       if ( aspect_ratio == 0.0 )
+               aspect_ratio = consumer_aspect;
+
+       // Reset the aspect ratio
+       mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio );
+
+       // Skip processing if requested.
+       char *rescale = mlt_properties_get( properties, "rescale.interp" );
+       if ( *format == mlt_image_none || ( rescale && !strcmp( rescale, "none" ) ) )
+               return mlt_frame_get_image( frame, image, format, width, height, writable );
+
+       if ( mlt_properties_get_int( properties, "distort" ) == 0 &&
+            geometry_item.distort == 0 )
+       {
+               // Normalise the input and out display aspect
+               int normalised_width = profile->width;
+               int normalised_height = profile->height;
+               int real_width = mlt_properties_get_int( properties, "meta.media.width" );
+               int real_height = mlt_properties_get_int( properties, "meta.media.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 = consumer_aspect * owidth / oheight;
+               
+               // Optimised for the input_ar > output_ar case (e.g. widescreen on standard)
+               int scaled_width = lrint( ( 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 = lrint( ( output_ar * normalised_height ) / input_ar );
+               }
+
+               // Now calculate the actual image size that we want
+               owidth = lrint( scaled_width * owidth / normalised_width );
+               oheight = lrint( scaled_height * oheight / normalised_height );
+
+               mlt_log_debug( MLT_FILTER_SERVICE(filter),
+                       "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);
+
+               // Tell frame we have conformed the aspect to the consumer
+               mlt_frame_set_aspect_ratio( frame, consumer_aspect );
+       }
+
+       mlt_properties_set_int( properties, "distort", 0 );
+
+       // Now get the image
+       *format = mlt_image_glsl;
+       error = mlt_frame_get_image( frame, image, format, &owidth, &oheight, writable );
+
+       // Offset the position according to alignment
+       float w = float( *width - owidth );
+       float h = float( *height - oheight );
+       if ( mlt_properties_get( properties, "resize.geometry" ) ) {
+               // default left if geometry supplied
+               geometry_item.x += w * alignment_parse( mlt_properties_get( properties, "resize.halign" ) ) / 2.0f;
+               geometry_item.y += h * alignment_parse( mlt_properties_get( properties, "resize.valign" ) ) / 2.0f;
+       } else {
+               // default center if no geometry
+               geometry_item.x = w * 0.5f;
+               geometry_item.y = h * 0.5f;
+       }
+
+       if ( !error ) {
+               GlslManager::get_instance()->lock_service( frame );
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( effect ) {
+                       bool ok = effect->set_int( "width", *width );
+                       ok |= effect->set_int( "height", *height );
+                       ok |= effect->set_float( "left", geometry_item.x );
+                       ok |= effect->set_float( "top", geometry_item.y );
+                       assert(ok);
+               }
+               GlslManager::get_instance()->unlock_service( frame );
+       }
+
+       return error;
+}
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !GlslManager::get_effect( filter, frame ) )
+               GlslManager::add_effect( filter, frame, new PaddingEffect );
+       mlt_frame_push_service( frame, filter );
+       mlt_frame_push_get_image( frame, get_image );
+       return frame;
+}
+
+extern "C"
+mlt_filter filter_movit_resize_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) )
+       {
+               filter->process = process;
+       }
+       return filter;
+}
diff --git a/src/modules/opengl/filter_movit_saturation.cpp b/src/modules/opengl/filter_movit_saturation.cpp
new file mode 100644 (file)
index 0000000..1e8f921
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * filter_movit_saturation.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/saturation_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new SaturationEffect() );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_float( "saturation", mlt_properties_get_double( filter_props, "saturation" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_saturation_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set( properties, "saturation", arg? arg : "1.0" );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_saturation.yml b/src/modules/opengl/filter_movit_saturation.yml
new file mode 100644 (file)
index 0000000..535af59
--- /dev/null
@@ -0,0 +1,24 @@
+schema_version: 0.1
+type: filter
+identifier: movit.saturation
+title: Saturation (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  A simple desaturation/saturation effect. We use the Rec. 709
+  definition of luminance (in linear light, of course) and linearly
+  interpolate between that (saturation=0) and the original signal
+  (saturation=1). Extrapolating that curve further (ie., saturation > 1)
+  gives us increased saturation if so desired.
+
+parameters:
+  - identifier: saturation
+    title: Saturation
+    type: float
+    minimum: 0
+    default: 1
diff --git a/src/modules/opengl/filter_movit_vignette.cpp b/src/modules/opengl/filter_movit_vignette.cpp
new file mode 100644 (file)
index 0000000..b0e33f7
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * filter_movit_vignette.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/vignette_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect ) {
+                       effect = GlslManager::add_effect( filter, frame, new VignetteEffect() );
+               }
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       bool ok = effect->set_float( "radius", mlt_properties_get_double( filter_props, "radius" ) );
+                       ok |= effect->set_float( "inner_radius", mlt_properties_get_double( filter_props, "inner_radius" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_movit_vignette_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               filter->process = process;
+               mlt_properties_set_double( MLT_FILTER_PROPERTIES(filter), "radius", 0.3 );
+               mlt_properties_set_double( MLT_FILTER_PROPERTIES(filter), "inner_radius", 0.3 );
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_movit_vignette.yml b/src/modules/opengl/filter_movit_vignette.yml
new file mode 100644 (file)
index 0000000..3355bd3
--- /dev/null
@@ -0,0 +1,29 @@
+schema_version: 0.1
+type: filter
+identifier: movit.vignette
+title: Vignette (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  A circular vignette, falling off as cos² of the distance from the center
+  (the classic formula for approximating a real lens).
+
+parameters:
+  - identifier: radius
+    title: Outer Radius
+    type: float
+    minimum: 0.0
+    maximum: 1.0
+    default: 0.3
+
+  - identifier: inner_radius
+    title: Inner Radius
+    type: float
+    minimum: 0.0
+    maximum: 1.0
+    default: 0.3
diff --git a/src/modules/opengl/filter_white_balance.cpp b/src/modules/opengl/filter_white_balance.cpp
new file mode 100644 (file)
index 0000000..e3f1d9c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * filter_white_balance.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/white_balance_effect.h>
+
+static mlt_frame process( mlt_filter filter, mlt_frame frame )
+{
+       if ( !mlt_frame_is_test_card( frame ) ) {
+               Effect* effect = GlslManager::get_effect( filter, frame );
+               if ( !effect )
+                       effect = GlslManager::add_effect( filter, frame, new WhiteBalanceEffect );
+               if ( effect ) {
+                       mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter );
+                       int color_int = mlt_properties_get_int( filter_props, "neutral_color" );
+                       RGBTriplet color(
+                               float((color_int >> 24) & 0xff) / 255.0f,
+                               float((color_int >> 16) & 0xff) / 255.0f,
+                               float((color_int >> 8) & 0xff) / 255.0f
+                       );
+                       bool ok = effect->set_vec3( "neutral_color", (float*) &color );
+                       ok |= effect->set_float( "output_color_temperature", mlt_properties_get_double( filter_props, "color_temperature" ) );
+                       assert(ok);
+               }
+       }
+       return frame;
+}
+
+extern "C" {
+
+mlt_filter filter_white_balance_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+
+       if ( glsl && ( filter = mlt_filter_new() ) ) {
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+               mlt_properties_set( properties, "neutral_color", arg? arg : "#7f7f7f" );
+               mlt_properties_set_double( properties, "color_temperature", 6500.0 );
+               filter->process = process;
+       }
+       return filter;
+}
+
+}
diff --git a/src/modules/opengl/filter_white_balance.yml b/src/modules/opengl/filter_white_balance.yml
new file mode 100644 (file)
index 0000000..d090dbe
--- /dev/null
@@ -0,0 +1,27 @@
+schema_version: 0.1
+type: filter
+identifier: movit.white_balance
+title: White Balance (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: Color correction in LMS color space.
+
+parameters:
+  - identifier: neutral_color
+    title: Neutral Color
+    type: string
+    widget: color
+    default: #7f7f7f
+
+  - identifier: color_temperature
+    title: Color Temperature
+    type: float
+    minimum: 1000.0
+    maximum: 15000.0
+    default: 6500.0
+    unit: Kelvin
diff --git a/src/modules/opengl/glsl_manager.h b/src/modules/opengl/glsl_manager.h
new file mode 100644 (file)
index 0000000..d1c8769
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * glsl_manager.h
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef GLSL_MANAGER_H
+#define GLSL_MANAGER_H
+
+#include <GL/glew.h>
+#include <mlt++/MltFilter.h>
+#include <mlt++/MltDeque.h>
+
+#define MAXLISTCOUNT 1024
+typedef struct glsl_list_s *glsl_list;
+struct glsl_list_s
+{
+       void *items[MAXLISTCOUNT];
+       int count;
+
+       int ( *add )( glsl_list, void* );
+       void* ( *at )( glsl_list, int );
+       void* ( *take_at )( glsl_list, int );
+       void* ( *take )( glsl_list, void* );
+};
+
+struct glsl_texture_s
+{
+       int used;
+       GLuint texture;
+       int width;
+       int height;
+       GLint internal_format;
+};
+typedef struct glsl_texture_s *glsl_texture;
+
+struct glsl_fbo_s
+{
+       int used;
+       int width;
+       int height;
+       GLuint fbo;
+};
+typedef struct glsl_fbo_s *glsl_fbo;
+
+struct glsl_pbo_s
+{
+       int size;
+       GLuint pbo;
+};
+typedef struct glsl_pbo_s *glsl_pbo;
+
+class Effect;
+class EffectChain;
+class MltInput;
+
+class GlslManager : public Mlt::Filter
+{
+public:
+       GlslManager();
+       ~GlslManager();
+       static GlslManager* get_instance();
+
+       glsl_fbo get_fbo(int width, int height);
+       static void release_fbo(glsl_fbo);
+       glsl_texture get_texture(int width, int height, GLint internal_format);
+       static void release_texture(glsl_texture);
+       glsl_pbo get_pbo(int size);
+
+       Properties effect_list( Mlt::Service &service );
+       static bool init_chain(mlt_service);
+       static EffectChain* get_chain(mlt_service);
+       static MltInput* get_input(mlt_service);
+       static void reset_finalized(mlt_service);
+       static Effect* get_effect(mlt_filter, mlt_frame);
+       static Effect* add_effect(mlt_filter, mlt_frame, Effect*);
+       static Effect* add_effect(mlt_filter, mlt_frame, Effect*, Effect* input_b);
+       static void render(mlt_service, void *chain, GLuint fbo, int width, int height);
+       static void lock_service(mlt_frame frame);
+       static void unlock_service(mlt_frame frame);
+
+private:
+       static void onInit( mlt_properties owner, GlslManager* filter );
+       static void onServiceChanged( mlt_properties owner, mlt_service service );
+       static void onPropertyChanged( mlt_properties owner, mlt_service service, const char* property );
+       Mlt::Deque fbo_list;
+       Mlt::Deque texture_list;
+       glsl_pbo  pbo;
+       EffectChain* current_chain;
+};
+
+#endif // GLSL_MANAGER_H
diff --git a/src/modules/opengl/mlt_flip_effect.h b/src/modules/opengl/mlt_flip_effect.h
new file mode 100644 (file)
index 0000000..3fa9b72
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * mlt_flip_effect.h
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef MLT_FLIP_EFFECT_H
+#define MLT_FLIP_EFFECT_H
+
+namespace Mlt
+{
+
+class VerticalFlip : public Effect {
+public:
+       VerticalFlip() {}
+       virtual std::string effect_type_id() const { return "MltVerticalFlip"; }
+       std::string output_fragment_shader() {
+               return "vec4 FUNCNAME(vec2 tc) { tc.y = 1.0 - tc.y; return INPUT(tc); }\n";
+       }
+       virtual bool needs_linear_light() const { return false; }
+       virtual bool needs_srgb_primaries() const { return false; }
+       AlphaHandling alpha_handling() const { return DONT_CARE_ALPHA_TYPE; }
+};
+
+} // namespace Mlt
+
+#endif // MLT_FLIP_EFFECT_H
diff --git a/src/modules/opengl/mlt_movit_input.cpp b/src/modules/opengl/mlt_movit_input.cpp
new file mode 100644 (file)
index 0000000..f4b2902
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * mlt_movit_input.cpp
+ * Copyright (C) 2013 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 "mlt_movit_input.h"
+#include "fbo_input.h"
+
+MltInput::MltInput(unsigned width, unsigned height)
+       : m_width(width)
+       , m_height(height)
+       , output_linear_gamma(false)
+       , needs_mipmaps(false)
+       , input(0)
+       , isRGB(true)
+{
+       register_int("output_linear_gamma", &output_linear_gamma);
+       register_int("needs_mipmaps", &needs_mipmaps);
+}
+
+MltInput::~MltInput()
+{
+       // XXX: this is crashing when a producer is closed
+       // on Windows when using melt with qglsl.
+//     delete input;
+}
+
+std::string MltInput::output_fragment_shader()
+{
+       assert(input);
+       return input->output_fragment_shader();
+}
+
+void MltInput::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
+{
+       assert(input);
+       input->set_gl_state(glsl_program_num, prefix, sampler_num);
+}
+
+Effect::AlphaHandling MltInput::alpha_handling() const
+{
+       assert(input);
+       return input->alpha_handling();
+}
+
+void MltInput::finalize()
+{
+       assert(input);
+       bool ok = input->set_int("output_linear_gamma", output_linear_gamma);
+       ok |= input->set_int("needs_mipmaps", needs_mipmaps);
+       assert(ok);
+       input->finalize();
+}
+
+bool MltInput::can_output_linear_gamma() const
+{
+       assert(input);
+       return input->can_output_linear_gamma();
+}
+
+Colorspace MltInput::get_color_space() const
+{
+       assert(input);
+       return input->get_color_space();
+}
+GammaCurve MltInput::get_gamma_curve() const
+{
+       assert(input);
+       return input->get_gamma_curve();
+}
+
+void MltInput::useFlatInput(EffectChain* chain, MovitPixelFormat pix_fmt, unsigned width, unsigned height)
+{
+       if (!input) {
+               m_width = width;
+               m_height = height;
+               ImageFormat image_format;
+               image_format.color_space = COLORSPACE_sRGB;
+               image_format.gamma_curve = GAMMA_sRGB;
+               input = new FlatInput(image_format, pix_fmt, GL_UNSIGNED_BYTE, width, height);
+               chain->add_output(image_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+               chain->set_dither_bits(8);
+       }
+}
+
+void MltInput::useYCbCrInput(EffectChain* chain, const ImageFormat& image_format, const YCbCrFormat& ycbcr_format, unsigned width, unsigned height)
+{
+       if (!input) {
+               m_width = width;
+               m_height = height;
+               input = new YCbCrInput(image_format, ycbcr_format, width, height);
+               ImageFormat output_format;
+               output_format.color_space = COLORSPACE_sRGB;
+               output_format.gamma_curve = GAMMA_sRGB;
+               chain->add_output(output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+               chain->set_dither_bits(8);
+               isRGB = false;
+               m_ycbcr_format = ycbcr_format;
+       }
+}
+
+void MltInput::useFBOInput(EffectChain *chain, GLuint texture)
+{
+       if (!input) {
+               FBOInput* fboInput = new FBOInput(m_width, m_height);
+               input = fboInput;
+               fboInput->set_texture(texture);
+       }
+}
+
+void MltInput::set_pixel_data(const unsigned char* data)
+{
+       assert(input);
+       if (isRGB) {
+               FlatInput* flat = (FlatInput*) input;
+               flat->set_pixel_data(data);
+       } else {
+               YCbCrInput* ycbcr = (YCbCrInput*) input;
+               ycbcr->set_pixel_data(0, data);
+               ycbcr->set_pixel_data(1, &data[m_width * m_height]);
+               ycbcr->set_pixel_data(2, &data[m_width * m_height + (m_width / m_ycbcr_format.chroma_subsampling_x * m_height / m_ycbcr_format.chroma_subsampling_y)]);
+       }
+}
diff --git a/src/modules/opengl/mlt_movit_input.h b/src/modules/opengl/mlt_movit_input.h
new file mode 100644 (file)
index 0000000..2f5de23
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * mlt_movit_input.h
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef MLT_MOVIT_INPUT_H
+#define MLT_MOVIT_INPUT_H
+
+#include <movit/flat_input.h>
+#include <movit/ycbcr_input.h>
+#include <movit/effect_chain.h>
+
+class MltInput : public Input
+{
+public:
+       MltInput(unsigned width, unsigned height);
+       ~MltInput();
+
+       // Effect overrides
+       std::string effect_type_id() const { return "MltInput"; }
+       Effect::AlphaHandling alpha_handling() const;
+       std::string output_fragment_shader();
+       void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
+
+       // Input ovverrides
+       void finalize();
+       bool can_output_linear_gamma() const;
+       unsigned get_width() const { return m_width; }
+       unsigned get_height() const { return m_height; }
+       Colorspace get_color_space() const;
+       GammaCurve get_gamma_curve() const;
+
+       // Custom methods
+       void useFlatInput(EffectChain* chain, MovitPixelFormat pix_fmt, unsigned width, unsigned height);
+       void useYCbCrInput(EffectChain* chain, const ImageFormat& image_format, const YCbCrFormat& ycbcr_format, unsigned width, unsigned height);
+       void useFBOInput(EffectChain* chain, GLuint texture);
+       void set_pixel_data(const unsigned char* data);
+
+private:
+       unsigned m_width, m_height;
+       int output_linear_gamma, needs_mipmaps;
+       Input *input;
+       bool isRGB;
+       YCbCrFormat m_ycbcr_format;
+};
+
+#endif // MLT_MOVIT_INPUT_H
diff --git a/src/modules/opengl/transition_movit_mix.cpp b/src/modules/opengl/transition_movit_mix.cpp
new file mode 100644 (file)
index 0000000..176798a
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * transition_movit_mix.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/init.h>
+#include <movit/effect_chain.h>
+#include <movit/util.h>
+#include <movit/mix_effect.h>
+#include "mlt_movit_input.h"
+#include "mlt_flip_effect.h"
+
+static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       int error = 0;
+
+       // Get the b frame from the stack
+       mlt_frame b_frame = (mlt_frame) mlt_frame_pop_frame( a_frame );
+
+       // Get the transition object
+       mlt_transition transition = (mlt_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 movit objects
+       mlt_service service = MLT_TRANSITION_SERVICE( transition );
+       mlt_service_lock( service );
+       EffectChain* chain = GlslManager::get_chain( service );
+       Effect* effect = (Effect*) mlt_properties_get_data( properties, "movit effect", NULL );
+       MltInput* a_input = GlslManager::get_input( service );
+       MltInput* b_input = (MltInput*) mlt_properties_get_data( properties, "movit input B", NULL );
+       mlt_image_format output_format = *format;
+
+       if ( !chain || !a_input ) {
+               mlt_service_unlock( service );
+               return 2;
+       }
+
+       // Get the transition parameters
+       int reverse = mlt_properties_get_int( properties, "reverse" );
+       double mix = mlt_properties_get( properties, "mix" ) ?
+               mlt_properties_get_double( properties, "mix" ) :
+               mlt_transition_get_progress( transition, a_frame );
+       double inverse = 1.0 - mix;
+
+       // Set the movit parameters
+       bool ok = effect->set_float( "strength_first",  reverse ? mix : inverse );
+       ok     |= effect->set_float( "strength_second", reverse ? inverse : mix );
+       assert( ok );
+
+       // Get the frames' textures
+       GLuint* texture_id[2] = {0, 0};
+       *format = mlt_image_glsl_texture;
+       mlt_frame_get_image( a_frame, (uint8_t**) &texture_id[0], format, width, height, 0 );
+       a_input->useFBOInput( chain, *texture_id[0] );
+       *format = mlt_image_glsl_texture;
+       mlt_frame_get_image( b_frame, (uint8_t**) &texture_id[1], format, width, height, 0 );
+       b_input->useFBOInput( chain, *texture_id[1] );
+
+       // Set resolution to that of the a_frame
+       *width = mlt_properties_get_int( a_props, "width" );
+       *height = mlt_properties_get_int( a_props, "height" );
+
+       // Setup rendering to an FBO
+       GlslManager* glsl = GlslManager::get_instance();
+       glsl_fbo fbo = glsl->get_fbo( *width, *height );
+       if ( output_format == mlt_image_glsl_texture ) {
+               glsl_texture texture = glsl->get_texture( *width, *height, GL_RGBA );
+
+               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+               check_error();
+               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+               check_error();
+               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+               check_error();
+
+               GlslManager::render( service, chain, fbo->fbo, *width, *height );
+
+               glFinish();
+               check_error();
+               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+               check_error();
+
+               *image = (uint8_t*) &texture->texture;
+               mlt_frame_set_image( a_frame, *image, 0, NULL );
+               mlt_properties_set_data( properties, "movit.convert", texture, 0,
+                       (mlt_destructor) GlslManager::release_texture, NULL );
+               *format = output_format;
+       }
+       else {
+               // Use a PBO to hold the data we read back with glReadPixels()
+               // (Intel/DRI goes into a slow path if we don't read to PBO)
+               GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
+                       GL_RGBA : GL_RGB;
+               int img_size = *width * *height * ( gl_format == GL_RGB? 3 : 4 );
+               glsl_pbo pbo = glsl->get_pbo( img_size );
+               glsl_texture texture = glsl->get_texture( *width, *height, gl_format );
+
+               if ( fbo && pbo && texture ) {
+                       // Set the FBO
+                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+                       check_error();
+                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+
+                       GlslManager::render( service, chain, fbo->fbo, *width, *height );
+
+                       // Read FBO into PBO
+                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
+                       check_error();
+                       glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
+                       check_error();
+                       glReadPixels( 0, 0, *width, *height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
+                       check_error();
+
+                       // Copy from PBO
+                       uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
+                       check_error();
+
+                       *format = gl_format == GL_RGBA ? mlt_image_rgb24a : mlt_image_rgb24;
+                       *image = (uint8_t*) mlt_pool_alloc( img_size );
+                       mlt_frame_set_image( a_frame, *image, img_size, mlt_pool_release );
+                       memcpy( *image, buf, img_size );
+
+                       // Release PBO and FBO
+                       glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
+                       check_error();
+                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+                       glBindTexture( GL_TEXTURE_2D, 0 );
+                       check_error();
+                       GlslManager::release_texture( texture );
+               }
+               else {
+                       error = 1;
+               }
+       }
+       if ( fbo ) GlslManager::release_fbo( fbo );
+       mlt_service_unlock( service );
+
+       return error;
+}
+
+static mlt_frame process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
+{
+       mlt_service service = MLT_TRANSITION_SERVICE(transition);
+
+       if ( !GlslManager::init_chain( service ) ) {
+               // Create the Movit effect chain
+               EffectChain* chain = GlslManager::get_chain( service );
+               mlt_profile profile = mlt_service_profile( service );
+               Input* b_input = new MltInput( profile->width, profile->height );
+               ImageFormat output_format;
+               output_format.color_space = COLORSPACE_sRGB;
+               output_format.gamma_curve = GAMMA_sRGB;
+               chain->add_input( b_input );
+               chain->add_output( output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED );
+               chain->set_dither_bits( 8 );
+
+               Effect* effect = chain->add_effect( new MixEffect(),
+                       GlslManager::get_input( service ), b_input );
+
+               // Save these new effects on properties for get_image
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES(transition);
+               mlt_properties_set_data( properties, "movit effect", effect, 0, NULL, NULL );
+               mlt_properties_set_data( properties, "movit input B", b_input, 0, NULL, NULL );
+       }
+
+       // 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, get_image );
+
+       return a_frame;
+}
+
+extern "C"
+mlt_transition transition_movit_mix_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_transition transition = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+       if ( glsl && ( transition = mlt_transition_new() ) ) {
+               transition->process = process;
+               mlt_properties_set( MLT_TRANSITION_PROPERTIES( transition ), "mix", arg );
+               
+               // Inform apps and framework that this is a video only transition
+               mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 );
+       }
+       return transition;
+}
diff --git a/src/modules/opengl/transition_movit_mix.yml b/src/modules/opengl/transition_movit_mix.yml
new file mode 100644 (file)
index 0000000..f814850
--- /dev/null
@@ -0,0 +1,35 @@
+schema_version: 0.1
+type: transition
+identifier: movit.mix
+title: Dissolve (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: A simple video cross-fade or mixing effect.
+
+parameters:
+  - identifier: argument
+    title: Mix Level
+    description: Performs a dissolve if a mix level is not supplied.
+    type: float
+    minimum: 0
+    maximum: 1
+
+  - identifier: mix
+    title: Mix Level
+    description: Performs a dissolve if a mix level is not supplied.
+    type: float
+    minimum: 0
+    maximum: 1
+
+  - identifier: reverse
+    title: Reverse
+    type: integer
+    mutable: yes
+    description: >
+      Reverse the direction of the transition.
+    default: 0
diff --git a/src/modules/opengl/transition_movit_overlay.cpp b/src/modules/opengl/transition_movit_overlay.cpp
new file mode 100644 (file)
index 0000000..a877514
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * transition_movit_overlay.cpp
+ * Copyright (C) 2013 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 <string.h>
+#include <assert.h>
+
+#include "glsl_manager.h"
+#include <movit/init.h>
+#include <movit/effect_chain.h>
+#include <movit/util.h>
+#include <movit/overlay_effect.h>
+#include "mlt_movit_input.h"
+#include "mlt_flip_effect.h"
+
+static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       int error = 0;
+
+       // Get the b frame from the stack
+       mlt_frame b_frame = (mlt_frame) mlt_frame_pop_frame( a_frame );
+
+       // Get the transition object
+       mlt_transition transition = (mlt_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 movit objects
+       mlt_service service = MLT_TRANSITION_SERVICE( transition );
+       mlt_service_lock( service );
+       EffectChain* chain = GlslManager::get_chain( service );
+       MltInput* a_input = GlslManager::get_input( service );
+       MltInput* b_input = (MltInput*) mlt_properties_get_data( properties, "movit input B", NULL );
+       mlt_image_format output_format = *format;
+
+       if ( !chain || !a_input ) {
+               mlt_service_unlock( service );
+               return 2;
+       }
+
+       // Get the frames' textures
+       GLuint* texture_id[2] = {0, 0};
+       *format = mlt_image_glsl_texture;
+       mlt_frame_get_image( a_frame, (uint8_t**) &texture_id[0], format, width, height, 0 );
+       a_input->useFBOInput( chain, *texture_id[0] );
+       *format = mlt_image_glsl_texture;
+       mlt_frame_get_image( b_frame, (uint8_t**) &texture_id[1], format, width, height, 0 );
+       b_input->useFBOInput( chain, *texture_id[1] );
+
+       // Set resolution to that of the a_frame
+       *width = mlt_properties_get_int( a_props, "width" );
+       *height = mlt_properties_get_int( a_props, "height" );
+
+       // Setup rendering to an FBO
+       GlslManager* glsl = GlslManager::get_instance();
+       glsl_fbo fbo = glsl->get_fbo( *width, *height );
+       if ( output_format == mlt_image_glsl_texture ) {
+               glsl_texture texture = glsl->get_texture( *width, *height, GL_RGBA );
+
+               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+               check_error();
+               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+               check_error();
+               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+               check_error();
+
+               GlslManager::render( service, chain, fbo->fbo, *width, *height );
+
+               glFinish();
+               check_error();
+               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+               check_error();
+
+               *image = (uint8_t*) &texture->texture;
+               mlt_frame_set_image( a_frame, *image, 0, NULL );
+               mlt_properties_set_data( properties, "movit.convert", texture, 0,
+                       (mlt_destructor) GlslManager::release_texture, NULL );
+               *format = output_format;
+       }
+       else {
+               // Use a PBO to hold the data we read back with glReadPixels()
+               // (Intel/DRI goes into a slow path if we don't read to PBO)
+               GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
+                       GL_RGBA : GL_RGB;
+               int img_size = *width * *height * ( gl_format == GL_RGB? 3 : 4 );
+               glsl_pbo pbo = glsl->get_pbo( img_size );
+               glsl_texture texture = glsl->get_texture( *width, *height, gl_format );
+
+               if ( fbo && pbo && texture ) {
+                       // Set the FBO
+                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+                       check_error();
+                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+
+                       GlslManager::render( service, chain, fbo->fbo, *width, *height );
+
+                       // Read FBO into PBO
+                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
+                       check_error();
+                       glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
+                       check_error();
+                       glReadPixels( 0, 0, *width, *height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
+                       check_error();
+
+                       // Copy from PBO
+                       uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
+                       check_error();
+
+                       *format = gl_format == GL_RGBA ? mlt_image_rgb24a : mlt_image_rgb24;
+                       *image = (uint8_t*) mlt_pool_alloc( img_size );
+                       mlt_frame_set_image( a_frame, *image, img_size, mlt_pool_release );
+                       memcpy( *image, buf, img_size );
+
+                       // Release PBO and FBO
+                       glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
+                       check_error();
+                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
+                       check_error();
+                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+                       check_error();
+                       glBindTexture( GL_TEXTURE_2D, 0 );
+                       check_error();
+                       GlslManager::release_texture( texture );
+               }
+               else {
+                       error = 1;
+               }
+       }
+       if ( fbo ) GlslManager::release_fbo( fbo );
+       mlt_service_lock( service );
+
+       return error;
+}
+
+static mlt_frame process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
+{
+       mlt_service service = MLT_TRANSITION_SERVICE(transition);
+
+       if ( !GlslManager::init_chain( service ) ) {
+               // Create the Movit effect chain
+               EffectChain* chain = GlslManager::get_chain( service );
+               mlt_profile profile = mlt_service_profile( service );
+               Input* b_input = new MltInput( profile->width, profile->height );
+               ImageFormat output_format;
+               output_format.color_space = COLORSPACE_sRGB;
+               output_format.gamma_curve = GAMMA_sRGB;
+               chain->add_input( b_input );
+               chain->add_output( output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED );
+               chain->set_dither_bits( 8 );
+
+               Effect* effect = chain->add_effect( new OverlayEffect(),
+                       GlslManager::get_input( service ), b_input );
+
+               // Save these new input on properties for get_image
+               mlt_properties_set_data( MLT_TRANSITION_PROPERTIES(transition),
+                       "movit input B", b_input, 0, NULL, NULL );
+       }
+
+       // 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, get_image );
+
+       return a_frame;
+}
+
+extern "C"
+mlt_transition transition_movit_overlay_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_transition transition = NULL;
+       GlslManager* glsl = GlslManager::get_instance();
+       if ( glsl && ( transition = mlt_transition_new() ) ) {
+               transition->process = process;
+               
+               // Inform apps and framework that this is a video only transition
+               mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "_transition_type", 1 );
+       }
+       return transition;
+}
diff --git a/src/modules/opengl/transition_movit_overlay.yml b/src/modules/opengl/transition_movit_overlay.yml
new file mode 100644 (file)
index 0000000..0ae18b2
--- /dev/null
@@ -0,0 +1,13 @@
+schema_version: 0.1
+type: transition
+identifier: movit.overlay
+title: Dissolve (GLSL)
+version: 1
+copyright: Dan Dennedy
+creator: Steinar H. Gunderson
+license: GPLv2
+language: en
+tags:
+  - Video
+description: >
+  A simple video overlay or alpha-compositing effect using the Porter-Duff over operation.
index 6a796075c79ccc2ae99c9a20fc22a3e5f2f22ca1..62019da8d75fa1bc198b0e4771be24c420794e71 100644 (file)
@@ -30,9 +30,9 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/plus"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/plus"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/plus"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/plus"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 0b55ff0464404ff39ccc6767150ba6d9449686a1..35f1ce52d94f504c967905376b00a8cad98cd60a 100644 (file)
@@ -48,20 +48,21 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                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;
+               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
 
                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, NULL, 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 ( transition )
+                               mlt_properties_set_int( MLT_TRANSITION_PROPERTIES( transition ), "b_alpha", 1 );
                }
 
                if ( producer != NULL && transition != NULL )
@@ -70,7 +71,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                        mlt_properties frame_properties = MLT_FRAME_PROPERTIES( this );
                        mlt_position in = mlt_filter_get_in( filter );
                        mlt_position out = mlt_filter_get_out( filter );
-                       double consumer_ar = mlt_properties_get_double( frame_properties, "consumer_aspect_ratio" );
+                       double consumer_ar = mlt_profile_sar( profile );
                        mlt_transition_set_in_and_out( transition, in, out );
                        if ( out > 0 ) {
                                mlt_properties_set_position( MLT_PRODUCER_PROPERTIES( producer ), "length", out - in + 1 );
@@ -85,21 +86,21 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 //                     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 );
+                       if ( mlt_frame_get_aspect_ratio( this ) == 0 )
+                               mlt_frame_set_aspect_ratio( this, consumer_ar );
+                       if ( mlt_frame_get_aspect_ratio( a_frame ) == 0 )
+                               mlt_frame_set_aspect_ratio( a_frame, consumer_ar );
 
                        // Add the affine transition onto the frame stack
                        mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
                        mlt_transition_process( transition, a_frame, this );
 
-                       if (mlt_properties_get_int( properties, "use_normalised" ))
+                       if ( mlt_properties_get_int( properties, "use_normalised" ) )
                        {
-                               // Use the normalised width & height from the a_frame
-                               *width = mlt_properties_get_int( MLT_FRAME_PROPERTIES( a_frame ), "normalised_width" );
-                               *height = mlt_properties_get_int( MLT_FRAME_PROPERTIES( a_frame ), "normalised_height" );
+                               // Use the normalised width & height
+                               mlt_profile profile = mlt_service_profile( MLT_FILTER_SERVICE( filter ) );
+                               *width = profile->width;
+                               *height = profile->height;
                        }
                        
                        mlt_frame_get_image( a_frame, image, format, width, height, writable );
@@ -137,7 +138,7 @@ mlt_filter filter_affine_init( mlt_profile profile, mlt_service_type type, const
        if ( this != NULL )
        {
                this->process = filter_process;
-               mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "background", arg ? arg : "colour:black" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "background", arg ? arg : "colour:0" );
        }
        return this;
 }
index 39e626dffd34c6b0aaf7c1242fd31fca86f36f2d..b223db974b41242b895972bce8890331f57cf4a3 100644 (file)
 
 //--------------------------------------------------------
 //pointer to an interpolating function
-typedef int (*interpp)(unsigned char*, int, int, float, float, float, unsigned char*);
-
-//************************************
-//REMAP AN IMAGE
-
-//--------------------------------------------------------
-//  vhs = vhodna slika velikosti wi x hi
-//  izs = izhodna slika velikosti wo x ho
-//  map = za vsak pixel izs pove, kje ga vzamemo is vhs
-//  bgc = background color
-//  interp = kazalec na interpolacijsko funkcijo
-void remap(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *izs, float *map, unsigned char bgc, interpp interp)
-{
-       int i,j;
-       float x,y;
-
-       for (i=0;i<ho;i++)
-               for (j=0;j<wo;j++)
-               {
-               x=map[2*(wo*i+j)];
-               y=map[2*(wo*i+j)+1];
-               if (x>0)
-                       interp(vhs,wi,hi,x,y,1.0,&izs[wo*i+j]);
-               else
-                       izs[wo*i+j]=bgc;        //background fill
-       }
-}
-
-
-//--------------------------------------------------------
-//for four byte (int, 32 bit) values    (packed RGB color)
-//little endian !!
-//  vhs = vhodna slika velikosti wi x hi
-//  izs = izhodna slika velikosti wo x ho
-//  map = za vsak pixel izs pove, kje ga vzamemo is vhs
-//  bgc = background color
-//  interp = kazalec na interpolacijsko funkcijo
-void remap32(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *izs, float *map, uint32_t bgc, interpp interp)
-{
-       int i,j;
-       float x,y;
-
-       for (i=0;i<ho;i++)
-               for (j=0;j<wo;j++)
-               {
-               x=map[2*(wo*i+j)];
-               y=map[2*(wo*i+j)+1];
-               if (x>0)
-                       interp(vhs,wi,hi,x,y,1.0,&izs[4*(wo*i+j)]);
-               else    //background fill
-               {
-                       izs[4*(wo*i+j)]=bgc;
-                       izs[4*(wo*i+j)+1]=bgc>>8;
-                       izs[4*(wo*i+j)+2]=bgc>>16;
-                       izs[4*(wo*i+j)+3]=bgc>>24;
-               }
-       }
-}
+//parameters:
+//  source image
+//  source width
+//  source height
+//  X coordinate
+//  Y coordinate
+//  opacity
+//  destination image
+//  flag to overwrite alpha channel
+typedef int (*interpp)(unsigned char*, int, int, float, float, float, unsigned char*, int);
 
 //**************************************
 //HERE BEGIN THE INTERPOLATION FUNCTIONS
@@ -119,7 +71,7 @@ void remap32(int wi, int hi, int wo, int ho, unsigned char *vhs, unsigned char *
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        //printf("u=%5.2f v=%5.2f   ",x,y);
        printf("u=%5.3f v=%5.3f     ",x/(w-1),y/(h-1));
@@ -141,7 +93,7 @@ int interpNNpr_b(unsigned char *sl, int w, int h, float x, float y, float o, uns
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpNN_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpNN_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
 #ifdef TEST_XY_LIMITS
        if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
@@ -160,16 +112,17 @@ int interpNN_b(unsigned char *sl, int w, int h, float x, float y, float o, unsig
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
 #ifdef TEST_XY_LIMITS
        if ((x<0)||(x>=(w-1))||(y<0)||(y>=(h-1))) return -1;
 #endif
-       v[3]= sl[(int)rintf(x)*4+(int)rintf(y)*4*w+3];
-       float alpha = (float) v[3] / 255.0 * o;
-       v[0]= v[0] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w] * alpha;
-       v[1]= v[1] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w+1] * alpha;
-       v[2]= v[2] * (1.0 - alpha) + sl[(int)rintf(x)*4+(int)rintf(y)*4*w+2] * alpha;
+       int p = (int) rintf(x) * 4 + (int) rintf(y) * 4 * w;
+       float alpha = (float) sl[p + 3] / 255.0 * o;
+       v[0]= v[0] * (1.0 - alpha) + sl[p] * alpha;
+       v[1]= v[1] * (1.0 - alpha) + sl[p + 1] * alpha;
+       v[2]= v[2] * (1.0 - alpha) + sl[p + 2] * alpha;
+       if (is_alpha) v[3] = sl[p +3];
 
        return 0;
 }
@@ -182,7 +135,7 @@ int interpNN_b32(unsigned char *sl, int w, int h, float x, float y, float o, uns
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpBL_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBL_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int m,n,k,l;
        float a,b;
@@ -202,7 +155,7 @@ int interpBL_b(unsigned char *sl, int w, int h, float x, float y, float o, unsig
 //------------------------------------------------------
 //bilinearna interpolacija
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
-int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int m,n,k,l,n1,l1,k1;
        float a,b;
@@ -218,8 +171,9 @@ int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, float o, uns
 
        a=sl[k+3]+(sl[k1+3]-sl[k+3])*(x-(float)m);
        b=sl[l+3]+(sl[l1+3]-sl[n1+3])*(x-(float)m);
-       v[3]=a+(b-a)*(y-(float)n);
-       float alpha = (float) v[3] / 255.0 * o;
+       float alpha = a+(b-a)*(y-(float)n);
+       if (is_alpha) v[3] = alpha;
+       alpha = alpha / 255.0 * o;
 
        a=sl[k]+(sl[k1]-sl[k])*(x-(float)m);
        b=sl[l]+(sl[l1]-sl[n1])*(x-(float)m);
@@ -245,7 +199,7 @@ int interpBL_b32(unsigned char *sl, int w, int h, float x, float y, float o, uns
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpBC_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBC_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,l,m,n;
        float k;
@@ -294,7 +248,7 @@ int interpBC_b(unsigned char *sl, int w, int h, float x, float y, float o, unsig
 //------------------------------------------------------
 //bikubicna interpolacija  "smooth"
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
-int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,b,l,m,n;
        float k;
@@ -337,10 +291,14 @@ int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, float o, uns
                                p[i]=p[i]+(x-i-m)/j*(p[i]-p[i-1]);
 
                if (p[3]<0.0) p[3]=0.0;
-               if (p[3]>256.0) p[3]=255.0;
+               if (p[3]>255.0) p[3]=255.0;
 
-               v[b]= v[b] * (1.0 - alpha) + p[3] * alpha;
-               if (b == 3) alpha = v[b] / 255.0 * o;
+               if (b == 3) {
+                       alpha = p[3] / 255.0 * o;
+                       if (is_alpha) v[3] = p[3];
+               } else {
+                       v[b] = v[b] * (1.0 - alpha) + p[3] * alpha;
+               }
        }
 
        return 0;
@@ -357,7 +315,7 @@ int interpBC_b32(unsigned char *sl, int w, int h, float x, float y, float o, uns
 //     *v interpolirana vrednost
 //!!! ODKOD SUM???  (ze po eni rotaciji v interp_test !!)
 //!!! v defish tega suma ni???
-int interpBC2_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBC2_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,k,l,m,n;
        float pp,p[4],wx[4],wy[4],xx;
@@ -409,7 +367,7 @@ int interpBC2_b(unsigned char *sl, int w, int h, float x, float y, float o, unsi
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
 //!!! ODKOD SUM???  (ze po eni rotaciji v interp_test !!)
 //!!! v defish tega suma ni???
-int interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int b,i,k,l,m,n,u;
        float pp,p[4],wx[4],wy[4],xx;
@@ -469,7 +427,7 @@ int interpBC2_b32(unsigned char *sl, int w, int h, float x, float y, float o, un
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,m,n;
        float pp,p[4],wx[4],wy[4],xx;
@@ -515,7 +473,7 @@ int interpSP4_b(unsigned char *sl, int w, int h, float x, float y, float o, unsi
 //------------------------------------------------------
 //spline 4x4 interpolacija
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
-int interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,m,n,b;
        float pp,p[4],wx[4],wy[4],xx;
@@ -573,7 +531,7 @@ int interpSP4_b32(unsigned char *sl, int w, int h, float x, float y, float o, un
 //     *v interpolirana vrednost
 //!!! PAZI, TOLE NE DELA CISTO PRAV ???   belina se siri
 //!!! zaenkrat sem dodal fudge factor...
-int interpSP6_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSP6_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,m,n;
        float pp,p[6],wx[6],wy[6],xx;
@@ -639,7 +597,7 @@ int interpSP6_b(unsigned char *sl, int w, int h, float x, float y, float o, unsi
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
 //!!! PAZI, TOLE NE DELA CISTO PRAV ???   belina se siri
 //!!! zaenkrat sem dodal fudge factor...
-int interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,b,j,m,n;
        float pp,p[6],wx[6],wy[6],xx;
@@ -712,7 +670,7 @@ int interpSP6_b32(unsigned char *sl, int w, int h, float x, float y, float o, un
 //     x,y tocka, za katero izracuna interpolirano vrednost
 //  o opacity
 //     *v interpolirana vrednost
-int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,m,n;
        float pp,p[16],wx[16],wy[16],xx,xxx,x1;
@@ -771,7 +729,7 @@ int interpSC16_b(unsigned char *sl, int w, int h, float x, float y, float o, uns
 //------------------------------------------------------
 //truncated sinc "lanczos" 16x16 interpolacija
 //za byte (char) vrednosti  v packed color 32 bitnem formatu
-int interpSC16_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v)
+int interpSC16_b32(unsigned char *sl, int w, int h, float x, float y, float o, unsigned char *v, int is_alpha)
 {
        int i,j,m,b,n;
        float pp,p[16],wx[16],wy[16],xx,xxx,x1;
index 1fa9cf3199a4cf95d1abcf5e14941a616ac0ab7f..86751a91b38c6496f3cf0572d91214b2f7622866 100644 (file)
@@ -33,9 +33,9 @@
 /** Calculate real geometry.
 */
 
-static void geometry_calculate( mlt_transition this, const char *store, struct mlt_geometry_item_s *output, float position )
+static void geometry_calculate( mlt_transition transition, const char *store, struct mlt_geometry_item_s *output, float position )
 {
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
        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" );
@@ -55,16 +55,16 @@ static void geometry_calculate( mlt_transition this, const char *store, struct m
 }
 
 
-static mlt_geometry transition_parse_keys( mlt_transition this, const char *name, const char *store, int normalised_width, int normalised_height )
+static mlt_geometry transition_parse_keys( mlt_transition transition, 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 );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
 
        // Try to fetch it first
        mlt_geometry geometry = mlt_properties_get_data( properties, store, NULL );
 
        // Determine length and obtain cycle
-       mlt_position length = mlt_transition_get_length( this );
+       mlt_position length = mlt_transition_get_length( transition );
        double cycle = mlt_properties_get_double( properties, "cycle" );
 
        // Allow a geometry repeat cycle
@@ -96,27 +96,27 @@ static mlt_geometry transition_parse_keys( mlt_transition this, const char *name
        return geometry;
 }
 
-static mlt_geometry composite_calculate( mlt_transition this, struct mlt_geometry_item_s *result, int nw, int nh, float position )
+static mlt_geometry composite_calculate( mlt_transition transition, 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 );
+       mlt_geometry start = transition_parse_keys( transition, "geometry", "geometries", nw, nh );
 
        // Do the calculation
-       geometry_calculate( this, "geometries", result, position );
+       geometry_calculate( transition, "geometries", result, position );
 
        return start;
 }
 
-static inline float composite_calculate_key( mlt_transition this, const char *name, const char *store, int norm, float position )
+static inline float composite_calculate_key( mlt_transition transition, 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 );
+       transition_parse_keys( transition, name, store, norm, 0 );
 
        // Do the calculation
-       geometry_calculate( this, store, &result, position );
+       geometry_calculate( transition, store, &result, position );
 
        return result.x;
 }
@@ -127,21 +127,21 @@ typedef struct
 }
 affine_t;
 
-static void affine_init( float this[3][3] )
+static void affine_init( float affine[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;
+       affine[0][0] = 1;
+       affine[0][1] = 0;
+       affine[0][2] = 0;
+       affine[1][0] = 0;
+       affine[1][1] = 1;
+       affine[1][2] = 0;
+       affine[2][0] = 0;
+       affine[2][1] = 0;
+       affine[2][2] = 1;
 }
 
 // Multiply two this affine transform with that
-static void affine_multiply( float this[3][3], float that[3][3] )
+static void affine_multiply( float affine[3][3], float matrix[3][3] )
 {
        float output[3][3];
        int i;
@@ -149,132 +149,132 @@ static void affine_multiply( float this[3][3], float that[3][3] )
 
        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];
+                       output[i][j] = affine[i][0] * matrix[j][0] + affine[i][1] * matrix[j][1] + affine[i][2] * matrix[j][2];
+
+       affine[0][0] = output[0][0];
+       affine[0][1] = output[0][1];
+       affine[0][2] = output[0][2];
+       affine[1][0] = output[1][0];
+       affine[1][1] = output[1][1];
+       affine[1][2] = output[1][2];
+       affine[2][0] = output[2][0];
+       affine[2][1] = output[2][1];
+       affine[2][2] = output[2][2];
 }
 
 // Rotate by a given angle
-static void affine_rotate_x( float this[3][3], float angle )
+static void affine_rotate_x( float affine[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 );
+       float matrix[3][3];
+       matrix[0][0] = cos( angle * M_PI / 180 );
+       matrix[0][1] = 0 - sin( angle * M_PI / 180 );
+       matrix[0][2] = 0;
+       matrix[1][0] = sin( angle * M_PI / 180 );
+       matrix[1][1] = cos( angle * M_PI / 180 );
+       matrix[1][2] = 0;
+       matrix[2][0] = 0;
+       matrix[2][1] = 0;
+       matrix[2][2] = 1;
+       affine_multiply( affine, matrix );
 }
 
-static void affine_rotate_y( float this[3][3], float angle )
+static void affine_rotate_y( float affine[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 );
+       float matrix[3][3];
+       matrix[0][0] = cos( angle * M_PI / 180 );
+       matrix[0][1] = 0;
+       matrix[0][2] = 0 - sin( angle * M_PI / 180 );
+       matrix[1][0] = 0;
+       matrix[1][1] = 1;
+       matrix[1][2] = 0;
+       matrix[2][0] = sin( angle * M_PI / 180 );
+       matrix[2][1] = 0;
+       matrix[2][2] = cos( angle * M_PI / 180 );
+       affine_multiply( affine, matrix );
 }
 
-static void affine_rotate_z( float this[3][3], float angle )
+static void affine_rotate_z( float affine[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 );
+       float matrix[3][3];
+       matrix[0][0] = 1;
+       matrix[0][1] = 0;
+       matrix[0][2] = 0;
+       matrix[1][0] = 0;
+       matrix[1][1] = cos( angle * M_PI / 180 );
+       matrix[1][2] = sin( angle * M_PI / 180 );
+       matrix[2][0] = 0;
+       matrix[2][1] = - sin( angle * M_PI / 180 );
+       matrix[2][2] = cos( angle * M_PI / 180 );
+       affine_multiply( affine, matrix );
 }
 
-static void affine_scale( float this[3][3], float sx, float sy )
+static void affine_scale( float affine[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 );
+       float matrix[3][3];
+       matrix[0][0] = sx;
+       matrix[0][1] = 0;
+       matrix[0][2] = 0;
+       matrix[1][0] = 0;
+       matrix[1][1] = sy;
+       matrix[1][2] = 0;
+       matrix[2][0] = 0;
+       matrix[2][1] = 0;
+       matrix[2][2] = 1;
+       affine_multiply( affine, matrix );
 }
 
 // Shear by a given value
-static void affine_shear( float this[3][3], float shear_x, float shear_y, float shear_z )
+static void affine_shear( float affine[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 );
+       float matrix[3][3];
+       matrix[0][0] = 1;
+       matrix[0][1] = tan( shear_x * M_PI / 180 );
+       matrix[0][2] = 0;
+       matrix[1][0] = tan( shear_y * M_PI / 180 );
+       matrix[1][1] = 1;
+       matrix[1][2] = tan( shear_z * M_PI / 180 );
+       matrix[2][0] = 0;
+       matrix[2][1] = 0;
+       matrix[2][2] = 1;
+       affine_multiply( affine, matrix );
 }
 
-static void affine_offset( float this[3][3], float x, float y )
+static void affine_offset( float affine[3][3], float x, float y )
 {
-       this[0][2] += x;
-       this[1][2] += y;
+       affine[0][2] += x;
+       affine[1][2] += y;
 }
 
 // Obtain the mapped x coordinate of the input
-static inline double MapX( float this[3][3], float x, float y )
+static inline double MapX( float affine[3][3], float x, float y )
 {
-       return this[0][0] * x + this[0][1] * y + this[0][2];
+       return affine[0][0] * x + affine[0][1] * y + affine[0][2];
 }
 
 // Obtain the mapped y coordinate of the input
-static inline double MapY( float this[3][3], float x, float y )
+static inline double MapY( float affine[3][3], float x, float y )
 {
-       return this[1][0] * x + this[1][1] * y + this[1][2];
+       return affine[1][0] * x + affine[1][1] * y + affine[1][2];
 }
 
-static inline double MapZ( float this[3][3], float x, float y )
+static inline double MapZ( float affine[3][3], float x, float y )
 {
-       return this[2][0] * x + this[2][1] * y + this[2][2];
+       return affine[2][0] * x + affine[2][1] * y + affine[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, float max_width, float max_height )
+static void affine_max_output( float affine[3][3], float *w, float *h, float dz, float max_width, float max_height )
 {
-       int tlx = MapX( this, -max_width,  max_height ) / dz;
-       int tly = MapY( this, -max_width,  max_height ) / dz;
-       int trx = MapX( this,  max_width,  max_height ) / dz;
-       int try = MapY( this,  max_width,  max_height ) / dz;
-       int blx = MapX( this, -max_width, -max_height ) / dz;
-       int bly = MapY( this, -max_width, -max_height ) / dz;
-       int brx = MapX( this,  max_width, -max_height ) / dz;
-       int bry = MapY( this,  max_width, -max_height ) / dz;
+       int tlx = MapX( affine, -max_width,  max_height ) / dz;
+       int tly = MapY( affine, -max_width,  max_height ) / dz;
+       int trx = MapX( affine,  max_width,  max_height ) / dz;
+       int try = MapY( affine,  max_width,  max_height ) / dz;
+       int blx = MapX( affine, -max_width, -max_height ) / dz;
+       int bly = MapY( affine, -max_width, -max_height ) / dz;
+       int brx = MapX( affine,  max_width, -max_height ) / dz;
+       int bry = MapY( affine,  max_width, -max_height ) / dz;
 
        int max_x;
        int max_y;
@@ -303,9 +303,9 @@ static void affine_max_output( float this[3][3], float *w, float *h, float dz, f
 
 #define IN_RANGE( v, r )       ( v >= - r / 2 && v < r / 2 )
 
-static inline void get_affine( affine_t *affine, mlt_transition this, float position )
+static inline void get_affine( affine_t *affine, mlt_transition transition, float position )
 {
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
        int keyed = mlt_properties_get_int( properties, "keyed" );
 
        if ( keyed == 0 )
@@ -336,14 +336,14 @@ static inline void get_affine( affine_t *affine, mlt_transition this, float posi
        }
        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 );
-               float o_x = composite_calculate_key( this, "ox", "ox_info", 0, position );
-               float o_y = composite_calculate_key( this, "oy", "oy_info", 0, position );
+               float rotate_x = composite_calculate_key( transition, "rotate_x", "rotate_x_info", 360, position );
+               float rotate_y = composite_calculate_key( transition, "rotate_y", "rotate_y_info", 360, position );
+               float rotate_z = composite_calculate_key( transition, "rotate_z", "rotate_z_info", 360, position );
+               float shear_x = composite_calculate_key( transition, "shear_x", "shear_x_info", 360, position );
+               float shear_y = composite_calculate_key( transition, "shear_y", "shear_y_info", 360, position );
+               float shear_z = composite_calculate_key( transition, "shear_z", "shear_z_info", 360, position );
+               float o_x = composite_calculate_key( transition, "ox", "ox_info", 0, position );
+               float o_y = composite_calculate_key( transition, "oy", "oy_info", 0, position );
                
                affine_rotate_x( affine->matrix, rotate_x );
                affine_rotate_y( affine->matrix, rotate_y );
@@ -362,10 +362,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
 
        // Get the transition object
-       mlt_transition this = mlt_frame_pop_service( a_frame );
+       mlt_transition transition = mlt_frame_pop_service( a_frame );
 
        // Get the properties of the transition
-       mlt_properties properties = MLT_TRANSITION_PROPERTIES( this );
+       mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
 
        // Get the properties of the a frame
        mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame );
@@ -380,10 +380,10 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        int b_height;
 
        // Assign the current position
-       mlt_position position =  mlt_transition_get_position( this, a_frame );
+       mlt_position position =  mlt_transition_get_position( transition, a_frame );
 
        int mirror = mlt_properties_get_position( properties, "mirror" );
-       int length = mlt_transition_get_length( this );
+       int length = mlt_transition_get_length( transition );
        if ( mlt_properties_get_int( properties, "always_active" ) )
        {
                mlt_properties props = mlt_properties_get_data( b_props, "_producer", NULL );
@@ -393,10 +393,11 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        }
 
        // 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" );
+       mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) );
+       int normalised_width = profile->width;
+       int normalised_height = profile->height;
 
-       double consumer_ar = mlt_properties_get_double( a_props, "consumer_aspect_ratio" );
+       double consumer_ar = mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(transition) ) );
 
        // Structures for geometry
        struct mlt_geometry_item_s result;
@@ -409,9 +410,9 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        mlt_frame_get_image( a_frame, image, format, width, height, 1 );
 
        // Calculate the region now
-       mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
-       composite_calculate( this, &result, normalised_width, normalised_height, ( float )position );
-       mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
+       mlt_service_lock( MLT_TRANSITION_SERVICE( transition ) );
+       composite_calculate( transition, &result, normalised_width, normalised_height, ( float )position );
+       mlt_service_unlock( MLT_TRANSITION_SERVICE( transition ) );
 
        // Fetch the b frame image
        result.w = ( result.w * *width / normalised_width );
@@ -420,8 +421,8 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
        result.y = ( result.y * *height / normalised_height );
 
        // Request full resolution of b frame image.
-       b_width = mlt_properties_get_int( b_props, "real_width" );
-       b_height = mlt_properties_get_int( b_props, "real_height" );
+       b_width = mlt_properties_get_int( b_props, "meta.media.width" );
+       b_height = mlt_properties_get_int( b_props, "meta.media.height" );
        mlt_properties_set_int( b_props, "rescale_width", b_width );
        mlt_properties_set_int( b_props, "rescale_height", b_height );
 
@@ -449,6 +450,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                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" );
+               int b_alpha = mlt_properties_get_int( properties, "b_alpha" );
                float geom_scale_x = (float) b_width / result.w;
                float geom_scale_y = (float) b_height / result.h;
                float cx = result.x + result.w / 2.0;
@@ -464,7 +466,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                affine_init( affine.matrix );
 
                // Compute the affine transform
-               get_affine( &affine, this, ( float )position );
+               get_affine( &affine, transition, ( float )position );
                dz = MapZ( affine.matrix, 0, 0 );
                if ( ( int )abs( dz * 1000 ) < 25 )
                {
@@ -490,13 +492,14 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                        {
                                scale_x = geom_scale_x * ( scale_x == 0 ? 1 : scale_x );
                                scale_y = geom_scale_x * ( scale_y == 0 ? 1 : scale_y );
+                               scale_y *= b_ar / consumer_ar;
                        }
                        else
                        {
                                scale_x = geom_scale_y * ( scale_x == 0 ? 1 : scale_x );
                                scale_y = geom_scale_y * ( scale_y == 0 ? 1 : scale_y );
+                               scale_x *= consumer_ar / b_ar;
                        }
-                       scale_x *= consumer_ar / b_ar;
                }
                if ( scale )
                {
@@ -531,7 +534,7 @@ static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_f
                                dx = MapX( affine.matrix, x, y ) / dz + x_offset;
                                dy = MapY( affine.matrix, x, y ) / dz + y_offset;
                                if ( dx >= 0 && dx < (b_width - 1) && dy >=0 && dy < (b_height - 1) )
-                                       interp( b_image, b_width, b_height, dx, dy, result.mix/100.0, p );
+                                       interp( b_image, b_width, b_height, dx, dy, result.mix/100.0, p, b_alpha );
                                p += 4;
                        }
                }
index 7368dddb0888ab4147bdc6c17c9f995420aefd70..eedfc6159c7bfce809369ed915595391a7b688cb 100644 (file)
@@ -1,6 +1,6 @@
 CFLAGS += -I../..
 
-LDFLAGS += -L../../framework -lmlt -lpthread -lm
+LDFLAGS += -L../../framework -lmlt -lpthread -lm -L../../mlt++ -lmlt++
 
 include ../../../config.mak
 include config.mak
@@ -8,13 +8,20 @@ include config.mak
 TARGET = ../libmltqimage$(LIBSUF)
 
 OBJS = factory.o producer_qimage.o producer_kdenlivetitle.o
-CPPOBJS = qimage_wrapper.o kdenlivetitle_wrapper.o
+CPPOBJS = qimage_wrapper.o \
+       kdenlivetitle_wrapper.o \
+       consumer_qglsl.o
 
-CXXFLAGS += $(CFLAGS) $(QTCXXFLAGS) $(EXIFCXXFLAGS) -Wno-deprecated
+ifdef GPL3
+       CPPOBJS += transition_vqm.o
+       CFLAGS += -DGPL3
+endif
+
+CXXFLAGS += $(CFLAGS) $(QTCXXFLAGS) $(EXIFCXXFLAGS) $(KDECXXFLAGS) -Wno-deprecated
 
-LDFLAGS += $(QTLIBS) $(EXIFLIBS)
+LDFLAGS += $(QTLIBS) $(EXIFLIBS) $(KDELIBS)
 
-ifdef USE_KDE
+ifdef USE_KDE3
 LDFLAGS += -lkio
 endif
 
@@ -35,9 +42,9 @@ clean:
                rm -f $(OBJS) $(TARGET) $(CPPOBJS)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/qimage"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/qimage"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/qimage"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/qimage"
 
 ifneq ($(wildcard .depend),)
 include .depend
index b53473e44483809a0811f532ba7525bcc2911cbd..a9ec7f8170b59d779a50f4dbe1b70ed3a3492c58 100755 (executable)
@@ -12,6 +12,7 @@ QImage options:
   --kde-includedir        - Location of KDE include directory [/usr/include/kde]
   --exif-libdir           - Location of libexif lib directory [/usr/lib]
   --exif-includedir       - Location of libexif include directory [/usr/include/libexif]
+  --without-kde           - Don't link to KDE libraries
 
 EOF
 
@@ -31,21 +32,8 @@ else
                ;;
        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/lib"
-               fi
-       fi
+       qimage_includedir=
+       qimage_libdir=
 
        if [ "$QTDIR" != "" ]
        then
@@ -55,6 +43,7 @@ else
 
        export force_qt3=
        export qt4_found=
+       export without_kde=
 
        for i in "$@"
        do
@@ -66,6 +55,7 @@ else
                        --exif-libdir=* )       exif_libdir="${i#--exif-libdir=}" ;;
                        --exif-includedir=* )   exif_includedir="${i#--exif-includedir=}" ;;
                        --force-qt3 )           force_qt3="true" ;;
+                       --without-kde ) without_kde="true" ;;
                esac
        done
 
@@ -95,19 +85,8 @@ else
                fi
        fi
 
-       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 QtCore QtGui QtXml QtSvg ) >> config.mak
-               echo QTLIBS=$(pkg-config --libs QtCore QtGui QtXml QtSvg) >> config.mak
-               
-       elif [ -d "$qimage_libdir" -a -d "$qimage_includedir" ]
+       if [ -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" ] || [ -f "$qimage_libdir/libQtCore4.a" ] && [ "$force_qt3" = "" ]
                then
@@ -125,27 +104,27 @@ else
                        echo "USE_QT4=1" >> config.mak
                        if [ -d "$qimage_libdir/QtGui.framework" ]
                        then
-                               echo QTCXXFLAGS=$(pkg-config --cflags QtCore QtGui QtXml QtSvg ) >> config.mak
-                               echo QTLIBS=$(pkg-config --libs QtCore QtGui QtXml QtSvg) >> config.mak
+                               echo QTCXXFLAGS=$(pkg-config --cflags QtCore QtGui QtXml QtSvg QtOpenGL) >> config.mak
+                               echo QTLIBS=$(pkg-config --libs QtCore QtGui QtXml QtSvg QtOpenGL) >> config.mak
                        elif [ -f "$qimage_libdir/libQtCore4.a" ]
                        then
                                echo QTCXXFLAGS=-I$qimage_includedir >> config.mak
-                               echo QTLIBS=-enable-auto-import -L$qimage_libdir -lQtCore4 -lQtGui4 -lQtXml4 -lQtSvg4 >> config.mak
+                               echo QTLIBS=-Wl,-enable-auto-import -L$qimage_libdir -lQtCore4 -lQtGui4 -lQtXml4 -lQtSvg4 -lQtOpenGL4 >> config.mak
                        else
                                echo QTCXXFLAGS=-I$qimage_includedir >> config.mak
-                               echo QTLIBS=-L$qimage_libdir -lQtCore -lQtGui -lQtXml -lQtSvg >> config.mak
+                               echo QTLIBS=-L$qimage_libdir -lQtCore -lQtGui -lQtXml -lQtSvg -lQtOpenGL >> config.mak
                        fi
-               else 
-                   if [ -d "$kde_includedir" ]
-                   then 
-                           echo "#define USE_KDE" >> config.h
-                           echo "USE_KDE=1" >> config.mak
+               else
+                   if [ "$without_kde" = "" ] && [ -d "$kde_includedir" ]
+                   then
+                           echo "#define USE_KDE3" >> config.h
+                           echo "USE_KDE3=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 -lqt-mt >> config.mak
-                   else 
-                           echo "qimage: KDE environment not found - disabling extra image formats"
+                   else
+                           echo "qimage: KDE environment not found or disabled by request - 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
@@ -153,8 +132,47 @@ else
                    fi
                fi
        else
-               echo "qimage: QT environment not found - disabling"
-               touch ../disable-qimage
+               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 QtCore QtGui QtXml QtSvg QtOpenGL) >> config.mak
+                       echo QTLIBS=$(pkg-config --libs QtCore QtGui QtXml QtSvg QtOpenGL) >> config.mak
+               else
+                       echo "qimage: QT environment not found - disabling"
+                       touch ../disable-qimage
+               fi
+       fi
+
+       if [ "$without_kde" = "" ]
+       then
+               kde4-config
+               if [ $? -eq 0 ] && [ "$qt4_found" != "" ]
+               then
+                       # test if we have KDE4, required on some systems to get QImage extra formats (xcf, ...)
+                       if [ "$kde_includedir" = "" ]
+                       then
+                                 kde_includedir=`kde4-config --install include`
+                       fi
+                       if [ "$kde_libdir" = "" ]
+                       then
+                                 kde_libdir=`kde4-config --install lib`
+                       fi
+                       if [ -d "$kde_includedir" ] && [ -d "$kde_libdir" ]
+                       then
+                               echo "KDE version 4.x detected, will enable extra image formats"
+                               echo "#define USE_KDE4" >> config.h
+                               echo "USE_KDE4=1" >> config.mak
+                               echo KDECXXFLAGS=-I$kde_includedir >> config.mak
+                               # the -L with kde4/devel is for Fedora
+                               echo KDELIBS=-L$kde_libdir -L${kde_libdir}/kde4/devel -lkdecore >> config.mak
+                       fi
+               fi
        fi
 
+       [ "$gpl3" = "true" ] && echo GPL3=1 >> config.mak
+       exit 0
 fi
diff --git a/src/modules/qimage/consumer_qglsl.cpp b/src/modules/qimage/consumer_qglsl.cpp
new file mode 100644 (file)
index 0000000..d87a7b7
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * consumer_qglsl.cpp
+ * Copyright (C) 2012 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 <QtGui/QApplication>
+#include <QtCore/QLocale>
+#include <QtOpenGL/QGLWidget>
+
+static void onThreadStarted(mlt_properties owner, mlt_consumer consumer)
+{
+       mlt_service service = MLT_CONSUMER_SERVICE(consumer);
+       mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
+       mlt_filter filter = (mlt_filter) mlt_properties_get_data(properties, "glslManager", NULL);
+       mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
+       QApplication* app = qApp;
+
+       mlt_log_debug(service, "%s\n", __FUNCTION__);
+#ifdef linux
+       if ( getenv("DISPLAY") == 0 ) {
+               mlt_log_error(service, "The qglsl consumer requires a X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
+       } else
+#endif
+       if (!app) {
+               int argc = 1;
+               char* argv[1];
+               argv[0] = (char*) "MLT qglsl consumer";
+               app = new QApplication(argc, argv);
+               const char *localename = mlt_properties_get_lcnumeric(properties);
+               QLocale::setDefault(QLocale(localename));
+       }
+       QGLWidget* renderContext = new QGLWidget;
+       renderContext->resize(0, 0);
+       renderContext->show();
+       mlt_events_fire(filter_properties, "init glsl", NULL);
+       if (!mlt_properties_get_int(filter_properties, "glsl_supported")) {
+               mlt_log_fatal(service,
+                       "OpenGL Shading Language rendering is not supported on this machine.\n" );
+               mlt_events_fire(properties, "consumer-fatal-error", NULL);
+       }
+       else {
+               mlt_properties_set_data(properties, "qglslRenderContext", renderContext, 0, NULL, NULL);
+       }
+}
+
+static void onCleanup(mlt_properties owner, mlt_consumer consumer)
+{
+       QGLWidget* renderContext = (QGLWidget*) mlt_properties_get_data(
+               MLT_CONSUMER_PROPERTIES(consumer), "qglslRenderContext", NULL);
+       if (renderContext)
+               renderContext->makeCurrent();
+       delete renderContext;
+       mlt_properties_set_data(MLT_CONSUMER_PROPERTIES(consumer),
+               "qglslRenderContext", NULL, 0, NULL, NULL);
+}
+
+extern "C" {
+
+mlt_consumer consumer_qglsl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_consumer consumer = mlt_factory_consumer(profile, "multi", arg);
+       if (consumer) {
+               mlt_filter filter = mlt_factory_filter(profile, "glsl.manager", 0);
+               if (filter) {
+                       mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
+                       mlt_properties_set_data(properties, "glslManager", filter, 0, (mlt_destructor) mlt_filter_close, NULL);
+                       mlt_events_register( properties, "consumer-cleanup", NULL );
+                       mlt_events_listen(properties, consumer, "consumer-thread-started", (mlt_listener) onThreadStarted);
+                       mlt_events_listen(properties, consumer, "consumer-cleanup", (mlt_listener) onCleanup);
+                       return consumer;
+               }
+               mlt_consumer_close(consumer);
+       }
+       return NULL;
+}
+
+}
index cb4fae7413b413274d2a43b19d9b3292f2fe5262..e11c8b2eee6aae2fdfc8746b87ea4e983922e2eb 100644 (file)
 #include <limits.h>
 #include <framework/mlt.h>
 
+extern mlt_consumer consumer_qglsl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_producer producer_qimage_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_producer producer_kdenlivetitle_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_transition transition_vqm_init( mlt_profile profile, mlt_service_type type, const char *id, void *arg );
 
 static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
 {
@@ -34,8 +36,13 @@ static mlt_properties metadata( mlt_service_type type, const char *id, void *dat
 
 MLT_REPOSITORY
 {
+       MLT_REGISTER( consumer_type, "qglsl", consumer_qglsl_init );
        MLT_REGISTER( producer_type, "qimage", producer_qimage_init );
        MLT_REGISTER( producer_type, "kdenlivetitle", producer_kdenlivetitle_init );
        MLT_REGISTER_METADATA( producer_type, "qimage", metadata, "producer_qimage.yml" );
        MLT_REGISTER_METADATA( producer_type, "kdenlivetitle", metadata, "producer_kdenlivetitle.yml" );
+#ifdef GPL3
+       MLT_REGISTER( transition_type, "vqm", transition_vqm_init );
+       MLT_REGISTER_METADATA( transition_type, "vqm", metadata, "transition_vqm.yml" );
+#endif
 }
index 746f382891eb3ff5d893e819b27bf93309ab89d7..1f701f1b4c1bc6e31780360f9450007e7bef4864 100755 (executable)
@@ -48,6 +48,7 @@
 #endif
 
 static QApplication *app = NULL;
+Q_DECLARE_METATYPE(QTextCursor);
 
 class ImageItem: public QGraphicsItem
 {
@@ -197,7 +198,10 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                                }
                                QGraphicsTextItem *txt = scene->addText(text, font);
                                if (txtProperties.namedItem("font-outline").nodeValue().toDouble()>0.0){
-                                       QTextCursor cursor(txt->document());
+                                       QTextDocument *doc = txt->document();
+                                       // Make sure some that the text item does not request refresh by itself
+                                       doc->blockSignals(true);
+                                       QTextCursor cursor(doc);
                                        cursor.select(QTextCursor::Document);
                                        QTextCharFormat format;
                                        format.setTextOutline(
@@ -218,6 +222,8 @@ void loadFromXml( mlt_producer producer, QGraphicsScene *scene, const char *temp
                                        mlt_properties_set_int( producer_props, "_animated", 1 );
                                        QStringList effetData = QStringList() << "typewriter" << text << txtProperties.namedItem( "typewriter" ).nodeValue();
                                        txt->setData(0, effetData);
+                                       if ( !txtProperties.namedItem( "textwidth" ).isNull() )
+                                               txt->setData( 1, txtProperties.namedItem( "textwidth" ).nodeValue() );
                                }
                                
                                if ( txtProperties.namedItem( "alignment" ).isNull() == false )
@@ -391,7 +397,6 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                                        {
                                                mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
                                                pthread_mutex_unlock( &self->mutex );
-                                               exit(1);
                                                return;
                                        }
 #endif
@@ -399,6 +404,7 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                                        const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) );
                                        QLocale::setDefault( QLocale( localename ) );
                                }
+                               qRegisterMetaType<QTextCursor>( "QTextCursor" );
                        }
                        scene = new QGraphicsScene();
                        scene->setItemIndexMethod( QGraphicsScene::NoIndex );
@@ -446,9 +452,15 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                                    QTextCharFormat format = cursor.charFormat();
                                    cursor.select(QTextCursor::Document);
                                    QString txt = params.at( 1 ).left( interval );
-                                   // If the string to insert is empty, insert a space so that we don't loose
+                                   // If the string to insert is empty, insert a space / linebreak so that we don't loose
                                    // formatting infos for the next iterations
-                                   cursor.insertText(txt.isEmpty() ? " " : txt, format);
+                                   int lines = params.at( 1 ).count( '\n' );
+                                   QString empty = " ";
+                                   for (int i = 0; i < lines; i++)
+                                           empty.append( "\n " );
+                                   cursor.insertText( txt.isEmpty() ? empty : txt, format );
+                                   if ( !titem->data( 1 ).isNull() )
+                                         titem->setTextWidth( titem->data( 1 ).toDouble() );
                            }
                    }
                }
@@ -470,7 +482,9 @@ void drawKdenliveTitle( producer_ktitle self, mlt_frame frame, int width, int he
                         scene->render( &p1, source, end, Qt::IgnoreAspectRatio );
                 }
                else {
-                        double percentage = position / anim_out;
+                        double percentage = 0;
+                       if ( position && anim_out )
+                               percentage = position / anim_out;
                        QPointF topleft = start.topLeft() + ( end.topLeft() - start.topLeft() ) * percentage;
                        QPointF bottomRight = start.bottomRight() + ( end.bottomRight() - start.bottomRight() ) * percentage;
                        const QRectF r1( topleft, bottomRight );
index 5c37d3a348f4d9994ef5d8b46b0fdf27998129b6..9536176a8ba3112fe7d7d462992e89ffa9037fab 100644 (file)
@@ -33,20 +33,31 @@ void read_xml(mlt_properties properties)
                int size = 0;
                long lSize;
  
-               fseek (f , 0 , SEEK_END);
+               if ( fseek (f , 0 , SEEK_END) < 0 )
+                       goto error;
                lSize = ftell (f);
+               if ( lSize <= 0 )
+                       goto error;
                rewind (f);
 
                char *infile = (char*) mlt_pool_alloc(lSize);
-               size=fread(infile,1,lSize,f);
-               infile[size] = '\0';
+               if ( infile )
+               {
+                       size = fread(infile,1,lSize,f);
+                       if ( size )
+                       {
+                               infile[size] = '\0';
+                               mlt_properties_set(properties, "_xmldata", infile);
+                       }
+                       mlt_pool_release( infile );
+               }
+error:
                fclose(f);
-               mlt_properties_set(properties, "_xmldata", infile);
-               mlt_pool_release( infile );
        }
 }
 
 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 );
@@ -64,13 +75,12 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
 
        /* Allocate the image */
        *format = mlt_image_rgb24a;
-       mlt_position time = mlt_producer_position( &this->parent ) + mlt_producer_get_in( &this->parent );
        if ( mlt_properties_get_int( producer_props, "force_reload" ) ) {
-               if (mlt_properties_get_int( producer_props, "force_reload" ) > 1) read_xml(producer_props);
+               if ( mlt_properties_get_int( producer_props, "force_reload" ) > 1 ) read_xml( producer_props );
                mlt_properties_set_int( producer_props, "force_reload", 0 );
-               drawKdenliveTitle( this, frame, *width, *height, time, 1);
+               drawKdenliveTitle( this, frame, *width, *height, mlt_frame_original_position( frame ), 1);
        }
-       else drawKdenliveTitle( this, frame, *width, *height, time, 0);
+       else drawKdenliveTitle( this, frame, *width, *height, mlt_frame_original_position( frame ), 0);
 
        // Get width and height (may have changed during the refresh)
        *width = mlt_properties_get_int( properties, "width" );
@@ -119,9 +129,7 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
 
                /* Set producer-specific frame properties */
-               mlt_profile profile = mlt_service_profile ( MLT_PRODUCER_SERVICE( producer ) ) ;
-               mlt_properties_set_int( properties, "progressive", ( profile ) ? profile->progressive : 1 );
-               mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) );
+               mlt_properties_pass_list( properties, producer_props, "progressive, aspect_ratio" );
 
                /* Push the get_image method */
                mlt_frame_push_get_image( *frame, producer_get_image );
@@ -147,7 +155,7 @@ mlt_producer producer_kdenlivetitle_init( mlt_profile profile, mlt_service_type
        /* fprintf(stderr, ":::::::::::: CREATE TITLE\n"); */
        /* Create a new producer object */
        
-       producer_ktitle this = calloc( sizeof( struct producer_ktitle_s ), 1 );
+       producer_ktitle this = calloc( 1, sizeof( struct producer_ktitle_s ) );
        if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
        {
                mlt_producer producer = &this->parent;
@@ -158,7 +166,7 @@ mlt_producer producer_kdenlivetitle_init( mlt_profile profile, mlt_service_type
                producer->get_frame = producer_get_frame;
                producer->close = ( mlt_destructor )producer_close;
                mlt_properties_set( properties, "resource", filename );
-               //mlt_properties_set_int( properties, "aspect_ratio", 1 );
+               mlt_properties_set_int( properties, "progressive", 1 );
                read_xml(properties);
                return producer;
        }
index b65c8d956ad4bf71b9727c591c22d9f0eddc02c9..e65e92444d79913ea4d71b9cedb25d14b98c1fd2 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <ctype.h>
 
-static void load_filenames( producer_qimage this, mlt_properties producer_properties );
+static void load_filenames( producer_qimage self, 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 )
+       producer_qimage self = calloc( 1, sizeof( struct producer_qimage_s ) );
+       if ( self != NULL && mlt_producer_init( &self->parent, self ) == 0 )
        {
-               mlt_producer producer = &this->parent;
+               mlt_producer producer = &self->parent;
 
                // Get the properties interface
-               mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
+               mlt_properties properties = MLT_PRODUCER_PROPERTIES( &self->parent );
        
-               // Callback registration
-#ifdef USE_KDE
+               // Initialize KDE image plugins
                init_qimage();
-#endif
+
+               // Callback registration
                producer->get_frame = producer_get_frame;
                producer->close = ( mlt_destructor )producer_close;
 
@@ -59,51 +60,57 @@ mlt_producer producer_qimage_init( mlt_profile profile, mlt_service_type type, c
                mlt_properties_set_int( properties, "ttl", 25 );
                mlt_properties_set_int( properties, "aspect_ratio", 1 );
                mlt_properties_set_int( properties, "progressive", 1 );
-               
+               mlt_properties_set_int( properties, "seekable", 1 );
+
                // Validate the resource
                if ( filename )
-                       load_filenames( this, properties );
-               if ( this->count )
+                       load_filenames( self, properties );
+               if ( self->count )
                {
                        mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
                        if ( frame )
                        {
                                mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
-                               mlt_properties_set_data( frame_properties, "producer_qimage", this, 0, NULL, NULL );
+                               mlt_properties_set_data( frame_properties, "producer_qimage", self, 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 );
+                               refresh_qimage( self, frame );
+                               mlt_cache_item_close( self->qimage_cache );
                                mlt_frame_close( frame );
                        }
                }
-               if ( this->current_width == 0 )
+               if ( self->current_width == 0 )
                {
                        producer_close( producer );
                        producer = NULL;
                }
-               if ( producer )
-                       pthread_mutex_init( &this->mutex, NULL );
                return producer;
        }
-       free( this );
+       free( self );
        return NULL;
 }
 
-static void load_filenames( producer_qimage this, mlt_properties producer_properties )
+static int load_svg( producer_qimage self, mlt_properties properties, const char *filename )
 {
-       char *filename = mlt_properties_get( producer_properties, "resource" );
-       this->filenames = mlt_properties_new( );
+       int result = 0;
 
        // Read xml string
        if ( strstr( filename, "<svg" ) )
        {
-               make_tempfile( this, filename );
+               make_tempfile( self, filename );
+               result = 1;
        }
-       // Obtain filenames
-       else if ( strchr( filename, '%' ) != NULL )
+       return result;
+}
+
+static int load_sequence_sprintf( producer_qimage self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with pattern
+       if ( strchr( filename, '%' ) != NULL )
        {
                // handle picture sequences
-               int i = mlt_properties_get_int( producer_properties, "begin" );
+               int i = mlt_properties_get_int( properties, "begin" );
                int gap = 0;
                char full[1024];
                int keyvalue = 0;
@@ -116,7 +123,7 @@ static void load_filenames( producer_qimage this, mlt_properties producer_proper
                        if ( stat( full, &buf ) == 0 )
                        {
                                sprintf( key, "%d", keyvalue ++ );
-                               mlt_properties_set( this->filenames, key, full );
+                               mlt_properties_set( self->filenames, key, full );
                                gap = 0;
                        }
                        else
@@ -124,10 +131,71 @@ static void load_filenames( producer_qimage this, mlt_properties producer_proper
                                gap ++;
                        }
                }
-               if ( mlt_properties_count( this->filenames ) > 0 )
-                       mlt_properties_set_int( producer_properties, "ttl", 1 );
+               if ( mlt_properties_count( self->filenames ) > 0 )
+               {
+                       mlt_properties_set_int( properties, "ttl", 1 );
+                       result = 1;
+               }
        }
-       else if ( strstr( filename, "/.all." ) != NULL )
+       return result;
+}
+
+static int load_sequence_deprecated( producer_qimage self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+       const char *start;
+
+       // Obtain filenames with pattern containing a begin value, e.g. foo%1234d.png
+       if ( ( start = strchr( filename, '%' ) ) )
+       {
+               const char *end = ++start;
+               while ( isdigit( *end ) ) end++;
+               if ( end > start && ( end[0] == 'd' || end[0] == 'i' || end[0] == 'u' ) )
+               {
+                       int n = end - start;
+                       char *s = calloc( 1, n + 1 );
+                       strncpy( s, start, n );
+                       mlt_properties_set( properties, "begin", s );
+                       free( s );
+                       s = calloc( 1, strlen( filename ) + 2 );
+                       strncpy( s, filename, start - filename );
+                       sprintf( s + ( start - filename ), ".%d%s", n, end );
+                       result = load_sequence_sprintf( self, properties, s );
+                       free( s );
+               }
+       }
+       return result;
+}
+
+static int load_sequence_querystring( producer_qimage self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames with pattern and begin value in query string
+       if ( strchr( filename, '%' ) && strchr( filename, '?' ) )
+       {
+               // Split filename into pattern and query string
+               char *s = strdup( filename );
+               char *querystring = strrchr( s, '?' );
+               *querystring++ = '\0';
+               if ( strstr( filename, "begin=" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin=" ) + 6 );
+               else if ( strstr( filename, "begin:" ) )
+                       mlt_properties_set( properties, "begin", strstr( querystring, "begin:" ) + 6 );
+               // Coerce to an int value so serialization does not have any extra query string cruft
+               mlt_properties_set_int( properties, "begin", mlt_properties_get_int( properties, "begin" ) );
+               result = load_sequence_sprintf( self, properties, s );
+               free( s );
+       }
+       return result;
+}
+
+static int load_folder( producer_qimage self, mlt_properties properties, const char *filename )
+{
+       int result = 0;
+
+       // Obtain filenames within folder
+       if ( strstr( filename, "/.all." ) != NULL )
        {
                char wildcard[ 1024 ];
                char *dir_name = strdup( filename );
@@ -136,55 +204,79 @@ static void load_filenames( producer_qimage this, mlt_properties producer_proper
                *( strstr( dir_name, "/.all." ) + 1 ) = '\0';
                sprintf( wildcard, "*%s", extension );
 
-               mlt_properties_dir_list( this->filenames, dir_name, wildcard, 1 );
+               mlt_properties_dir_list( self->filenames, dir_name, wildcard, 1 );
 
                free( dir_name );
+               result = 1;
        }
-       else
+       return result;
+}
+
+static void load_filenames( producer_qimage self, mlt_properties properties )
+{
+       char *filename = mlt_properties_get( properties, "resource" );
+       self->filenames = mlt_properties_new( );
+
+       if (!load_svg( self, properties, filename ) &&
+               !load_sequence_querystring( self, properties, filename ) &&
+               !load_sequence_sprintf( self, properties, filename ) &&
+               !load_sequence_deprecated( self, properties, filename ) &&
+               !load_folder( self, properties, filename ) )
        {
-               mlt_properties_set( this->filenames, "0", filename );
+               mlt_properties_set( self->filenames, "0", filename );
        }
-
-       this->count = mlt_properties_count( this->filenames );
+       self->count = mlt_properties_count( self->filenames );
 }
 
 static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
 {
        int error = 0;
        
-       // Obtain properties of frame
+       // Obtain properties of frame and producer
        mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
-       // Obtain the producer for this frame
-       producer_qimage this = mlt_properties_get_data( properties, "producer_qimage", NULL );
+       producer_qimage self = mlt_properties_get_data( properties, "producer_qimage", NULL );
+       mlt_producer producer = &self->parent;
 
        *width = mlt_properties_get_int( properties, "rescale_width" );
        *height = mlt_properties_get_int( properties, "rescale_height" );
 
-       mlt_service_lock( MLT_PRODUCER_SERVICE( &this->parent ) );
+       mlt_service_lock( MLT_PRODUCER_SERVICE( &self->parent ) );
 
        // Refresh the image
-       refresh_qimage( this, frame, *width, *height );
+       self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
+       self->qimage = mlt_cache_item_data( self->qimage_cache, NULL );
+       self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
+       self->current_image = mlt_cache_item_data( self->image_cache, NULL );
+       self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.alpha" );
+       self->current_alpha = mlt_cache_item_data( self->alpha_cache, NULL );
+       refresh_image( self, frame, *format, *width, *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" );
-       *format = this->has_alpha ? mlt_image_rgb24a : mlt_image_rgb24;
+       *format = self->format;
 
        // 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 )
+       if ( self->current_image )
        {
                // Clone the image and the alpha
-               int image_size = this->current_width * ( this->current_height + 1 ) * ( this->has_alpha ? 4 :3 );
+               int image_size = mlt_image_format_size( self->format, self->current_width, self->current_height, NULL );
                uint8_t *image_copy = mlt_pool_alloc( image_size );
-               memcpy( image_copy, this->current_image, image_size );
+               memcpy( image_copy, self->current_image, image_size );
                // Now update properties so we free the copy after
                mlt_frame_set_image( frame, image_copy, image_size, mlt_pool_release );
                // We're going to pass the copy on
                *buffer = image_copy;
-               mlt_log_debug( MLT_PRODUCER_SERVICE( &this->parent ), "%dx%d (%s)\n", 
-                       this->current_width, this->current_height, mlt_image_format_name( *format ) );
+               mlt_log_debug( MLT_PRODUCER_SERVICE( &self->parent ), "%dx%d (%s)\n",
+                       self->current_width, self->current_height, mlt_image_format_name( *format ) );
+               // Clone the alpha channel
+               if ( self->current_alpha )
+               {
+                       image_copy = mlt_pool_alloc( self->current_width * self->current_height );
+                       memcpy( image_copy, self->current_alpha, self->current_width * self->current_height );
+                       mlt_frame_set_alpha( frame, image_copy, self->current_width * self->current_height, mlt_pool_release );
+               }
        }
        else
        {
@@ -192,9 +284,10 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        }
 
        // Release references and locks
-       pthread_mutex_unlock( &this->mutex );
-       mlt_cache_item_close( this->image_cache );
-       mlt_service_unlock( MLT_PRODUCER_SERVICE( &this->parent ) );
+       mlt_cache_item_close( self->qimage_cache );
+       mlt_cache_item_close( self->image_cache );
+       mlt_cache_item_close( self->alpha_cache );
+       mlt_service_unlock( MLT_PRODUCER_SERVICE( &self->parent ) );
 
        return error;
 }
@@ -202,33 +295,33 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
 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;
+       producer_qimage self = 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 );
+       if ( self->filenames == NULL && mlt_properties_get( producer_properties, "resource" ) != NULL )
+               load_filenames( self, producer_properties );
 
        // Generate a frame
        *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
 
-       if ( *frame != NULL && this->count > 0 )
+       if ( *frame != NULL && self->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 );
+               mlt_properties_set_data( properties, "producer_qimage", self, 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 );
+               self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
+               self->qimage = mlt_cache_item_data( self->qimage_cache, NULL );
+               refresh_qimage( self, *frame );
+               mlt_cache_item_close( self->qimage_cache );
 
                // Set producer-specific frame properties
                mlt_properties_set_int( properties, "progressive", mlt_properties_get_int( producer_properties, "progressive" ) );
@@ -250,11 +343,10 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 
 static void producer_close( mlt_producer parent )
 {
-       producer_qimage this = parent->child;
-       pthread_mutex_destroy( &this->mutex );
+       producer_qimage self = parent->child;
        parent->close = NULL;
        mlt_service_cache_purge( MLT_PRODUCER_SERVICE(parent) );
        mlt_producer_close( parent );
-       mlt_properties_close( this->filenames );
-       free( this );
+       mlt_properties_close( self->filenames );
+       free( self );
 }
index b998f9cc8dcd6c1b14a5fbef983f9e5c61bf7610..eaf20b27d8415f9ca0ae671feff44ac1aeffd393 100644 (file)
@@ -2,10 +2,107 @@ schema_version: 0.1
 type: producer
 identifier: qimage
 title: Qt QImage
-version: 1
+version: 2
 copyright: Visual Media ?
 creator: Charles Yates
 license: GPLv2
 language: en
 tags:
   - Video
+description: >
+    A still graphics to video generator using Qt QImage
+notes: >
+    QImage 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.
+parameters:
+  - identifier: argument
+    title: File
+    type: string
+    description: >
+        The name of a graphics file loadable by Qt.
+
+        If "%" in filename, the filename is used with sprintf to generate a
+        filename from a counter for multi-file/flipbook animation. The file
+        sequence ends when numeric discontinuity exceeds 100.
+
+        If the file sequence does not begin within the count of 100 you
+        can pass the begin property like a query string parameter, for
+        example: anim-%04d.png?begin=1000.
+
+        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 qimage tries to load the
+        filename as inline SVG XML, which is convenient for melt commands.
+    readonly: no
+    required: yes
+    mutable: no
+    widget: fileopen
+
+  - identifier: begin
+    title: Begin
+    type: integer
+    description: When using an image sequence, this sets the starting number.
+    readonly: no
+    minimum: 0
+    mutable: no
+    widget: spinner
+
+  - identifier: ttl
+    title: Time-to-live
+    type: integer
+    description: How long (in frames) to repeat each picture in file sequences.
+    readonly: no
+    default: 25
+    minimum: 0
+    mutable: yes
+    widget: spinner
+
+  - identifier: meta.media.width
+    title: Real width
+    type: integer
+    description: The original, unscaled width of the rendered image.
+    readonly: yes
+
+  - identifier: meta.media.height
+    title: Real height
+    type: integer
+    description: The original, unscaled height of the rendered image.
+    readonly: yes
+
+  - identifier: width
+    title: Width
+    type: integer
+    description: The last requested scaled image width.
+    readonly: yes
+
+  - identifier: height
+    title: Height
+    type: integer
+    description: The last requested scaled image height.
+    readonly: yes
+
+  - identifier: force_reload
+    type: integer
+    description: >
+      Reload the file instead of using its cached image. This property
+      automatically resets itself once it has been set 1 and processed.
+    minimum: 0
+    maximum: 1
+    mutable: yes
+
+  - identifier: disable_exif
+    title: Disable auto-rotation
+    type: integer
+    minimum: 0
+    maximum: 1
+    widget: checkbox
+
+  - identifier: force_aspect_ratio
+    title: Sample aspect ratio
+    type: float
+    description: Optionally override a (mis)detected aspect ratio
+    mutable: yes
+
index abcef45449b2a332b5203eb820b961d964ba30a2..18a0c9f2e7334eaf8068b9038179bc81ce934d86 100644 (file)
 #include <qimage.h>
 #include <qmutex.h>
 
-#ifdef USE_KDE
+#ifdef USE_KDE3
 #include <kinstance.h>
 #include <kimageio.h>
 #endif
-
 #endif
 
+#ifdef USE_KDE4
+#include <kcomponentdata.h>
+#endif
 
 #ifdef USE_QT4
 #include <QtGui/QImage>
 #include <QtCore/QSysInfo>
+#include <QtGui/QApplication>
 #include <QtCore/QMutex>
 #include <QtCore/QtEndian>
 #include <QtCore/QTemporaryFile>
+#include <QtCore/QLocale>
 #endif
 
 #ifdef USE_EXIF
 #endif
 
 #include <cmath>
+#include <unistd.h>
 
 extern "C" {
 
 #include <framework/mlt_pool.h>
 #include <framework/mlt_cache.h>
 
-#ifdef USE_KDE
+#ifdef USE_KDE4
+static KComponentData *instance = 0L;
+#elif USE_KDE3
 static KInstance *instance = 0L;
 #endif
 
+static QApplication *app = NULL;
+
 static void qimage_delete( void *data )
 {
        QImage *image = ( QImage * )data;
        delete image;
        image = NULL;
-#ifdef USE_KDE
+#if defined(USE_KDE3) || defined(USE_KDE4) 
        if (instance) delete instance;
        instance = 0L;
 #endif
-}
 
-static QMutex g_mutex;
+}
 
-#ifdef USE_KDE
 void init_qimage()
 {
-       if (!instance) {
-           instance = new KInstance("qimage_prod");
+#ifdef USE_KDE4
+       if ( !instance ) {
+           instance = new KComponentData( "qimage_prod" );
+       }
+#elif defined(USE_KDE3)
+       if ( !instance ) {
+           instance = new KInstance( "qimage_prod" );
            KImageIO::registerFormats();
        }
+#endif
+  
 }
+
+static QImage* reorient_with_exif( producer_qimage self, int image_idx, QImage *qimage )
+{
+#ifdef USE_EXIF
+       mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( &self->parent );
+       ExifData *d = exif_data_new_from_file( mlt_properties_get_value( self->filenames, image_idx ) );
+       ExifEntry *entry;
+       int exif_orientation = 0;
+       /* get orientation and rotate image accordingly if necessary */
+       if (d) {
+               if ( ( entry = exif_content_get_entry ( d->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION ) ) )
+                       exif_orientation = exif_get_short (entry->data, exif_data_get_byte_order (d));
+
+               /* Free the EXIF data */
+               exif_data_unref(d);
+       }
+
+       // Remember EXIF value, might be useful for someone
+       mlt_properties_set_int( producer_props, "_exif_orientation" , exif_orientation );
+
+       if ( exif_orientation > 1 )
+       {
+                 // Rotate image according to exif data
+                 QImage processed;
+                 QMatrix matrix;
+
+                 switch ( exif_orientation ) {
+                 case 2:
+                         matrix.scale( -1, 1 );
+                         break;
+                 case 3:
+                         matrix.rotate( 180 );
+                         break;
+                 case 4:
+                         matrix.scale( 1, -1 );
+                         break;
+                 case 5:
+                         matrix.rotate( 270 );
+                         matrix.scale( -1, 1 );
+                         break;
+                 case 6:
+                         matrix.rotate( 90 );
+                         break;
+                 case 7:
+                         matrix.rotate( 90 );
+                         matrix.scale( -1, 1 );
+                         break;
+                 case 8:
+                         matrix.rotate( 270 );
+                         break;
+                 }
+                 processed = qimage->transformed( matrix );
+                 delete qimage;
+                 qimage = new QImage( processed );
+       }
 #endif
+       return qimage;
+}
 
-void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int height )
+int refresh_qimage( producer_qimage self, mlt_frame frame )
 {
-       // Obtain properties of frame
+       // Obtain properties of frame and producer
        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 ) );
-
        // Check if user wants us to reload the image
        if ( mlt_properties_get_int( producer_props, "force_reload" ) )
        {
-               qimage = NULL;
+               self->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" );
+       mlt_position position = mlt_frame_original_position( frame );
        position += mlt_producer_get_in( producer );
 
        // Image index
@@ -128,138 +181,101 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh
        char image_key[ 10 ];
        sprintf( image_key, "%d", image_idx );
 
-       g_mutex.lock();
-
-       // Check if the frame is already loaded
-       if ( use_cache )
+       int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
+       
+       
+       if ( app == NULL ) 
        {
-               if ( cache == NULL )
+               if ( qApp ) 
                {
-                       cache = mlt_properties_new( );
-                       mlt_properties_set_data( producer_props, "_cache", cache, 0, ( mlt_destructor )mlt_properties_close, NULL );
+                       app = qApp;
                }
-
-               mlt_frame cached = ( mlt_frame )mlt_properties_get_data( cache, image_key, NULL );
-
-               if ( cached )
+               else 
                {
-                       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->has_alpha = mlt_properties_get_int( cached_props, "alpha" );
-
-                       if ( width != 0 && ( width != self->current_width || height != self->current_height ) )
-                               self->current_image = NULL;
+#ifdef linux
+                       if ( getenv("DISPLAY") == 0 )
+                       {
+                               mlt_log_panic( MLT_PRODUCER_SERVICE( producer ), "Error, cannot render titles without an X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
+                               return -1;
+                       }
+#endif
+                       int argc = 1;
+                       char* argv[1];
+                       argv[0] = (char*) "xxx";
+                       app = new QApplication( argc, argv );
+                       const char *localename = mlt_properties_get_lcnumeric( MLT_SERVICE_PROPERTIES( MLT_PRODUCER_SERVICE( producer ) ) );
+                       QLocale::setDefault( QLocale( localename ) );
                }
        }
 
-       int disable_exif = mlt_properties_get_int( producer_props, "disable_exif" );
-
-       // optimization for subsequent iterations on single pictur
-       if ( width != 0 && ( image_idx != self->image_idx || width != self->current_width || height != self->current_height ) )
-               self->current_image = NULL;
        if ( image_idx != self->qimage_idx )
-               qimage = NULL;
-
-       if ( !qimage || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif)
+               self->qimage = NULL;
+       if ( !self->qimage || mlt_properties_get_int( producer_props, "_disable_exif" ) != disable_exif )
        {
                self->current_image = NULL;
-               qimage = new QImage( mlt_properties_get_value( self->filenames, image_idx ) );
+               QImage *qimage = new QImage( QString::fromUtf8( mlt_properties_get_value( self->filenames, image_idx ) ) );
+               self->qimage = qimage;
 
                if ( !qimage->isNull( ) )
                {
-#ifdef USE_EXIF
                        // Read the exif value for this file
-                       if ( disable_exif == 0) {
-                               ExifData *d = exif_data_new_from_file( mlt_properties_get_value( self->filenames, image_idx ) );
-                               ExifEntry *entry;
-                               int exif_orientation = 0;
-                               /* get orientation and rotate image accordingly if necessary */
-                               if (d) {
-                                       if ( ( entry = exif_content_get_entry ( d->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION ) ) )
-                                               exif_orientation = exif_get_short (entry->data, exif_data_get_byte_order (d));
-                                       
-                                       /* Free the EXIF data */
-                                       exif_data_unref(d);
-                               }
-
-                               // Remember EXIF value, might be useful for someone
-                               mlt_properties_set_int( producer_props, "_exif_orientation" , exif_orientation );
-                                     
-                               if ( exif_orientation > 1 )
-                               {
-                                     // Rotate image according to exif data
-                                     QImage processed;
-                                     QMatrix matrix;
-
-                                     switch ( exif_orientation ) {
-                                         case 2:
-                                             matrix.scale( -1, 1 );
-                                             break;
-                                         case 3:
-                                             matrix.rotate( 180 );
-                                             break;
-                                         case 4:
-                                             matrix.scale( 1, -1 );
-                                             break;
-                                         case 5:
-                                             matrix.rotate( 270 );
-                                             matrix.scale( -1, 1 );
-                                             break;
-                                         case 6:
-                                             matrix.rotate( 90 );
-                                             break;
-                                         case 7:
-                                             matrix.rotate( 90 );
-                                             matrix.scale( -1, 1 );
-                                             break;
-                                         case 8:
-                                             matrix.rotate( 270 );
-                                             break;
-                                     }
-                                     processed = qimage->transformed( matrix );
-                                     delete qimage;
-                                     qimage = new QImage( processed );
-                               }
-                       }
-#endif                 
-                       // Store the width/height of the qimage  
-                       self->current_width = qimage->width( );
-                       self->current_height = qimage->height( );
+                       if ( !disable_exif )
+                               qimage = reorient_with_exif( self, image_idx, qimage );
 
                        // Register qimage for destruction and reuse
-                       mlt_cache_item_close( qimage_cache );
+                       mlt_cache_item_close( self->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" );
+                       self->qimage_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.qimage" );
                        self->qimage_idx = image_idx;
 
+                       // Store the width/height of the qimage
+                       self->current_width = qimage->width( );
+                       self->current_height = qimage->height( );
+
                        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_properties_set_int( producer_props, "meta.media.width", self->current_width );
+                       mlt_properties_set_int( producer_props, "meta.media.height", self->current_height );
                        mlt_properties_set_int( producer_props, "_disable_exif", disable_exif );
                        mlt_events_unblock( producer_props, NULL );
                }
                else
                {
                        delete qimage;
-                       qimage = NULL;
+                       self->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 )
+       // Set width/height of frame
+       mlt_properties_set_int( properties, "width", self->current_width );
+       mlt_properties_set_int( properties, "height", self->current_height );
+
+       return image_idx;
+}
+
+void refresh_image( producer_qimage self, mlt_frame frame, mlt_image_format format, int width, int height )
+{
+       // Obtain properties of frame and producer
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       mlt_producer producer = &self->parent;
+
+       // Get index and qimage
+       int image_idx = refresh_qimage( self, frame );
+
+       // optimization for subsequent iterations on single pictur
+       if ( image_idx != self->image_idx || width != self->current_width || height != self->current_height )
+               self->current_image = NULL;
+
+       // If we have a qimage and need a new scaled image
+       if ( self->qimage && ( !self->current_image || ( format != mlt_image_none  && format != self->format ) ) )
        {
                char *interps = mlt_properties_get( properties, "rescale.interp" );
                int interp = 0;
+               QImage *qimage = static_cast<QImage*>( self->qimage );
 
                // QImage has two scaling modes - we'll toggle between them here
-               if ( strcmp( interps, "tiles" ) == 0 )
-                       interp = 1;
-               else if ( strcmp( interps, "hyper" ) == 0 )
+               if ( strcmp( interps, "tiles" ) == 0
+                       || strcmp( interps, "hyper" ) == 0
+                       || strcmp( interps, "bicubic" ) == 0 )
                        interp = 1;
 
 #ifdef USE_QT4
@@ -269,10 +285,11 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh
                        QImage temp = qimage->convertToFormat( QImage::Format_RGB32 );
                        delete qimage;
                        qimage = new QImage( temp );
+                       self->qimage = qimage;
                }
                QImage scaled = interp == 0 ? qimage->scaled( QSize( width, height ) ) :
                        qimage->scaled( QSize(width, height), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
-               self->has_alpha = scaled.hasAlphaChannel();
+               int has_alpha = scaled.hasAlphaChannel();
 #endif
 
 #ifdef USE_QT3
@@ -287,9 +304,11 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh
                self->current_height = height;
 
                // Allocate/define image
-               int dst_stride = width * ( self->has_alpha ? 4 : 3 );
+               int dst_stride = width * ( has_alpha ? 4 : 3 );
                int image_size = dst_stride * ( height + 1 );
                self->current_image = ( uint8_t * )mlt_pool_alloc( image_size );
+               self->current_alpha = NULL;
+               self->format = has_alpha ? mlt_image_rgb24a : mlt_image_rgb24;
 
                // Copy the image
                int y = self->current_height + 1;
@@ -303,51 +322,55 @@ void refresh_qimage( producer_qimage self, mlt_frame frame, int width, int heigh
                                *dst++ = qRed(*src);
                                *dst++ = qGreen(*src);
                                *dst++ = qBlue(*src);
-                               if ( self->has_alpha ) *dst++ = qAlpha(*src);
+                               if ( has_alpha ) *dst++ = qAlpha(*src);
                                ++src;
                        }
                }
 
+               // Convert image to requested format
+               if ( format != mlt_image_none && format != self->format )
+               {
+                       uint8_t *buffer = NULL;
+
+                       // First, set the image so it can be converted when we get it
+                       mlt_frame_replace_image( frame, self->current_image, self->format, width, height );
+                       mlt_frame_set_image( frame, self->current_image, image_size, mlt_pool_release );
+                       self->format = format;
+
+                       // get_image will do the format conversion
+                       mlt_frame_get_image( frame, &buffer, &format, &width, &height, 0 );
+
+                       // cache copies of the image and alpha buffers
+                       if ( buffer )
+                       {
+                               image_size = mlt_image_format_size( format, width, height, NULL );
+                               self->current_image = (uint8_t*) mlt_pool_alloc( image_size );
+                               memcpy( self->current_image, buffer, image_size );
+                       }
+                       if ( ( buffer = mlt_frame_get_alpha_mask( frame ) ) )
+                       {
+                               self->current_alpha = (uint8_t*) mlt_pool_alloc( width * height );
+                               memcpy( self->current_alpha, buffer, width * height );
+                       }
+               }
+
                // Update the cache
-               if ( !use_cache )
-                       mlt_cache_item_close( self->image_cache );
+               mlt_cache_item_close( self->image_cache );
                mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "qimage.image", self->current_image, image_size, mlt_pool_release );
                self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "qimage.image" );
                self->image_idx = image_idx;
-
-               // 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 );
+               self->alpha_cache = NULL;
+               if ( self->current_alpha )
+               {
+                       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" );
+               }
        }
 
        // 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 ) * ( self->has_alpha ? 4 : 3 ),
-                       mlt_pool_release, NULL );
-               mlt_properties_set_int( cached_props, "alpha", self->has_alpha );
-               mlt_properties_set_data( cache, image_key, cached, 0, ( mlt_destructor )mlt_frame_close, NULL );
-       }
-       g_mutex.unlock();
 }
 
 extern void make_tempfile( producer_qimage self, const char *xml )
index b66924428900cbd7d60ad1c8e29410d3be83f000..7e4b7395421d44b33f1e964a8f6b8d44910b7f3a 100644 (file)
@@ -41,21 +41,23 @@ struct producer_qimage_s
        int image_idx;
        int qimage_idx;
        uint8_t *current_image;
-       int has_alpha;
+       uint8_t *current_alpha;
        int current_width;
        int current_height;
        mlt_cache_item image_cache;
-       pthread_mutex_t mutex;
+       mlt_cache_item alpha_cache;
+       mlt_cache_item qimage_cache;
+       void *qimage;
+       mlt_image_format format;
 };
 
 typedef struct producer_qimage_s *producer_qimage;
 
-extern void refresh_qimage( producer_qimage, mlt_frame, int width, int height );
+extern int refresh_qimage( producer_qimage self, mlt_frame frame );
+extern void refresh_image( producer_qimage, mlt_frame, mlt_image_format, int width, int height );
 extern void make_tempfile( producer_qimage, const char *xml );
-
-#ifdef USE_KDE
 extern void init_qimage();
-#endif
+
 
 #ifdef __cplusplus
 }
diff --git a/src/modules/qimage/transition_vqm.cpp b/src/modules/qimage/transition_vqm.cpp
new file mode 100644 (file)
index 0000000..d08a308
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * transition_vqm.c -- video quality measurement
+ * Copyright (c) 2012 Dan Dennedy <dan@dennedy.org>
+ * Core psnr and ssim routines based on code from
+ *   qsnr (C) 2010 E. Oriani, ema <AT> fastwebnet <DOT> it
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>
+ */
+
+#include <framework/mlt.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#include <QtGui/QtGui>
+
+static QApplication *app = 0;
+
+static double calc_psnr( const uint8_t *a, const uint8_t *b, int size, int bpp )
+{
+       double mse = 0.0;
+       int n = size + 1;
+
+       while ( --n )
+       {
+               int diff = *a - *b;
+               mse += diff * diff;
+               a += bpp;
+               b += bpp;
+       }
+
+       return 10.0 * log10( 255.0 * 255.0 / ( mse == 0 ? 1e-10 : mse/size ) );
+}
+
+static double calc_ssim( const uint8_t *a, const uint8_t *b, int width, int height, int window_size, int bpp )
+{
+       int     windows_x = width / window_size;
+       int windows_y = height / window_size;
+       double  avg = 0.0;
+
+       if ( !windows_x || !windows_y )
+               return 0.0;
+
+       // for each window
+       for ( int y = 0; y < windows_y; ++y )
+               for ( int x = 0; x < windows_x; ++x )
+               {
+                       int     base_offset = x * window_size + y * window_size * width;
+                       double  ref_acc = 0.0,
+                                       ref_acc_2 = 0.0,
+                                       cmp_acc = 0.0,
+                                       cmp_acc_2 = 0.0,
+                                       ref_cmp_acc = 0.0;
+
+                       // accumulate the pixel values for this window
+                       for ( int j = 0; j < window_size; ++j )
+                               for ( int i = 0; i < window_size; ++i )
+                               {
+                                       uint8_t c_a = a[bpp * (base_offset + j * width + i)];
+                                       uint8_t c_b = b[bpp * (base_offset + j * width + i)];
+                                       ref_acc += c_a;
+                                       ref_acc_2 += c_a * c_a;
+                                       cmp_acc += c_b;
+                                       cmp_acc_2 += c_b * c_b;
+                                       ref_cmp_acc += c_a * c_b;
+                               }
+
+                       // compute the SSIM for this window
+                       // http://en.wikipedia.org/wiki/SSIM
+                       // http://en.wikipedia.org/wiki/Variance
+                       // http://en.wikipedia.org/wiki/Covariance
+                       double n_samples = window_size * window_size,
+                                       ref_avg = ref_acc / n_samples,
+                                       ref_var = ref_acc_2 / n_samples - ref_avg * ref_avg,
+                                       cmp_avg = cmp_acc / n_samples,
+                                       cmp_var = cmp_acc_2 / n_samples - cmp_avg * cmp_avg,
+                                       ref_cmp_cov = ref_cmp_acc / n_samples - ref_avg * cmp_avg,
+                                       c1 = 6.5025, // (0.01*255.0)^2
+                                       c2 = 58.5225, // (0.03*255)^2
+                                       ssim_num = (2.0 * ref_avg * cmp_avg + c1) * (2.0 * ref_cmp_cov + c2),
+                                       ssim_den = (ref_avg * ref_avg + cmp_avg * cmp_avg + c1) * (ref_var + cmp_var + c2);
+
+                       // accumulate the SSIM
+                       avg += ssim_num / ssim_den;
+               }
+
+       // return the average SSIM
+       return avg / windows_x / windows_y;
+}
+
+static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       mlt_frame b_frame = mlt_frame_pop_frame( a_frame );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( a_frame );
+       mlt_transition transition = MLT_TRANSITION( mlt_frame_pop_service( a_frame ) );
+       uint8_t *b_image;
+       int window_size = mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "window_size" );
+       double psnr[3], ssim[3];
+
+       *format = mlt_image_yuv422;
+       mlt_frame_get_image( b_frame, &b_image, format, width, height, writable );
+       mlt_frame_get_image( a_frame, image, format, width, height, writable );
+
+       psnr[0] = calc_psnr( *image, b_image, *width * *height, 2 );
+       psnr[1] = calc_psnr( *image + 1, b_image + 1, *width * *height / 2, 4 );
+       psnr[2] = calc_psnr( *image + 3, b_image + 3, *width * *height / 2, 4 );
+       ssim[0] = calc_ssim( *image, b_image, *width, *height, window_size, 2 );
+       ssim[1] = calc_ssim( *image + 1, b_image + 1, *width / 2, *height, window_size, 4 );
+       ssim[2] = calc_ssim( *image + 3, b_image + 3, *width / 2, *height, window_size, 4 );
+       mlt_properties_set_double( properties, "meta.vqm.psnr.y", psnr[0] );
+       mlt_properties_set_double( properties, "meta.vqm.psnr.cb", psnr[1] );
+       mlt_properties_set_double( properties, "meta.vqm.psnr.cr", psnr[2] );
+       mlt_properties_set_double( properties, "meta.vqm.ssim.y", ssim[0] );
+       mlt_properties_set_double( properties, "meta.vqm.ssim.cb", ssim[1] );
+       mlt_properties_set_double( properties, "meta.vqm.ssim.cr", ssim[2] );
+       printf( "%05d %05.2f %05.2f %05.2f %5.3f %5.3f %5.3f\n",
+                       mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2],
+                       ssim[0], ssim[1], ssim[2] );
+
+       // copy the B frame to the bottom of the A frame for comparison
+       window_size = mlt_image_format_size( *format, *width, *height, NULL ) / 2;
+       memcpy( *image + window_size, b_image + window_size, window_size );
+
+       if ( !mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( transition ), "render" ) )
+               return 0;
+
+       // get RGBA image for Qt drawing
+       *format = mlt_image_rgb24a;
+       mlt_frame_get_image( a_frame, image, format, width, height, 1 );
+
+       // convert mlt image to qimage
+       QImage img( *width, *height, QImage::Format_ARGB32 );
+       int y = *height + 1;
+       uint8_t *src = *image;
+       while ( --y )
+       {
+               QRgb *dst = (QRgb*) img.scanLine( *height - y );
+               int x = *width + 1;
+               while ( --x )
+               {
+                       *dst++ = qRgba( src[0], src[1], src[2], 255 );
+                       src += 4;
+               }
+       }
+
+       // create QApplication, if needed
+       if ( !app )
+       {
+               if ( qApp )
+               {
+                       app = qApp;
+               }
+               else
+               {
+                       int argc = 1;
+                       char* argv[] = { strdup( "unknown" ) };
+
+                       app = new QApplication( argc, argv );
+                       const char *localename = mlt_properties_get_lcnumeric( MLT_TRANSITION_PROPERTIES(transition) );
+                       QLocale::setDefault( QLocale( localename ) );
+                       free( argv[0] );
+               }
+       }
+
+       // setup Qt drawing
+       QPainter painter;
+       painter.begin( &img );
+       painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing );
+
+       // draw some stuff with Qt
+       QPalette palette;
+       QFont font;
+       QString s;
+       font.setBold( true );
+       font.setPointSize( 30 * *height / 1080 );
+       painter.setPen( QColor("black") );
+       painter.drawLine( 0, *height/2 + 1, *width, *height/2 );
+       painter.setPen( QColor("white") );
+       painter.drawLine( 0, *height/2 - 1, *width, *height/2 );
+       painter.setFont( font );
+       s.sprintf( "Frame: %05d\nPSNR:   %05.2f (Y) %05.2f (Cb) %05.2f (Cr)\nSSIM:    %5.3f (Y) %5.3f (Cb) %5.3f (Cr)",
+                         mlt_frame_get_position( a_frame ), psnr[0], psnr[1], psnr[2],
+                         ssim[0], ssim[1], ssim[2] );
+       painter.setPen( QColor("black") );
+       painter.drawText( 52, *height * 8 / 10 + 2, *width, *height, 0, s );
+       painter.setPen( QColor("white") );
+       painter.drawText( 50, *height * 8 / 10, *width, *height, 0, s );
+
+       // finish Qt drawing
+       painter.end();
+       window_size = mlt_image_format_size( *format, *width, *height, NULL );
+       uint8_t *dst = (uint8_t *) mlt_pool_alloc( window_size );
+       mlt_properties_set_data( MLT_FRAME_PROPERTIES(a_frame), "image", dst, window_size, mlt_pool_release, NULL );
+       *image = dst;
+
+       // convert qimage to mlt
+       y = *height + 1;
+       while ( --y )
+       {
+               QRgb *src = (QRgb*) img.scanLine( *height - y );
+               int x = *width + 1;
+               while ( --x )
+               {
+                       *dst++ = qRed( *src );
+                       *dst++ = qGreen( *src );
+                       *dst++ = qBlue( *src );
+                       *dst++ = qAlpha( *src );
+                       src++;
+               }
+       }
+
+       return 0;
+}
+
+static mlt_frame process( mlt_transition transition, mlt_frame a_frame, mlt_frame b_frame )
+{
+       mlt_frame_push_service( a_frame, transition );
+       mlt_frame_push_frame( a_frame, b_frame );
+       mlt_frame_push_get_image( a_frame, get_image );
+
+       return a_frame;
+}
+
+extern "C" {
+
+mlt_transition transition_vqm_init( mlt_profile profile, mlt_service_type type, const char *id, void *arg )
+{
+       mlt_transition transition = mlt_transition_new();
+
+       if ( transition )
+       {
+               mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition );
+
+               transition->process = process;
+               mlt_properties_set_int( properties, "_transition_type", 1 ); // video only
+               mlt_properties_set_int( properties, "window_size", 8 );
+               printf( "frame psnr[Y] psnr[Cb] psnr[Cr] ssim[Y] ssim[Cb] ssim[Cr]\n" );
+       }
+
+       return transition;
+}
+
+} // extern "C"
diff --git a/src/modules/qimage/transition_vqm.yml b/src/modules/qimage/transition_vqm.yml
new file mode 100644 (file)
index 0000000..836cb72
--- /dev/null
@@ -0,0 +1,28 @@
+schema_version: 0.1
+type: transition
+identifier: vqm
+title: Video Quality Measurement
+version: 1
+copyright: Dan Dennedy
+creator: Dan Dennedy
+license: GPLv3
+language: en
+description: >
+  This performs the PSNR and SSIM video quality measurements by comparing the
+  B frames to the reference frame A.
+  It outputs the numbers to stdout in space-delimited format for easy
+  by another tool.
+  The bottom half of the B frame is placed below the top half of the A frame
+  for visual comparison.
+tags:
+  - Video
+parameters:
+  - identifier: render
+    title: Render
+    description: >
+      Render a line between top and bottom halves and the values atop the video.
+    type: integer
+    default: 0
+    minimum: 0
+    maximum: 1
+    widget: checkbox
index f2e8178189959f59e8e17d7ded501dc26e5d61a6..28545d51a4702a541a420e57bb20c4b38b3497b6 100644 (file)
@@ -30,9 +30,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/resample"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/resample"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/resample"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/resample"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 274fbd6714c6d2d02f0f1cd205964a9a38f2cc75..c2d56bdba902d1467c7aaac4171db6d3b9da3c4e 100644 (file)
@@ -55,25 +55,20 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        if ( error ) return error;
 
        // Return now if no work to do
-       if ( output_rate != *frequency )
+       if ( output_rate != *frequency && *frequency > 0 && *channels > 0 )
        {
                mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
                        *channels, *samples, *frequency, output_rate );
 
                // Do not convert to float unless we need to change the rate
-               if ( *format != mlt_audio_float )
-               {
-                       *format = mlt_audio_float;
-                       mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
-               }
+               if ( *format != mlt_audio_f32le )
+                       frame->convert_audio( frame, buffer, format, mlt_audio_f32le );
 
                mlt_service_lock( MLT_FILTER_SERVICE(filter) );
 
-               float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
-               float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
                SRC_DATA data;
-               data.data_in = input_buffer;
-               data.data_out = output_buffer;
+               data.data_in = *buffer;
+               data.data_out = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
                data.src_ratio = ( float ) output_rate / ( float ) *frequency;
                data.input_frames = *samples;
                data.output_frames = BUFFER_LEN / *channels;
@@ -88,44 +83,14 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                        mlt_properties_set_int( filter_properties, "channels", *channels );
                }
 
-               // Convert to interleaved
-               float *q = (float*) *buffer;
-               float *p = input_buffer;
-               int s, c;
-               for ( s = 0; s < *samples; s++ )
-                       for ( c = 0; c < *channels; c++ )
-                               *p++ = *( q + c * *samples + s );
-
                // Resample the audio
                error = src_process( state, &data );
                if ( !error )
                {
-                       int size = data.output_frames_gen * *channels * sizeof(float);
-
-                       // Resize if necessary
-                       if ( data.output_frames_gen > *samples )
-                       {
-                               *buffer = mlt_pool_realloc( *buffer, size );
-                               mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
-                       }
-
-                       // Convert to non-interleaved
-                       p = (float*) *buffer;
-                       for ( c = 0; c < *channels; c++ )
-                       {
-                               float *q = output_buffer + c;
-                               int i = data.output_frames_gen + 1;
-                               while ( --i  )
-                               {
-                                       *p++ = *q;
-                                       q += *channels;
-                               }
-                       }
-
                        // Update output variables
                        *samples = data.output_frames_gen;
                        *frequency = output_rate;
-
+                       *buffer = data.data_out;
                }
                else
                {
@@ -163,14 +128,12 @@ mlt_filter filter_resample_init( mlt_profile profile, mlt_service_type type, con
                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
index 782733ac6d189109d9e0188154f3aec41fdf8a2d..f3f2dec09473bfc417dac3d63f464b6674e3f25a 100644 (file)
@@ -30,9 +30,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d $(DESTDIR)$(datadir)/mlt/rotoscoping
-       install -m 644 filter_rotoscoping.yml "$(DESTDIR)$(datadir)/mlt/rotoscoping"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d $(DESTDIR)$(mltdatadir)/rotoscoping
+       install -m 644 filter_rotoscoping.yml "$(DESTDIR)$(mltdatadir)/rotoscoping"
 
 ifneq ($(wildcard .depend),)
 include .depend
index a5cabb41613304e55b677469c516d33b4473a62b..4a40bbe2f5cce1aadb6a99ad5724a13de50e9f50 100644 (file)
@@ -54,7 +54,7 @@ const char *ALPHAOPERATIONSTR[5] = { "clear", "max", "min", "add", "sub" };
 
 /** Returns the index of \param string in \param stringList.
  * Useful for assigning string parameters to enums. */
-int stringValue( const char *string, const char **stringList, int max )
+static int stringValue( const char *string, const char **stringList, int max )
 {
     int i;
     for ( i = 0; i < max; i++ )
@@ -72,7 +72,7 @@ static void rotoPropertyChanged( mlt_service owner, mlt_filter this, char *name
 }
 
 /** Linear interp */
-inline void lerp( const PointF *a, const PointF *b, PointF *result, double t )
+static inline void lerp( const PointF *a, const PointF *b, PointF *result, double t )
 {
     result->x = a->x + ( b->x - a->x ) * t;
     result->y = a->y + ( b->y - a->y ) * t;
@@ -80,7 +80,7 @@ inline void lerp( const PointF *a, const PointF *b, PointF *result, double t )
 
 /** Linear interp. with t = 0.5
  * Speed gain? */
-inline void lerpHalf( const PointF *a, const PointF *b, PointF *result )
+static inline void lerpHalf( const PointF *a, const PointF *b, PointF *result )
 {
     result->x = ( a->x + b->x ) * .5;
     result->y = ( a->y + b->y ) * .5;
@@ -93,7 +93,7 @@ int ncompare( const void *a, const void *b )
 }
 
 /** Turns a json array with two children into a point (x, y tuple). */
-void jsonGetPoint( cJSON *json, PointF *point )
+static void jsonGetPoint( cJSON *json, PointF *point )
 {
     if ( cJSON_GetArraySize( json ) == 2 )
     {
@@ -109,7 +109,7 @@ void jsonGetPoint( cJSON *json, PointF *point )
  * \param points pointer to array of points. Will be allocated and filled with the points in \param array
  * \return number of points
  */
-int json2BCurves( cJSON *array, BPointF **points )
+static int json2BCurves( cJSON *array, BPointF **points )
 {
     int count = cJSON_GetArraySize( array );
     cJSON *child = array->child;
@@ -134,7 +134,7 @@ int json2BCurves( cJSON *array, BPointF **points )
 }
 
 /** Blurs \param src horizontally. \See funtion blur. */
-void blurHorizontal( uint8_t *src, uint8_t *dst, int width, int height, int radius)
+static void blurHorizontal( uint8_t *src, uint8_t *dst, int width, int height, int radius)
 {
     int x, y, kx, yOff, total, amount, amountInit;
     amountInit = radius * 2 + 1;
@@ -167,7 +167,7 @@ void blurHorizontal( uint8_t *src, uint8_t *dst, int width, int height, int radi
 }
 
 /** Blurs \param src vertically. \See funtion blur. */
-void blurVertical( uint8_t *src, uint8_t *dst, int width, int height, int radius)
+static void blurVertical( uint8_t *src, uint8_t *dst, int width, int height, int radius)
 {
     int x, y, ky, total, amount, amountInit;
     amountInit = radius * 2 + 1;
@@ -202,7 +202,7 @@ void blurVertical( uint8_t *src, uint8_t *dst, int width, int height, int radius
  * \param radius blur radius
  * \param passes blur passes
  */
-void blur( uint8_t *map, int width, int height, int radius, int passes )
+static void blur( uint8_t *map, int width, int height, int radius, int passes )
 {
     uint8_t *src = mlt_pool_alloc( width * height );
     uint8_t *tmp = mlt_pool_alloc( width * height );
@@ -229,7 +229,7 @@ void blur( uint8_t *map, int width, int height, int radius, int passes )
  * \param map array of integers of the dimension width * height.
  *            The map entries belonging to the points in the polygon will be set to \param set * 255 the others to !set * 255.
  */
-void fillMap( PointF *vertices, int count, int width, int height, int invert, uint8_t *map )
+static void fillMap( PointF *vertices, int count, int width, int height, int invert, uint8_t *map )
 {
     int nodes, nodeX[1024], pixelY, i, j, value;
 
@@ -270,7 +270,7 @@ void fillMap( PointF *vertices, int count, int width, int height, int invert, ui
 /** Determines the point in the middle of the Bézier curve (t = 0.5) defined by \param p1 and \param p2
  * using De Casteljau's algorithm.
  */
-void deCasteljau( BPointF *p1, BPointF *p2, BPointF *mid )
+static void deCasteljau( BPointF *p1, BPointF *p2, BPointF *mid )
 {
     struct PointF ab, bc, cd;
 
@@ -292,7 +292,7 @@ void deCasteljau( BPointF *p1, BPointF *p2, BPointF *mid )
  * \param count Number of calculated points in \param points
  * \param size Allocated size of \param points (in elements not in bytes)
  */
-void curvePoints( BPointF p1, BPointF p2, PointF **points, int *count, int *size )
+static void curvePoints( BPointF p1, BPointF p2, PointF **points, int *count, int *size )
 {
     double errorSqr = SQR( p1.p.x - p2.p.x ) + SQR( p1.p.y - p2.p.y );
 
index d55c6c38562193cbfd5ffcfaddafbe157da64515..acada51fb38a957b42fe83b7990b1c6c272e4b96 100644 (file)
@@ -48,13 +48,13 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       #install -d "$(DESTDIR)$(datadir)/mlt/rtaudio"
-       #install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/rtaudio"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       #install -d "$(DESTDIR)$(mltdatadir)/rtaudio"
+       #install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/rtaudio"
 
 uninstall:
-       rm "$(DESTDIR)$(libdir)/mlt/libmltrtaudio$(LIBSUF)" 2> /dev/null || true
-       rm -rf "$(DESTDIR)$(datadir)/mlt/rtaudio"
+       rm "$(DESTDIR)$(moduledir)/libmltrtaudio$(LIBSUF)" 2> /dev/null || true
+       rm -rf "$(DESTDIR)$(mltdatadir)/rtaudio"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 2bdd89b9884bbc22d590d35fea9ab9e3f3eb17f2..422a78417b5a6eeaa008a37f9939f9fc4adc7ea8 100644 (file)
@@ -156,7 +156,7 @@ RtAudio :: RtAudio( RtAudio::Api api ) throw()
   getCompiledApi( apis );\r
   for ( unsigned int i=0; i<apis.size(); i++ ) {\r
     openRtApi( apis[i] );\r
-    if ( rtapi_->getDeviceCount() ) break;\r
+    if ( rtapi_ && rtapi_->getDeviceCount() ) break;\r
   }\r
 \r
   if ( rtapi_ ) return;\r
@@ -1193,7 +1193,7 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   // Allocate necessary internal buffers.\r
   unsigned long bufferBytes;\r
   bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  //  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  //  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) );\r
   memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
@@ -1218,7 +1218,7 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
@@ -2124,7 +2124,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   // Allocate necessary internal buffers.\r
   unsigned long bufferBytes;\r
   bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
     errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";\r
     goto error;\r
@@ -2146,7 +2146,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
@@ -2999,7 +2999,7 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   // Allocate necessary internal buffers\r
   unsigned long bufferBytes;\r
   bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
     errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory.";\r
     goto error;\r
@@ -3019,7 +3019,7 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
@@ -4216,7 +4216,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
 \r
   // Allocate necessary internal buffers\r
   long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
     errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory.";\r
     goto error;\r
@@ -4236,7 +4236,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
@@ -5848,7 +5848,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   // Allocate necessary internal buffers.\r
   unsigned long bufferBytes;\r
   bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
     errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory.";\r
     goto error;\r
@@ -5868,7 +5868,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
@@ -6858,7 +6858,7 @@ bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
   // Allocate necessary internal buffers.\r
   unsigned long bufferBytes;\r
   bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r
-  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r
+  stream_.userBuffer[mode] = (char *) calloc( 1, bufferBytes );\r
   if ( stream_.userBuffer[mode] == NULL ) {\r
     errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory.";\r
     goto error;\r
@@ -6878,7 +6878,7 @@ bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
     if ( makeBuffer ) {\r
       bufferBytes *= *bufferSize;\r
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r
-      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r
+      stream_.deviceBuffer = (char *) calloc( 1, bufferBytes );\r
       if ( stream_.deviceBuffer == NULL ) {\r
         errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory.";\r
         goto error;\r
index 2c254ef8e753910972491ca2be2dcc72975baac0..aa8904a7aed7dea8defcac78b5e063c0c512aeb3 100644 (file)
@@ -47,6 +47,7 @@
 #ifndef __RTAUDIO_H
 #define __RTAUDIO_H
 
+#include <string.h>
 #include <string>
 #include <vector>
 #include "RtError.h"
@@ -540,7 +541,7 @@ struct CallbackInfo {
 
   // Default constructor.
   CallbackInfo()
-    :object(0), callback(0), userData(0), apiInfo(0), isRunning(false) {}
+    :object(0), thread(0), callback(0), userData(0), apiInfo(0), isRunning(false) {}
 };
 
 // **************************************************************** //
@@ -651,7 +652,29 @@ protected:
 #endif
 
     RtApiStream()
-      :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; }
+       :apiHandle(0),
+       mode(OUTPUT),
+       state(STREAM_STOPPED),
+       deviceBuffer(0),
+       userInterleaved(0),
+       sampleRate(0),
+       bufferSize(0),
+       nBuffers(0),
+       streamTime(0)
+    {
+       device[0] = 11111;
+       device[1] = 11111;
+       memset( &channelOffset, 0, sizeof( channelOffset ) );
+       memset( &deviceFormat, 0, sizeof( deviceFormat ) );
+       memset( &deviceInterleaved, 0, sizeof( deviceInterleaved ) );
+       memset( &doByteSwap, 0, sizeof( doByteSwap ) );
+       memset( &doConvertBuffer, 0, sizeof( doConvertBuffer ) );
+       memset( &latency, 0, sizeof( latency ) );
+       memset( &nDeviceChannels, 0, sizeof( nDeviceChannels ) );
+       memset( &nUserChannels, 0, sizeof( nUserChannels ) );
+       memset( &userBuffer, 0, sizeof( userBuffer ) );
+       memset( &userFormat, 0, sizeof( userFormat ) );
+    }
   };
 
   typedef signed short Int16;
index f425fed0fce9638678850a9abc50976611d75c54..1526e335e964dbac888e31c813ad03077bfedfb0 100644 (file)
@@ -56,12 +56,15 @@ public:
 
        RtAudioConsumer()
                : device_id(-1)
+               , queue(NULL)
                , joined(0)
                , running(0)
                , audio_avail(0)
                , playing(0)
                , refresh_count(0)
-               {}
+       {
+               memset( &consumer, 0, sizeof( consumer ) );
+       }
 
        ~RtAudioConsumer()
        {
@@ -222,7 +225,10 @@ public:
                int64_t playtime = 0;
                struct timespec tm = { 0, 100000 };
        //      int last_position = -1;
+
+               pthread_mutex_lock( &refresh_mutex );
                refresh_count = 0;
+               pthread_mutex_unlock( &refresh_mutex );
 
                // Loop until told not to
                while ( running )
@@ -389,6 +395,7 @@ public:
                // 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" );
+               int scrub = mlt_properties_get_int( properties, "scrub_audio" );
                static int counter = 0;
                int samples = mlt_sample_calculator( mlt_properties_get_double( properties, "fps" ), frequency, counter++ );
                int16_t *pcm;
@@ -441,7 +448,7 @@ public:
                                pthread_cond_wait( &audio_cond, &audio_mutex );
                        if ( running )
                        {
-                               if ( mlt_properties_get_double( properties, "_speed" ) == 1 )
+                               if ( scrub || mlt_properties_get_double( properties, "_speed" ) == 1 )
                                        memcpy( &audio_buffer[ audio_avail ], pcm, bytes );
                                else
                                        memset( &audio_buffer[ audio_avail ], 0, bytes );
@@ -640,7 +647,7 @@ mlt_consumer consumer_rtaudio_init( mlt_profile profile, mlt_service_type type,
        if ( rtaudio && !mlt_consumer_init( rtaudio->getConsumer(), rtaudio, profile ) )
        {
                // If initialises without error
-               if ( rtaudio->open( arg ) )
+               if ( rtaudio->open( arg? arg : getenv( "AUDIODEV" ) ) )
                {
                        // Setup callbacks
                        consumer = rtaudio->getConsumer();
index 80ded0e1356ce8b5710c6468275c32bf7c71442b..c2b8cb21fcdf542c0c0cb1ad9b80b1feb3a6df4c 100644 (file)
@@ -42,3 +42,13 @@ parameters:
     type: integer
     minimum: 0
     maximum: 1
+
+  - identifier: scrub_audio
+    title: Audio scrubbing
+    type: integer
+    description: If enabled, sound is played even when the speed is not normal.
+    mutable: yes
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
index 6fab5d41ad7fb9b69f32b63f349367a7826d9c88..e368730c0226c74c02708ed876a3be0ec7c3f230 100644 (file)
@@ -52,9 +52,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/sdl"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/sdl"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/sdl"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/sdl"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 1f8b9ce4e9f2b86936cf70647fdbd8bf4bd6d77a..4d8ab8fc8b043b7baa2e9c69f508d30fe79bd347 100644 (file)
@@ -62,7 +62,6 @@ struct consumer_sdl_s
        int height;
        int playing;
        int sdl_flags;
-       SDL_Surface *sdl_screen;
        SDL_Overlay *sdl_overlay;
        SDL_Rect rect;
        uint8_t *buffer;
@@ -87,7 +86,7 @@ static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt
 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 );
+       consumer_sdl this = calloc( 1, sizeof( struct consumer_sdl_s ) );
 
        // If no malloc'd and consumer init ok
        if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
@@ -117,6 +116,7 @@ mlt_consumer consumer_sdl_init( mlt_profile profile, mlt_service_type type, cons
                // Default scaler (for now we'll use nearest)
                mlt_properties_set( this->properties, "rescale", "nearest" );
                mlt_properties_set( this->properties, "deinterlace_method", "onefield" );
+               mlt_properties_set_int( this->properties, "top_field_first", -1 );
 
                // Default buffer for low latency
                mlt_properties_set_int( this->properties, "buffer", 1 );
@@ -230,12 +230,6 @@ int consumer_start( mlt_consumer parent )
                        SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
                        SDL_EnableUNICODE( 1 );
                }
-               else if ( display_off == 0 )
-               {
-                       pthread_mutex_lock( &mlt_sdl_mutex );
-                       this->sdl_screen = SDL_GetVideoSurface( );
-                       pthread_mutex_unlock( &mlt_sdl_mutex );
-               }
 
                if ( audio_off == 0 )
                        SDL_InitSubSystem( SDL_INIT_AUDIO );
@@ -253,7 +247,8 @@ int consumer_start( mlt_consumer parent )
                        this->window_height = this->height;
                }
 
-               if ( this->sdl_screen == NULL && display_off == 0 )
+               pthread_mutex_lock( &mlt_sdl_mutex );
+               if ( !SDL_GetVideoSurface() && display_off == 0 )
                {
                        if ( mlt_properties_get_int( this->properties, "fullscreen" ) )
                        {
@@ -266,10 +261,9 @@ int consumer_start( mlt_consumer parent )
                                this->sdl_flags |= SDL_FULLSCREEN;
                                SDL_ShowCursor( SDL_DISABLE );
                        }
-                       pthread_mutex_lock( &mlt_sdl_mutex );
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
-                       pthread_mutex_unlock( &mlt_sdl_mutex );
+                       SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
                }
+               pthread_mutex_unlock( &mlt_sdl_mutex );
 
                pthread_create( &this->thread, NULL, consumer_thread, this );
        }
@@ -311,8 +305,6 @@ int consumer_stop( mlt_consumer parent )
                        SDL_Quit( );
                        pthread_mutex_unlock( &mlt_sdl_mutex );
                }
-
-               this->sdl_screen = NULL;
        }
 
        return 0;
@@ -513,7 +505,7 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                void *pool = mlt_cocoa_autorelease_init();
 
                // Handle events
-               if ( this->sdl_screen != NULL )
+               if ( SDL_GetVideoSurface() )
                {
                        SDL_Event event;
        
@@ -562,7 +554,7 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                        this->sdl_overlay = NULL;
                }
 
-               if ( this->running && ( this->sdl_screen == NULL || changed ) )
+               if ( this->running && ( !SDL_GetVideoSurface() || changed ) )
                {
                        // Force an overlay recreation
                        if ( this->sdl_overlay != NULL )
@@ -571,14 +563,17 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
 
                        // open SDL window with video overlay, if possible
                        pthread_mutex_lock( &mlt_sdl_mutex );
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
+                       SDL_Surface *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 );
+                               screen = SDL_SetVideoMode( this->window_width, this->window_height, this->bpp, this->sdl_flags );
                        pthread_mutex_unlock( &mlt_sdl_mutex );
 
-                       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 ( screen )
+                       {
+                               uint32_t color = mlt_properties_get_int( this->properties, "window_background" );
+                               SDL_FillRect( screen, NULL, color >> 8 );
+                               SDL_Flip( screen );
+                       }
                }
 
                if ( this->running )
@@ -637,16 +632,16 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                        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 );
+                       SDL_SetClipRect( SDL_GetVideoSurface(), &this->rect );
                }
 
-               if ( this->running && this->sdl_screen != NULL && this->sdl_overlay == NULL )
+               if ( this->running && SDL_GetVideoSurface() && this->sdl_overlay == NULL )
                {
-                       SDL_SetClipRect( this->sdl_screen, &this->rect );
-                       this->sdl_overlay = SDL_CreateYUVOverlay( width, height, SDL_YUY2_OVERLAY, this->sdl_screen );
+                       SDL_SetClipRect( SDL_GetVideoSurface(), &this->rect );
+                       this->sdl_overlay = SDL_CreateYUVOverlay( width, height, SDL_YUY2_OVERLAY, SDL_GetVideoSurface() );
                }
 
-               if ( this->running && this->sdl_screen != NULL && this->sdl_overlay != NULL )
+               if ( this->running && SDL_GetVideoSurface() && this->sdl_overlay != NULL )
                {
                        this->buffer = this->sdl_overlay->pixels[ 0 ];
                        if ( SDL_LockYUVOverlay( this->sdl_overlay ) >= 0 )
@@ -654,7 +649,7 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                                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_DisplayYUVOverlay( this->sdl_overlay, &SDL_GetVideoSurface()->clip_rect );
                        }
                }
 
@@ -868,7 +863,6 @@ static void *consumer_thread( void *arg )
        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;
index e59aae3c68868e9c875880274583a9f468daed10..31e71829edc5a3cd725edaefeb008a31aaaec1e4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * consumer_sdl_audio.c -- A Simple DirectMedia Layer audio-only consumer
- * Copyright (C) 2009, 2010 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -67,7 +67,7 @@ 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_refresh_cb( mlt_consumer sdl, mlt_consumer this, char *name );
+static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer self, char *name );
 
 /** This is what will be called by the factory - anything can be passed in
        via the argument, but keep it simple.
@@ -76,45 +76,46 @@ static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer this, char *name
 mlt_consumer consumer_sdl_audio_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 );
+       consumer_sdl self = calloc( 1, sizeof( struct consumer_sdl_s ) );
 
        // If no malloc'd and consumer init ok
-       if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
+       if ( self != NULL && mlt_consumer_init( &self->parent, self, profile ) == 0 )
        {
                // Create the queue
-               this->queue = mlt_deque_init( );
+               self->queue = mlt_deque_init( );
 
                // Get the parent consumer object
-               mlt_consumer parent = &this->parent;
+               mlt_consumer parent = &self->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 );
+               self->properties = MLT_SERVICE_PROPERTIES( service );
 
                // Set the default volume
-               mlt_properties_set_double( this->properties, "volume", 1.0 );
+               mlt_properties_set_double( self->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);
+               pthread_mutex_init( &self->audio_mutex, NULL );
+               pthread_cond_init( &self->audio_cond, NULL);
+               pthread_mutex_init( &self->video_mutex, NULL );
+               pthread_cond_init( &self->video_cond, NULL);
 
                // Default scaler (for now we'll use nearest)
-               mlt_properties_set( this->properties, "rescale", "nearest" );
-               mlt_properties_set( this->properties, "deinterlace_method", "onefield" );
+               mlt_properties_set( self->properties, "rescale", "nearest" );
+               mlt_properties_set( self->properties, "deinterlace_method", "onefield" );
+               mlt_properties_set_int( self->properties, "top_field_first", -1 );
 
                // Default buffer for low latency
-               mlt_properties_set_int( this->properties, "buffer", 1 );
+               mlt_properties_set_int( self->properties, "buffer", 1 );
 
                // Default audio buffer
-               mlt_properties_set_int( this->properties, "audio_buffer", 2048 );
+               mlt_properties_set_int( self->properties, "audio_buffer", 2048 );
 
                // Ensure we don't join on a non-running object
-               this->joined = 1;
+               self->joined = 1;
                
                // Allow thread to be started/stopped
                parent->start = consumer_start;
@@ -122,16 +123,16 @@ mlt_consumer consumer_sdl_audio_init( mlt_profile profile, mlt_service_type type
                parent->is_stopped = consumer_is_stopped;
 
                // Initialize the refresh handler
-               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 );
+               pthread_cond_init( &self->refresh_cond, NULL );
+               pthread_mutex_init( &self->refresh_mutex, NULL );
+               mlt_events_listen( MLT_CONSUMER_PROPERTIES( parent ), self, "property-changed", ( mlt_listener )consumer_refresh_cb );
 
                // Return the consumer produced
                return parent;
        }
 
        // malloc or consumer init failed
-       free( this );
+       free( self );
 
        // Indicate failure
        return NULL;
@@ -141,19 +142,20 @@ static void consumer_refresh_cb( mlt_consumer sdl, mlt_consumer parent, char *na
 {
        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 + 1;
-               pthread_cond_broadcast( &this->refresh_cond );
-               pthread_mutex_unlock( &this->refresh_mutex );
+               consumer_sdl self = parent->child;
+               pthread_mutex_lock( &self->refresh_mutex );
+               if ( self->refresh_count < 2 )
+                       self->refresh_count = self->refresh_count <= 0 ? 1 : self->refresh_count + 1;
+               pthread_cond_broadcast( &self->refresh_cond );
+               pthread_mutex_unlock( &self->refresh_mutex );
        }
 }
 
 int consumer_start( mlt_consumer parent )
 {
-       consumer_sdl this = parent->child;
+       consumer_sdl self = parent->child;
 
-       if ( !this->running )
+       if ( !self->running )
        {
                consumer_stop( parent );
 
@@ -166,9 +168,9 @@ int consumer_start( mlt_consumer parent )
                        return -1;
                }
 
-               this->running = 1;
-               this->joined = 0;
-               pthread_create( &this->thread, NULL, consumer_thread, this );
+               self->running = 1;
+               self->joined = 0;
+               pthread_create( &self->thread, NULL, consumer_thread, self );
        }
 
        return 0;
@@ -177,34 +179,34 @@ int consumer_start( mlt_consumer parent )
 int consumer_stop( mlt_consumer parent )
 {
        // Get the actual object
-       consumer_sdl this = parent->child;
+       consumer_sdl self = parent->child;
 
-       if ( this->running && !this->joined )
+       if ( self->running && !self->joined )
        {
                // Kill the thread and clean up
-               this->joined = 1;
-               this->running = 0;
+               self->joined = 1;
+               self->running = 0;
 
                // Unlatch the consumer thread
-               pthread_mutex_lock( &this->refresh_mutex );
-               pthread_cond_broadcast( &this->refresh_cond );
-               pthread_mutex_unlock( &this->refresh_mutex );
+               pthread_mutex_lock( &self->refresh_mutex );
+               pthread_cond_broadcast( &self->refresh_cond );
+               pthread_mutex_unlock( &self->refresh_mutex );
 
                // Cleanup the main thread
 #ifndef WIN32
-               if ( this->thread )
+               if ( self->thread )
 #endif
-                       pthread_join( this->thread, NULL );
+                       pthread_join( self->thread, NULL );
 
                // Unlatch the video thread
-               pthread_mutex_lock( &this->video_mutex );
-               pthread_cond_broadcast( &this->video_cond );
-               pthread_mutex_unlock( &this->video_mutex );
+               pthread_mutex_lock( &self->video_mutex );
+               pthread_cond_broadcast( &self->video_cond );
+               pthread_mutex_unlock( &self->video_mutex );
 
                // Unlatch the audio callback
-               pthread_mutex_lock( &this->audio_mutex );
-               pthread_cond_broadcast( &this->audio_cond );
-               pthread_mutex_unlock( &this->audio_mutex );
+               pthread_mutex_lock( &self->audio_mutex );
+               pthread_cond_broadcast( &self->audio_cond );
+               pthread_mutex_unlock( &self->audio_mutex );
 
                SDL_QuitSubSystem( SDL_INIT_AUDIO );
        }
@@ -214,68 +216,72 @@ int consumer_stop( mlt_consumer parent )
 
 int consumer_is_stopped( mlt_consumer parent )
 {
-       consumer_sdl this = parent->child;
-       return !this->running;
+       consumer_sdl self = parent->child;
+       return !self->running;
 }
 
 static void sdl_fill_audio( void *udata, uint8_t *stream, int len )
 {
-       consumer_sdl this = udata;
+       consumer_sdl self = udata;
 
        // Get the volume
-       double volume = mlt_properties_get_double( this->properties, "volume" );
+       double volume = mlt_properties_get_double( self->properties, "volume" );
 
-       pthread_mutex_lock( &this->audio_mutex );
+       pthread_mutex_lock( &self->audio_mutex );
 
        // Block until audio received
-       while ( this->running && len > this->audio_avail )
-               pthread_cond_wait( &this->audio_cond, &this->audio_mutex );
+#ifdef __DARWIN__
+       while ( self->running && len > self->audio_avail )
+               pthread_cond_wait( &self->audio_cond, &self->audio_mutex );
+#endif
 
-       if ( this->audio_avail >= len )
+       if ( self->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 ) );
+                       SDL_MixAudio( stream, self->audio_buffer, len, ( int )( ( float )SDL_MIX_MAXVOLUME * volume ) );
                else
-                       memcpy( stream, this->audio_buffer, len );
+                       memcpy( stream, self->audio_buffer, len );
 
                // Remove len from the audio available
-               this->audio_avail -= len;
+               self->audio_avail -= len;
 
                // Remove the samples
-               memmove( this->audio_buffer, this->audio_buffer + len, this->audio_avail );
+               memmove( self->audio_buffer, self->audio_buffer + len, self->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 ) );
+               // Mix the audio
+               SDL_MixAudio( stream, self->audio_buffer, self->audio_avail,
+                       ( int )( ( float )SDL_MIX_MAXVOLUME * volume ) );
 
                // No audio left
-               this->audio_avail = 0;
+               self->audio_avail = 0;
        }
 
        // We're definitely playing now
-       this->playing = 1;
+       self->playing = 1;
 
-       pthread_cond_broadcast( &this->audio_cond );
-       pthread_mutex_unlock( &this->audio_mutex );
+       pthread_cond_broadcast( &self->audio_cond );
+       pthread_mutex_unlock( &self->audio_mutex );
 }
 
-static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_audio, int *duration )
+static int consumer_play_audio( consumer_sdl self, mlt_frame frame, int init_audio, int *duration )
 {
        // Get the properties of this consumer
-       mlt_properties properties = this->properties;
+       mlt_properties properties = self->properties;
        mlt_audio_format afmt = mlt_audio_s16;
 
        // 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" );
+       int scrub = mlt_properties_get_int( properties, "scrub_audio" );
        static int counter = 0;
 
-       int samples = mlt_sample_calculator( mlt_properties_get_double( this->properties, "fps" ), frequency, counter++ );
+       int samples = mlt_sample_calculator( mlt_properties_get_double( self->properties, "fps" ), frequency, counter++ );
        
        int16_t *pcm;
        int bytes;
@@ -285,7 +291,7 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud
 
        if ( mlt_properties_get_int( properties, "audio_off" ) )
        {
-               this->playing = 1;
+               self->playing = 1;
                init_audio = 1;
                return init_audio;
        }
@@ -299,16 +305,16 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud
 
                // specify audio format
                memset( &request, 0, sizeof( SDL_AudioSpec ) );
-               this->playing = 0;
+               self->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;
+               request.userdata = (void *)self;
                if ( SDL_OpenAudio( &request, &got ) != 0 )
                {
-                       mlt_log_error( MLT_CONSUMER_SERVICE( this ), "SDL failed to open audio: %s\n", SDL_GetError() );
+                       mlt_log_error( MLT_CONSUMER_SERVICE( self ), "SDL failed to open audio: %s\n", SDL_GetError() );
                        init_audio = 2;
                }
                else if ( got.size != 0 )
@@ -322,33 +328,33 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud
        {
                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 )
+               pthread_mutex_lock( &self->audio_mutex );
+               while ( self->running && bytes > ( sizeof( self->audio_buffer) - self->audio_avail ) )
+                       pthread_cond_wait( &self->audio_cond, &self->audio_mutex );
+               if ( self->running )
                {
-                       if ( mlt_properties_get_double( properties, "_speed" ) == 1 )
-                               memcpy( &this->audio_buffer[ this->audio_avail ], pcm, bytes );
+                       if ( scrub || mlt_properties_get_double( properties, "_speed" ) == 1 )
+                               memcpy( &self->audio_buffer[ self->audio_avail ], pcm, bytes );
                        else
-                               memset( &this->audio_buffer[ this->audio_avail ], 0, bytes );
-                       this->audio_avail += bytes;
+                               memset( &self->audio_buffer[ self->audio_avail ], 0, bytes );
+                       self->audio_avail += bytes;
                }
-               pthread_cond_broadcast( &this->audio_cond );
-               pthread_mutex_unlock( &this->audio_mutex );
+               pthread_cond_broadcast( &self->audio_cond );
+               pthread_mutex_unlock( &self->audio_mutex );
        }
        else
        {
-               this->playing = 1;
+               self->playing = 1;
        }
 
        return init_audio;
 }
 
-static int consumer_play_video( consumer_sdl this, mlt_frame frame )
+static int consumer_play_video( consumer_sdl self, mlt_frame frame )
 {
        // Get the properties of this consumer
-       mlt_properties properties = this->properties;
-       if ( this->running && !mlt_consumer_is_stopped( &this->parent ) )
+       mlt_properties properties = self->properties;
+       if ( self->running && !mlt_consumer_is_stopped( &self->parent ) )
                mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
 
        return 0;
@@ -357,7 +363,7 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
 static void *video_thread( void *arg )
 {
        // Identify the arg
-       consumer_sdl this = arg;
+       consumer_sdl self = arg;
 
        // Obtain time of thread start
        struct timeval now;
@@ -369,7 +375,7 @@ static void *video_thread( void *arg )
        double speed = 0;
 
        // Get real time flag
-       int real_time = mlt_properties_get_int( this->properties, "real_time" );
+       int real_time = mlt_properties_get_int( self->properties, "real_time" );
 
        // Get the current time
        gettimeofday( &now, NULL );
@@ -377,19 +383,19 @@ static void *video_thread( void *arg )
        // Determine start time
        start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
 
-       while ( this->running )
+       while ( self->running )
        {
                // Pop the next frame
-               pthread_mutex_lock( &this->video_mutex );
-               next = mlt_deque_pop_front( this->queue );
-               while ( next == NULL && this->running )
+               pthread_mutex_lock( &self->video_mutex );
+               next = mlt_deque_pop_front( self->queue );
+               while ( next == NULL && self->running )
                {
-                       pthread_cond_wait( &this->video_cond, &this->video_mutex );
-                       next = mlt_deque_pop_front( this->queue );
+                       pthread_cond_wait( &self->video_cond, &self->video_mutex );
+                       next = mlt_deque_pop_front( self->queue );
                }
-               pthread_mutex_unlock( &this->video_mutex );
+               pthread_mutex_unlock( &self->video_mutex );
 
-               if ( !this->running || next == NULL ) break;
+               if ( !self->running || next == NULL ) break;
 
                // Get the properties
                properties =  MLT_FRAME_PROPERTIES( next );
@@ -404,7 +410,7 @@ static void *video_thread( void *arg )
                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 )
+               if ( mlt_properties_get_int( properties, "rendered" ) == 1 && self->running )
                {
                        // Obtain the scheduled playout time
                        int64_t scheduled = mlt_properties_get_int( properties, "playtime" );
@@ -421,11 +427,11 @@ static void *video_thread( void *arg )
                        }
 
                        // 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 ( !real_time || ( difference > -10000 || speed != 1.0 || mlt_deque_count( self->queue ) < 2 ) )
+                               consumer_play_video( self, 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 ) )
+                       if ( real_time && ( mlt_deque_count( self->queue ) == 0 && speed == 1.0 ) )
                        {
                                gettimeofday( &now, NULL );
                                start = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - scheduled + 20000;
@@ -440,7 +446,7 @@ static void *video_thread( void *arg )
        if ( next != NULL )
                mlt_frame_close( next );
 
-       mlt_consumer_stopped( &this->parent );
+       mlt_consumer_stopped( &self->parent );
 
        return NULL;
 }
@@ -451,10 +457,10 @@ static void *video_thread( void *arg )
 static void *consumer_thread( void *arg )
 {
        // Identify the arg
-       consumer_sdl this = arg;
+       consumer_sdl self = arg;
 
        // Get the consumer
-       mlt_consumer consumer = &this->parent;
+       mlt_consumer consumer = &self->parent;
 
        // Get the properties
        mlt_properties consumer_props = MLT_CONSUMER_PROPERTIES( consumer );
@@ -471,10 +477,13 @@ static void *consumer_thread( void *arg )
        int64_t playtime = 0;
        struct timespec tm = { 0, 100000 };
 //     int last_position = -1;
-       this->refresh_count = 0;
+
+       pthread_mutex_lock( &self->refresh_mutex );
+       self->refresh_count = 0;
+       pthread_mutex_unlock( &self->refresh_mutex );
 
        // Loop until told not to
-       while( this->running )
+       while( self->running )
        {
                // Get a frame from the attached producer
                frame = mlt_consumer_rt_frame( consumer );
@@ -497,13 +506,13 @@ static void *consumer_thread( void *arg )
                        mlt_events_unblock( consumer_props, consumer_props );
 
                        // Play audio
-                       init_audio = consumer_play_audio( this, frame, init_audio, &duration );
+                       init_audio = consumer_play_audio( self, frame, init_audio, &duration );
 
                        // Determine the start time now
-                       if ( this->playing && init_video )
+                       if ( self->playing && init_video )
                        {
                                // Create the video thread
-                               pthread_create( &thread, NULL, video_thread, this );
+                               pthread_create( &thread, NULL, video_thread, self );
 
                                // Video doesn't need to be initialised any more
                                init_video = 0;
@@ -512,31 +521,31 @@ static void *consumer_thread( void *arg )
                        // Set playtime for this frame
                        mlt_properties_set_int( properties, "playtime", playtime );
 
-                       while ( this->running && speed != 0 && mlt_deque_count( this->queue ) > 15 )
+                       while ( self->running && speed != 0 && mlt_deque_count( self->queue ) > 15 )
                                nanosleep( &tm, NULL );
 
                        // Push this frame to the back of the queue
-                       if ( this->running && speed )
+                       if ( self->running && speed )
                        {
-                               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 );
+                               pthread_mutex_lock( &self->video_mutex );
+                               mlt_deque_push_back( self->queue, frame );
+                               pthread_cond_broadcast( &self->video_cond );
+                               pthread_mutex_unlock( &self->video_mutex );
 
                                // Calculate the next playtime
                                playtime += ( duration * 1000 );
                        }
-                       else if ( this->running )
+                       else if ( self->running )
                        {
-                               pthread_mutex_lock( &this->refresh_mutex );
-                               if ( refresh == 0 && this->refresh_count <= 0 )
+                               pthread_mutex_lock( &self->refresh_mutex );
+                               if ( ( refresh == 0 && self->refresh_count <= 0 ) || self->refresh_count > 1 )
                                {
-                                       consumer_play_video( this, frame );
-                                       pthread_cond_wait( &this->refresh_cond, &this->refresh_mutex );
+                                       consumer_play_video( self, frame );
+                                       pthread_cond_wait( &self->refresh_cond, &self->refresh_mutex );
                                }
                                mlt_frame_close( frame );
-                               this->refresh_count --;
-                               pthread_mutex_unlock( &this->refresh_mutex );
+                               self->refresh_count --;
+                               pthread_mutex_unlock( &self->refresh_mutex );
                        }
                        else
                        {
@@ -563,16 +572,16 @@ static void *consumer_thread( void *arg )
        // 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_mutex_lock( &self->video_mutex );
+               pthread_cond_broadcast( &self->video_cond );
+               pthread_mutex_unlock( &self->video_mutex );
                pthread_join( thread, NULL );
        }
 
-       while( mlt_deque_count( this->queue ) )
-               mlt_frame_close( mlt_deque_pop_back( this->queue ) );
+       while( mlt_deque_count( self->queue ) )
+               mlt_frame_close( mlt_deque_pop_back( self->queue ) );
 
-       this->audio_avail = 0;
+       self->audio_avail = 0;
 
        return NULL;
 }
@@ -583,7 +592,7 @@ static void *consumer_thread( void *arg )
 static void consumer_close( mlt_consumer parent )
 {
        // Get the actual object
-       consumer_sdl this = parent->child;
+       consumer_sdl self = parent->child;
 
        // Stop the consumer
        mlt_consumer_stop( parent );
@@ -592,16 +601,16 @@ static void consumer_close( mlt_consumer parent )
        mlt_consumer_close( parent );
 
        // Close the queue
-       mlt_deque_close( this->queue );
+       mlt_deque_close( self->queue );
 
        // Destroy mutexes
-       pthread_mutex_destroy( &this->audio_mutex );
-       pthread_cond_destroy( &this->audio_cond );
-       pthread_mutex_destroy( &this->video_mutex );
-       pthread_cond_destroy( &this->video_cond );
-       pthread_mutex_destroy( &this->refresh_mutex );
-       pthread_cond_destroy( &this->refresh_cond );
+       pthread_mutex_destroy( &self->audio_mutex );
+       pthread_cond_destroy( &self->audio_cond );
+       pthread_mutex_destroy( &self->video_mutex );
+       pthread_cond_destroy( &self->video_cond );
+       pthread_mutex_destroy( &self->refresh_mutex );
+       pthread_cond_destroy( &self->refresh_cond );
 
        // Finally clean up this
-       free( this );
+       free( self );
 }
index 2e1d802c816e967377b153c2e3eae34a84de6041..834261fcaab0b7b0ce9bbdd2b3f86899a0ae61ad 100644 (file)
@@ -9,3 +9,40 @@ license: LGPLv2.1
 language: en
 tags:
   - Audio
+description: >
+  Simple DirectMedia Layer audio only output module.
+
+parameters:
+  - identifier: volume
+    title: Volume
+    type: float
+    description: Audio level factor.
+    mutable: yes
+
+  - identifier: audio_off
+    title: Audio off
+    type: integer
+    description: If 1, disable audio output
+    mutable: yes
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
+
+  - identifier: audio_buffer
+    title: Audio buffer
+    type: integer
+    description: Size of the sdl audio buffer.
+    mutable: yes
+    default: 2048
+    minimum: 128
+
+  - identifier: scrub_audio
+    title: Audio scrubbing
+    type: integer
+    description: If enabled, sound is played even when the speed is not normal.
+    mutable: yes
+    minimum: 0
+    maximum: 1
+    default: 0
+    widget: checkbox
index bd5fe3661473a8ab2cafc24ad795b6f4974bdc9a..3d7e222991eed9be8fa6feb74517842399eb71ef 100644 (file)
@@ -67,7 +67,7 @@ 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 );
+       consumer_sdl this = calloc( 1, sizeof( struct consumer_sdl_s ) );
        if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
        {
                // Get the parent consumer object
@@ -93,6 +93,8 @@ mlt_consumer consumer_sdl_preview_init( mlt_profile profile, mlt_service_type ty
                mlt_properties_set( properties, "rescale", "nearest" );
                mlt_properties_set( properties, "deinterlace_method", "onefield" );
                mlt_properties_set_int( properties, "prefill", 1 );
+               mlt_properties_set_int( properties, "top_field_first", -1 );
+
                parent->close = consumer_close;
                parent->start = consumer_start;
                parent->stop = consumer_stop;
@@ -199,9 +201,10 @@ static int consumer_start( mlt_consumer parent )
 
                mlt_properties_pass_list( play, properties,
                        "deinterlace_method,resize,rescale,width,height,aspect_ratio,display_ratio,preview_off,preview_format,window_background"
-                       ",volume,real_time,buffer,prefill,audio_off,frequency,drop_max" );
+                       ",top_field_first,volume,real_time,buffer,prefill,audio_off,frequency,drop_max" );
                mlt_properties_pass_list( still, properties,
-                       "deinterlace_method,resize,rescale,width,height,aspect_ratio,display_ratio,preview_off,preview_format,window_background" );
+                       "deinterlace_method,resize,rescale,width,height,aspect_ratio,display_ratio,preview_off,preview_format,window_background"
+                       ",top_field_first");
 
                mlt_properties_pass( play, properties, "play." );
                mlt_properties_pass( still, properties, "still." );
@@ -287,12 +290,16 @@ static void *consumer_thread( void *arg )
        mlt_frame frame = NULL;
        int last_position = -1;
        int eos = 0;
-       int eos_threshold = 20 + mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( this->play ), "buffer" );
+       int eos_threshold = 20;
+       if ( this->play )
+               eos_threshold = eos_threshold + mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( this->play ), "buffer" );
 
        // Determine if the application is dealing with the preview
        int preview_off = mlt_properties_get_int( properties, "preview_off" );
 
+       pthread_mutex_lock( &this->refresh_mutex );
        this->refresh_count = 0;
+       pthread_mutex_unlock( &this->refresh_mutex );
 
        // Loop until told not to
        while( this->running )
@@ -425,7 +432,8 @@ static void *consumer_thread( void *arg )
                                        this->ignore_change = 0;
                                        mlt_consumer_start( this->play );
                                }
-                               mlt_consumer_put_frame( this->play, frame );
+                               if ( this->play )
+                                       mlt_consumer_put_frame( this->play, frame );
                        }
 
                        // Copy the rectangle info from the active consumer
index 1ef82b8766556e53e71b8e1bb4ccfdd2bb9da2e9..725165b70a5bee8a629a65d1aedeb388c1e1a10c 100644 (file)
@@ -53,7 +53,6 @@ struct consumer_sdl_s
        int height;
        int playing;
        int sdl_flags;
-       SDL_Surface *sdl_screen;
        SDL_Rect rect;
        uint8_t *buffer;
        int last_position;
@@ -78,7 +77,7 @@ static void consumer_sdl_event( mlt_listener listener, mlt_properties owner, mlt
 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 );
+       consumer_sdl this = calloc( 1, sizeof( struct consumer_sdl_s ) );
 
        // If no malloc'd and consumer init ok
        if ( this != NULL && mlt_consumer_init( &this->parent, this, profile ) == 0 )
@@ -180,23 +179,11 @@ static int consumer_start( mlt_consumer parent )
                        SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
                        SDL_EnableUNICODE( 1 );
                }
-               else if ( preview_off == 0 )
-               {
-                       pthread_mutex_lock( &mlt_sdl_mutex );
-                       SDL_Surface *screen = SDL_GetVideoSurface( );
-                       pthread_mutex_unlock( &mlt_sdl_mutex );
-                       if ( screen != NULL )
-                       {
-                               this->sdl_screen = screen;
-                       }
-               }
 
-               if ( this->sdl_screen == NULL && preview_off == 0 )
-               {
-                       pthread_mutex_lock( &mlt_sdl_mutex );
-                       this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
-                       pthread_mutex_unlock( &mlt_sdl_mutex );
-               }
+               pthread_mutex_lock( &mlt_sdl_mutex );
+               if ( !SDL_GetVideoSurface() && preview_off == 0 )
+                       SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
+               pthread_mutex_unlock( &mlt_sdl_mutex );
 
                pthread_create( &this->thread, NULL, consumer_thread, this );
        }
@@ -226,8 +213,6 @@ static int consumer_stop( mlt_consumer parent )
                        SDL_Quit( );
                        pthread_mutex_unlock( &mlt_sdl_mutex );
                }
-
-               this->sdl_screen = NULL;
        }
 
        return 0;
@@ -401,7 +386,7 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
        sdl_lock_display();
        
        // Handle events
-       if ( this->sdl_screen != NULL )
+       if ( SDL_GetVideoSurface() )
        {
                SDL_Event event;
 
@@ -439,18 +424,18 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                }
        }
 
-       if ( this->sdl_screen == NULL || changed )
+       if ( !SDL_GetVideoSurface() || changed )
        {
                // open SDL window
                pthread_mutex_lock( &mlt_sdl_mutex );
-               this->sdl_screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
+               SDL_Surface *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 );
+                       screen = SDL_SetVideoMode( this->window_width, this->window_height, 0, this->sdl_flags );
 
-               uint32_t color = mlt_properties_get_int( this->properties, "window_background" );
-               if ( this->sdl_screen )
+               if ( screen )
                {
-                       SDL_FillRect( this->sdl_screen, NULL, color >> 8 );
+                       uint32_t color = mlt_properties_get_int( this->properties, "window_background" );
+                       SDL_FillRect( screen, NULL, color >> 8 );
                        changed = 1;
                }
                pthread_mutex_unlock( &mlt_sdl_mutex );
@@ -513,29 +498,29 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
        
        pthread_mutex_lock( &mlt_sdl_mutex );
        SDL_Surface *screen = SDL_GetVideoSurface( );
-       if ( !mlt_consumer_is_stopped( &this->parent ) && screen != NULL && this->sdl_screen != NULL && this->sdl_screen->pixels != NULL )
+       if ( !mlt_consumer_is_stopped( &this->parent ) && screen && screen->pixels )
        {
-               switch( this->sdl_screen->format->BytesPerPixel )
+               switch( screen->format->BytesPerPixel )
                {
                        case 1:
-                               display_1( this->sdl_screen, this->rect, image, width, height );
+                               display_1( screen, this->rect, image, width, height );
                                break;
                        case 2:
-                               display_2( this->sdl_screen, this->rect, image, width, height );
+                               display_2( screen, this->rect, image, width, height );
                                break;
                        case 3:
-                               display_3( this->sdl_screen, this->rect, image, width, height );
+                               display_3( screen, this->rect, image, width, height );
                                break;
                        case 4:
-                               display_4( this->sdl_screen, this->rect, image, width, height );
+                               display_4( screen, this->rect, image, width, height );
                                break;
                        default:
-                               fprintf( stderr, "Unsupported video depth %d\n", this->sdl_screen->format->BytesPerPixel );
+                               fprintf( stderr, "Unsupported video depth %d\n", screen->format->BytesPerPixel );
                                break;
                }
 
                // Flip it into sight
-               SDL_Flip( this->sdl_screen );
+               SDL_Flip( screen );
        }
        pthread_mutex_unlock( &mlt_sdl_mutex );
 
index 2890ad319acecfee100447dd95cd921d26838720..6bee9ee2130ef1197c08a73ce27e7ee13ff453d3 100644 (file)
@@ -157,8 +157,8 @@ static SDL_Surface *load_image( mlt_producer producer )
                                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 );
+                               mlt_properties_set_int( properties, "meta.media.width", surface->w );
+                               mlt_properties_set_int( properties, "meta.media.height", surface->h );
                        }
                }
                else if ( surface != NULL )
@@ -195,8 +195,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                        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 );
index d810b03e9da85069c6f26d79ef7b8d38f7a84fde..7205014ed050ed6578362ce971127f17788b4386 100644 (file)
@@ -7,5 +7,6 @@ copyright: Visual Media FX ?
 creator: Charles Yates
 license: LGPLv2.1
 language: en
+notes: DEPRECATED
 tags:
   - Video
index 19ba02d8fe6304a9b758efb3f4b94adca103dcd5..fda50a32dd125a00af2b7b296feaa948f196a2bf 100644 (file)
@@ -28,14 +28,14 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/sox"
-       install -m 644 filter_sox.yml "$(DESTDIR)$(datadir)/mlt/sox"
-       install -m 644 filter_sox_effect.yml "$(DESTDIR)$(datadir)/mlt/sox"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/sox"
+       install -m 644 filter_sox.yml "$(DESTDIR)$(mltdatadir)/sox"
+       install -m 644 filter_sox_effect.yml "$(DESTDIR)$(mltdatadir)/sox"
 
 uninstall:
-       rm "$(DESTDIR)$(libdir)/mlt/libmltsox$(LIBSUF)" 2> /dev/null || true
-       rm -rf "$(DESTDIR)$(datadir)/mlt/sox"
+       rm "$(DESTDIR)$(moduledir)/libmltsox$(LIBSUF)" 2> /dev/null || true
+       rm -rf "$(DESTDIR)$(mltdatadir)/sox"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 3739526a46fdbdf4836ffd5590857626f53104eb..004c2be8a83c21818044e91599dc0b3e4b4f884a 100644 (file)
@@ -100,7 +100,10 @@ static int create_effect( mlt_filter this, char *value, int count, int channel,
        // Tokenise the effect specification
        mlt_tokeniser_parse_new( tokeniser, value, " " );
        if ( tokeniser->count < 1 )
+       {
+               mlt_tokeniser_close( tokeniser );
                return error;
+       }
 
        // Locate the effect
        mlt_destructor effect_destructor = mlt_pool_release;
index 32d5d5d4b6fd84713c90632a77bc22dbf29786ad..ae18e44d4c15eed3c5537f4ae465c48b33d54e69 100644 (file)
@@ -10,7 +10,7 @@ TARGET = ../libmltswfdec$(LIBSUF)
 OBJS = producer_swfdec.o
 
 ifeq ($(targetos), MinGW)
-LDFLAGS += -enable-auto-import -lz
+LDFLAGS += -Wl,enable-auto-import -lz
 endif
 
 SRCS := $(OBJS:.o=.c)
@@ -30,9 +30,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/swfdec"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/swfdec"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/swfdec"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/swfdec"
 
 ifneq ($(wildcard .depend),)
 include .depend
index f1134afde957c7e04848a2e4dd724b9c74dca888..cffd6df9e65431e2f3057d24cb88714837ef7f68 100755 (executable)
@@ -4,6 +4,7 @@ if [ "$help" != "1" ]
 then
        pkg-config swfdec-0.9 2> /dev/null
        disable_swfdec=$?
+       echo > config.mak
        if [ "$disable_swfdec" = "0" ]
        then
                echo "CFLAGS += $(pkg-config --cflags swfdec-0.9)" >> config.mak
index 4d70e14114d49d397212867b2db3cd3df001a340..83640fbf4ff8b812a352b4b3ddb1fa8937aeff34 100644 (file)
@@ -113,7 +113,6 @@ static int get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *forma
        producer_swfdec swfdec = mlt_frame_pop_service( frame );
        mlt_service service = MLT_PRODUCER_SERVICE( &swfdec->parent );
        mlt_profile profile = mlt_service_profile( service );
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
        mlt_service_lock( service );
        
@@ -129,7 +128,7 @@ static int get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *forma
        mlt_frame_set_image( frame, *buffer, *width * ( *height + 1 ) * 4, mlt_pool_release );
 
        // Seek
-       mlt_position pos = mlt_properties_get_position( properties, "swfdec.position" );
+       mlt_position pos = mlt_frame_original_position( frame );
        if ( pos > swfdec->last_position )
        {
                gulong msec = 1000UL * ( pos - swfdec->last_position ) * profile->frame_rate_den / profile->frame_rate_num;
@@ -180,11 +179,8 @@ static int get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
        mlt_properties_set_int( properties, "test_image", 0 );
        mlt_properties_set_int( properties, "width", swfdec->width );
        mlt_properties_set_int( properties, "height", swfdec->height );
-       mlt_properties_set_int( properties, "real_width", swfdec->width );
-       mlt_properties_set_int( properties, "real_height", swfdec->height );
        mlt_properties_set_int( properties, "progressive", 1 );
        mlt_properties_set_double( properties, "aspect_ratio", 1.0 );
-       mlt_properties_set_position( properties, "swfdec.position", mlt_producer_frame( producer ) );
 
        // Push the get_image method on to the stack
        mlt_frame_push_service( *frame, swfdec );
index c6b45fd22555cca8d00bafd25e32bde2bece4e0a..c9d6eedfbecf18a04189387266a554b6260ce773 100644 (file)
@@ -34,9 +34,9 @@ clean:
                rm -f $(OBJS) $(TARGET)
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d $(DESTDIR)$(datadir)/mlt/videostab
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/videostab"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d $(DESTDIR)$(mltdatadir)/videostab
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/videostab"
 
 
 ifneq ($(wildcard .depend),)
index c569801fb34260fc839c860f5789e78babec4612..f6f860007060bdad51504835eb7c9aa5a20d278d 100644 (file)
@@ -72,8 +72,8 @@ static void serialize_vectors( videostab self, mlt_position length )
 
                // Put the analysis results in a property
                mlt_geometry_set_length( g, length );
-               mlt_properties_set( MLT_FILTER_PROPERTIES( self->parent ), "vectors", mlt_geometry_serialise( g ) );
-               mlt_geometry_close( g );
+               mlt_properties_set_data( MLT_FILTER_PROPERTIES( self->parent ), "vectors", g, 0,
+                       (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise );
        }
 }
 
@@ -82,7 +82,7 @@ static void deserialize_vectors( videostab self, char *vectors, mlt_position len
        mlt_geometry g = mlt_geometry_init();
 
        // Parse the property as a geometry
-       if ( !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
+       if ( g && !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
        {
                struct mlt_geometry_item_s item;
                int i;
@@ -199,6 +199,11 @@ mlt_filter filter_videostab_init( mlt_profile profile, mlt_service_type type, co
        if ( self )
        {
                mlt_filter parent = mlt_filter_new();
+               if ( !parent )
+               {
+                       free( self );
+                       return NULL;
+               }
                parent->child = self;
                parent->close = filter_close;
                parent->process = filter_process;
index b57d001d689717ff481ddfb43141b4c8a3451a74..474c7f7fa48990473e5c1fda464f3e55966c96a0 100644 (file)
@@ -48,8 +48,8 @@ static void serialize_vectors( videostab2_data* self, mlt_position length )
                mlt_position i;
 
                // Initialize geometry item
-               item.key = item.f[0] = item.f[1] = 1;
-               item.f[2] = item.f[3] = item.f[4] = 1;
+               item.key = item.f[0] = item.f[1] = item.f[2] = item.f[3] = 1;
+               item.f[4] = 0;
 
                tlist* transform_data =self->stab->transs;
                for ( i = 0; i < length; i++ )
@@ -72,17 +72,17 @@ static void serialize_vectors( videostab2_data* self, mlt_position length )
 
                // Put the analysis results in a property
                mlt_geometry_set_length( g, length );
-               mlt_properties_set( MLT_FILTER_PROPERTIES( (mlt_filter) self->parent ), "vectors", mlt_geometry_serialise( g ) );
-               mlt_geometry_close( g );
+               mlt_properties_set_data( MLT_FILTER_PROPERTIES( (mlt_filter) self->parent ), "vectors", g, 0,
+                       (mlt_destructor) mlt_geometry_close, (mlt_serialiser) mlt_geometry_serialise );
        }
 }
-
-Transform* deserialize_vectors( char *vectors, mlt_position length )
+// scale zoom implements the factor that the vetcors must be scaled since the vector is calulated for real with, now we need it for (scaled)width
+Transform* deserialize_vectors( char *vectors, mlt_position length ,float scale_zoom )
 {
        mlt_geometry g = mlt_geometry_init();
        Transform* tx=NULL;
        // Parse the property as a geometry
-       if ( !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
+       if ( g && !mlt_geometry_parse( g, vectors, length, -1, -1 ) )
        {
                struct mlt_geometry_item_s item;
                int i;
@@ -92,10 +92,10 @@ Transform* deserialize_vectors( char *vectors, mlt_position length )
                {
                        mlt_geometry_fetch( g, &item, i );
                        Transform t;
-                       t.x=item.x;
-                       t.y=item.y;
+                       t.x=scale_zoom*item.x;
+                       t.y=scale_zoom*item.y;
                        t.alpha=item.w;
-                       t.zoom=item.h;
+                       t.zoom=scale_zoom*item.h;
                        t.extra=0;
                        tx[i]=t;
                }
@@ -173,6 +173,9 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                                        data->initialized = 2;
 
                                        int interp = 2;
+                                       float scale_zoom=1.0;
+                                       if ( *width != mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "meta.media.width" ) )
+                                               scale_zoom = (float) *width / (float) mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "meta.media.width" );
                                        if ( strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 )
                                                interp = 0;
                                        else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 )
@@ -195,7 +198,7 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                                        data->trans->optzoom = mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "optzoom" );
                                        data->trans->sharpen = mlt_properties_get_double( MLT_FILTER_PROPERTIES(filter), "sharpen" );
 
-                                       transform_configure(data->trans,w,h,*format ,*image, deserialize_vectors(  vectors, length ),length);
+                                       transform_configure(data->trans,w,h,*format ,*image, deserialize_vectors(  vectors, length , scale_zoom ),length);
 
                                }
                                if ( data->initialized == 2 )
@@ -238,11 +241,31 @@ static void filter_close( mlt_filter parent )
 mlt_filter filter_videostab2_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
        videostab2_data* data= calloc( 1, sizeof(videostab2_data));
-       data->stab = calloc( 1, sizeof(StabData) );
-       data->trans = calloc( 1, sizeof (TransformData) ) ;
        if ( data )
        {
+               data->stab = calloc( 1, sizeof(StabData) );
+               if ( !data->stab )
+               {
+                       free( data );
+                       return NULL;
+               }
+
+               data->trans = calloc( 1, sizeof (TransformData) ) ;
+               if ( !data->trans )
+               {
+                       free( data->stab );
+                       free( data );
+                       return NULL;
+               }
+
                mlt_filter parent = mlt_filter_new();
+               if ( !parent )
+               {
+                       free( data->trans );
+                       free( data->stab );
+                       free( data );
+                       return NULL;
+               }
 
                parent->child = data;
                parent->close = filter_close;
index 5d2e3f401d43729b999e3dd19e0d2f0a511acf35..254c90334b9007941282a0918a3b7b6e4541502f 100644 (file)
@@ -117,11 +117,11 @@ parameters:
   - identifier: maxangle
     title: Maxangle
     type: float
-    description: max anglen to rotate (in rad)
+    description: max angle to rotate (in rad)
     readonly: no
     required: no
     minimum: -1
-    maximum: 1000
+    maximum: 3.142
     default: -1
     mutable: yes
     widget: spinner
index 8d39cec6ecd4ce11a80dad116fd4de3c7866970a..17057beddb08ae0d02494462b35ef660b9efd435 100644 (file)
@@ -18,7 +18,7 @@
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
-#if !defined(__DARWIN__) && !defined(__FreeBSD__)
+#if !defined(__DARWIN__) && !defined(__FreeBSD__) && !defined(WIN32) && !defined(__NetBSD__)
 #include <values.h>
 #endif
 
index 0731cf2cb6d3680109f457e8e1584366e4c3d7c2..5cb4ee4edb5492a6ec94b21d7254cc1e963c4434 100644 (file)
@@ -9,7 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
-
+#include <framework/mlt_log.h>
 
 /*********************************************************************
  * KLTError
@@ -25,11 +25,10 @@ void KLTError(char *fmt, ...)
   va_list args;
 
   va_start(args, fmt);
-  fprintf(stderr, "KLT Error: ");
-  vfprintf(stderr, fmt, args);
-  fprintf(stderr, "\n");
+  mlt_log_error(NULL, "KLT Error: ");
+  mlt_log_error(NULL, fmt, args);
+  mlt_log_error(NULL, "\n");
   va_end(args);
-  exit(1);
 }
 
 
index d922e497cb01c994cb343c50fc0de42136cc61d3..76ed461c6f36673d8c7500b7079b286d1bb32161 100644 (file)
 
 KLT_TrackingContext KLTCreateTrackingContext()
 {
-  KLT_TrackingContext tc;
+  KLT_TrackingContext tc = NULL;
 
   /* Allocate memory */
-  tc = (KLT_TrackingContext)  malloc(sizeof(KLT_TrackingContextRec));
+  tc = (KLT_TrackingContext) calloc(1, sizeof(KLT_TrackingContextRec));
 
   /* Set values to default values */
   tc->mindist = 10;
@@ -40,8 +40,8 @@ KLT_TrackingContext KLTCreateTrackingContext()
   tc->max_residue = 10.0;
   tc->grad_sigma = 1.0;
   tc->smooth_sigma_fact = 0.1;
-  tc->pyramid_sigma_fact = 0.9;\r
-  tc->step_factor = 1.0;\r
+  tc->pyramid_sigma_fact = 0.9;
+  tc->step_factor = 1.0;
   tc->nSkippedPixels = 0;
   tc->pyramid_last = NULL;
   tc->pyramid_last_gradx = NULL;
index 31a4204dfe03d8b2822e7b07fb5afb25e443c33b..790f1fffc28d581ba32deff33ea53aa1f41a5df5 100644 (file)
@@ -667,8 +667,11 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
     t = null_transform();
     num_trans = index; // amount of transforms we actually have
     if (num_trans < 1) {
-        printf( "too low contrast! No field remains.\n \
-                    (no translations are detected in frame %i)", sd->t);
+        printf( "too low contrast! No field remains.\n"
+                "(no translations are detected in frame %i)", sd->t);
+        free(ts);
+        free(fs);
+        free(angles);
         return t;
     }
 
@@ -728,13 +731,16 @@ Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc,
 #ifdef STABVERBOSE
     fclose(f);
 #endif
+    free(ts);
+    free(fs);
+    free(angles);
     return t;
 }
 
 /** draws the field scanning area */
 void drawFieldScanArea(StabData* sd, const Field* field, const Transform* t)
 {
-    if (!sd->pixelformat == mlt_image_yuv420p) {
+       if (sd->pixelformat != mlt_image_yuv420p) {
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
@@ -745,7 +751,7 @@ void drawFieldScanArea(StabData* sd, const Field* field, const Transform* t)
 /** draws the field */
 void drawField(StabData* sd, const Field* field, const Transform* t)
 {
-    if (!sd->pixelformat == mlt_image_yuv420p){
+       if (sd->pixelformat != mlt_image_yuv420p){
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
@@ -756,7 +762,7 @@ void drawField(StabData* sd, const Field* field, const Transform* t)
 /** draws the transform data of this field */
 void drawFieldTrans(StabData* sd, const Field* field, const Transform* t)
 {
-    if (!sd->pixelformat == mlt_image_yuv420p){
+       if (sd->pixelformat != mlt_image_yuv420p){
                mlt_log_warning (NULL, "format not usable\n");
         return;
        }
@@ -796,20 +802,6 @@ struct iterdata {
 
 /*************************************************************************/
 
-/**
- * stabilize_init:  Initialize this instance of the module.  See
- * tcmodule-data.h for function details.
- */
-int stabilize_init(StabData* instance)
-{
-
-    instance = calloc(1,sizeof(StabData)); // allocation with zero values
-    if (!instance) {
-        return -1;
-    }
-    return 0;
-}
-
 /*
  * stabilize_configure:  Configure this instance of the module.  See
  * tcmodule-data.h for function details.
index 520a1f75f58b0c16d2a27076d00598e99388e2c9..8e7ac96c78d2fb64285cc1f821b290fab27318bb 100644 (file)
@@ -178,7 +178,6 @@ void drawBox(unsigned char* I, int width, int height, int bytesPerPixel,
              int x, int y, int sizex, int sizey, unsigned char color);
 void addTrans(StabData* sd, Transform sl);
 
-int stabilize_init(StabData* instance);
 int stabilize_configure(StabData* instance);
 int stabilize_stop(StabData* instance);
 
index a2e6de561243464d1cbb16de1512bbdc788bcc8b..c0a8751af6d15c462313c64043e93b6ef06dae9b 100644 (file)
@@ -82,7 +82,7 @@ void interpolateBiCub(unsigned char *rv, float x, float y,
                       unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel)
 {
     // do a simple linear interpolation at the border
-    if (x < 1 || x > width-2 || y < 1 || y > height - 2) {
+    if (x < 1 || x >= width-2 || y < 1 || y >= height - 2) {
         interpolateBiLinBorder(rv, x,y,img,width,height,def,N,channel);
     } else {
         int x_f = myfloor(x);
@@ -116,7 +116,7 @@ void interpolateBiCub(unsigned char *rv, float x, float y,
 void interpolateSqr(unsigned char *rv, float x, float y,
                     unsigned char* img, int width, int height, unsigned char def,unsigned char N, unsigned char channel)
 {
-    if (x < 0 || x > width-1 || y < 0 || y > height - 1) {
+    if (x < 0 || x >= width-1 || y < 0 || y >= height-1) {
         interpolateBiLinBorder(rv, x, y, img, width, height, def,N,channel);
     } else {
         int x_f = myfloor(x);
@@ -141,7 +141,7 @@ void interpolateBiLin(unsigned char *rv, float x, float y,
                       unsigned char* img, int width, int height,
                       unsigned char def,unsigned char N, unsigned char channel)
 {
-    if (x < 0 || x > width-1 || y < 0 || y > height - 1) {
+    if (x < 0 || x >= width-1 || y < 0 || y >= height - 1) {
         interpolateBiLinBorder(rv, x, y, img, width, height, def,N,channel);
     } else {
         int x_f = myfloor(x);
index 27793e3dad6802f18f664e7af026f0c27d174ff6..2343ec94ae18816b1a0f102053990828f8ab4fd7 100644 (file)
@@ -30,9 +30,9 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/vmfx"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/vmfx"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/vmfx"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/vmfx"
 
 ifneq ($(wildcard .depend),)
 include .depend
index a3a0e9698eee84b63306494f7218210b165fa6de..cfe0ee6243b652f2d096d6cb8e232f3d4036e33e 100644 (file)
@@ -25,7 +25,7 @@
 #include <framework/mlt_producer.h>
 #include <framework/mlt_geometry.h>
 
-inline double smoothstep( const double e1, const double e2, const double a )
+static inline double smoothstep( const double e1, const double e2, const double a )
 {
     if ( a < e1 ) return 0.0;
     if ( a > e2 ) return 1.0;
index 3988da64c1cc102d190d4be28a4b1fc3092e24be..5a74fa036ec896d450b9ae0f97f41d652102dd5c 100644 (file)
@@ -45,8 +45,8 @@ mlt_producer producer_pgm_init( mlt_profile profile, mlt_service_type type, cons
                        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 );
+                       mlt_properties_set_int( properties, "meta.media.width", width );
+                       mlt_properties_set_int( properties, "meta.media.height", height );
                }
                else
                {
@@ -155,8 +155,8 @@ static int read_pgm( char *name, uint8_t **image, int *width, int *height, int *
 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 real_width = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.media.width" );
+       int real_height = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.media.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 );
@@ -183,7 +183,6 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        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 );
index 6c8cd6c6572f3a9c745f956630fb84764ff182c8..399c3ae3d4046d1294d5ed7fbcdb6ad6aee774fe 100644 (file)
@@ -32,9 +32,9 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/vorbis"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/vorbis"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/vorbis"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/vorbis"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 908aeec4d608944f95c1aaa20e5c9120bc61788c..920108627f500d495535dadf00d1080b17e61a0e 100644 (file)
@@ -152,8 +152,14 @@ static int producer_open( mlt_producer this, mlt_profile profile, char *file )
                        char **ptr = ov_comment(ov, -1)->user_comments;
                        while(*ptr) {
                                metadata = vorbis_metadata_from_str (*ptr);
-                               if (metadata != NULL)
+                               if (metadata != NULL) {
                                        mlt_properties_set(properties, metadata->name, metadata->content);
+                                       if (metadata->name)
+                                               free(metadata->name);
+                                       if (metadata->content)
+                                               free(metadata->content);
+                                       free(metadata);
+                               }
                                ++ptr;
                        }
 
@@ -208,11 +214,8 @@ static double producer_time_of_frame( mlt_producer this, mlt_position position )
 
 static int producer_get_audio( mlt_frame frame, void **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" );
+       mlt_position position = mlt_frame_original_position( frame );
 
        // Get the producer 
        mlt_producer this = mlt_frame_pop_audio( frame );
@@ -360,16 +363,12 @@ static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index
        // 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" );
+       mlt_properties_pass_list( MLT_FRAME_PROPERTIES(*frame), MLT_PRODUCER_PROPERTIES( this ), "frequency, channels" );
 
        // Calculate the next timecode
        mlt_producer_prepare_next( this );
index cebf39276b00ec1a34697db35b45e61cf909085a..ed29e30e1de745acb794cd3af77806655008f0e6 100644 (file)
@@ -33,7 +33,7 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
 
 ifneq ($(wildcard .depend),)
 include .depend
index c028da916b9870baf7599a81e33d03742a1895f9..1eec14b0b966e871da9749cfa63ede87c3b34020 100644 (file)
@@ -30,6 +30,9 @@
 #include <string.h>
 #include <stdlib.h>
 
+#define YADIF_MODE_TEMPORAL_SPATIAL (0)
+#define YADIF_MODE_TEMPORAL (2)
+
 static yadif_filter *init_yadif( int width, int height )
 {
        yadif_filter *yadif = mlt_pool_alloc( sizeof( *yadif ) );
@@ -109,21 +112,25 @@ static int deinterlace_yadif( mlt_frame frame, mlt_filter filter, uint8_t **imag
        int next_height = *height;
        
        mlt_log_debug( MLT_FILTER_SERVICE(filter), "previous %d current %d next %d\n",
-               previous_frame? mlt_frame_get_position(previous_frame) : -1,
-               mlt_frame_get_position(frame),
-               next_frame?  mlt_frame_get_position(next_frame) : -1);
+               previous_frame? mlt_frame_original_position(previous_frame) : -1,
+               mlt_frame_original_position(frame),
+               next_frame?  mlt_frame_original_position(next_frame) : -1);
 
        if ( !previous_frame || !next_frame )
                return 1;
 
        // Get the preceding frame's image
        int error = mlt_frame_get_image( previous_frame, &previous_image, format, &previous_width, &previous_height, 0 );
+       int progressive = mlt_properties_get_int( MLT_FRAME_PROPERTIES( previous_frame ), "progressive" );
 
        // Check that we aren't already progressive
-       if ( !error && previous_image  && *format == mlt_image_yuv422 &&
-                !mlt_properties_get_int( MLT_FRAME_PROPERTIES( previous_frame ), "progressive" ) )
+       if ( !error && previous_image && !progressive )
        {
+               // OK, now we know we have work to do and can request the image in our format
+               frame->convert_image( previous_frame, &previous_image, format, mlt_image_yuv422 );
+
                // Get the current frame's image
+               *format = mlt_image_yuv422;
                error = mlt_frame_get_image( frame, image, format, width, height, 0 );
 
                if ( !error && *image && *format == mlt_image_yuv422 )
@@ -176,18 +183,19 @@ static int deinterlace_yadif( mlt_frame frame, mlt_filter filter, uint8_t **imag
 /** Do it :-).
 */
 
-static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
        int error = 0;
-       mlt_properties properties = MLT_FRAME_PROPERTIES( this );
+       mlt_filter filter = mlt_frame_pop_service( frame );
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
        int deinterlace = mlt_properties_get_int( properties, "consumer_deinterlace" );
+       // The progressive var should only represent the frame's original state and not the state
+       // as modified by this filter!
        int progressive = mlt_properties_get_int( properties, "progressive" );
-       
-       // Pop the service off the stack
-       mlt_filter filter = mlt_frame_pop_service( this );
+       // At this point - before image was requested - (progressive == 0) cannot be trusted because
+       // some producers (avformat) do not yet know.
 
-       // Get the input image
-       if ( deinterlace && !progressive )
+       if ( deinterlace )
        {
                // Determine deinterlace method
                char *method_str = mlt_properties_get( MLT_FILTER_PROPERTIES( filter ), "method" );
@@ -212,53 +220,76 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
                else if ( strcmp( method_str, "greedy" ) == 0 )
                        method = DEINTERLACE_GREEDY;
 
-               *format = mlt_image_yuv422;
+               // Some producers like pixbuf want rescale_width & _height, but will not get them if you request
+               // the previous image first. So, on the first iteration, we use linearblend.
+               if ( ( method == DEINTERLACE_YADIF || method == DEINTERLACE_YADIF_NOSPATIAL ) &&
+                       !mlt_properties_get_int( MLT_FILTER_PROPERTIES(filter), "_notfirst" ) )
+               {
+                       mlt_properties_set_int( MLT_FILTER_PROPERTIES(filter), "_notfirst", 1 );
+                       method = DEINTERLACE_LINEARBLEND;
+                       error = 1;
+               }
 
                if ( method == DEINTERLACE_YADIF )
                {
-                       int mode = 0;
-                       error = deinterlace_yadif( this, filter, image, format, width, height, mode );
-                       progressive = mlt_properties_get_int( properties, "progressive" );
+                       error = deinterlace_yadif( frame, filter, image, format, width, height, YADIF_MODE_TEMPORAL_SPATIAL );
                }
                else if ( method == DEINTERLACE_YADIF_NOSPATIAL )
                {
-                       int mode = 2;
-                       error = deinterlace_yadif( this, filter, image, format, width, height, mode );
-                       progressive = mlt_properties_get_int( properties, "progressive" );
+                       error = deinterlace_yadif( frame, filter, image, format, width, height, YADIF_MODE_TEMPORAL );
                }
                if ( error || ( method > DEINTERLACE_NONE && method < DEINTERLACE_YADIF ) )
                {
-                       // Signal that we no longer need previous and next frames
                        mlt_service service = mlt_properties_get_data( MLT_FILTER_PROPERTIES(filter), "service", NULL );
-                       mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_need_previous_next", 0 );
-                       
-                       if ( error )
-                               method = DEINTERLACE_ONEFIELD;
-                       
+
                        // Get the current frame's image
-                       error = mlt_frame_get_image( this, image, format, width, height, writable );
+                       int error2 = mlt_frame_get_image( frame, image, format, width, height, writable );
                        progressive = mlt_properties_get_int( properties, "progressive" );
 
-                       // Check that we aren't already progressive
-                       if ( !progressive && !error && *image && *format == mlt_image_yuv422 )
+                       if ( error )
+                       {
+                               method = DEINTERLACE_LINEARBLEND;
+                               // If YADIF requested, prev/next cancelled because some previous frames were progressive,
+                               // but new frames are interlaced, then turn prev/next frames back on.
+                               if ( !progressive )
+                                       mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_need_previous_next", 1 );
+                       }
+                       else
                        {
-                               // Deinterlace the image using one of the Xine deinterlacers
-                               int image_size = *width * *height * 2;
-                               uint8_t *new_image = mlt_pool_alloc( image_size );
+                               // Signal that we no longer need previous and next frames
+                               mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_need_previous_next", 0 );
+                       }
+                       error = error2;
+                       
+                       if ( !error && !progressive )
+                       {
+                               // OK, now we know we have work to do and can request the image in our format
+                               error = frame->convert_image( frame, image, format, mlt_image_yuv422 );
 
-                               deinterlace_yuv( new_image, image, *width * 2, *height, method );
-                               mlt_frame_set_image( this, new_image, image_size, mlt_pool_release );
-                               *image = new_image;
+                               // Check that we aren't already progressive
+                               if ( !error && *image && *format == mlt_image_yuv422 )
+                               {
+                                       // Deinterlace the image using one of the Xine deinterlacers
+                                       int image_size = *width * *height * 2;
+                                       uint8_t *new_image = mlt_pool_alloc( image_size );
+
+                                       deinterlace_yuv( new_image, image, *width * 2, *height, method );
+                                       mlt_frame_set_image( frame, new_image, image_size, mlt_pool_release );
+                                       *image = new_image;
+                               }
                        }
                }
                else if ( method == DEINTERLACE_NONE )
                {
-                       error = mlt_frame_get_image( this, image, format, width, height, writable );
+                       error = mlt_frame_get_image( frame, image, format, width, height, writable );
                }
-               
+
+               // update progressive flag after having obtained image
+               progressive = mlt_properties_get_int( properties, "progressive" );
+
                mlt_log_debug( MLT_FILTER_SERVICE( filter ), "error %d deint %d prog %d fmt %s method %s\n",
                        error, deinterlace, progressive, mlt_image_format_name( *format ), method_str ? method_str : "yadif" );
-               
+
                if ( !error )
                {
                        // Make sure that others know the frame is deinterlaced
@@ -268,7 +299,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        else
        {
                // Pass through
-               error = mlt_frame_get_image( this, image, format, width, height, writable );
+               error = mlt_frame_get_image( frame, image, format, width, height, writable );
        }
 
        if ( !deinterlace || progressive )
@@ -285,10 +316,10 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
 /** Deinterlace filter processing - this should be lazy evaluation here...
 */
 
-static mlt_frame deinterlace_process( mlt_filter this, mlt_frame frame )
+static mlt_frame deinterlace_process( mlt_filter filter, mlt_frame frame )
 {
-       // Push this on to the service stack
-       mlt_frame_push_service( frame, this );
+       // Push filter on to the service stack
+       mlt_frame_push_service( frame, filter );
 
        // Push the get_image method on to the stack
        mlt_frame_push_get_image( frame, filter_get_image );
@@ -307,13 +338,13 @@ static void on_service_changed( mlt_service owner, mlt_service 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 )
+       mlt_filter filter = mlt_filter_new( );
+       if ( filter != NULL )
        {
-               this->process = deinterlace_process;
-               mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "method", arg );
-               mlt_events_listen( MLT_FILTER_PROPERTIES( this ), this, "service-changed", (mlt_listener) on_service_changed ); 
+               filter->process = deinterlace_process;
+               mlt_properties_set( MLT_FILTER_PROPERTIES( filter ), "method", arg );
+               mlt_events_listen( MLT_FILTER_PROPERTIES( filter ), filter, "service-changed", (mlt_listener) on_service_changed );
        }
-       return this;
+       return filter;
 }
 
index 2a57d418ee3fc8a2c5aa23e9af68bb6f9b1d304b..e224844427e6c9159d193ca968cef877724a90d6 100644 (file)
@@ -144,8 +144,8 @@ static attribute_align_arg void FILTER_LINE_FUNC_NAME(int mode, uint8_t *dst, co
             "pmaxub      %%xmm3, %%xmm2 \n\t"\\r
             /*"pshuflw      $9,%%xmm2, %%xmm3 \n\t"*/\\r
             /*"pshufhw      $9,%%xmm2, %%xmm3 \n\t"*/\\r
-            "movdqa %%xmm2, %%xmm3 \n\t" /* correct replacement (here)  */\
-            "psrldq $2, %%xmm3 \n\t"/* for "pshufw $9,%%mm2, %%mm3" - fix by Fizick */\
+            "movdqa %%xmm2, %%xmm3 \n\t" /* correct replacement (here)  */\\r
+            "psrldq $2, %%xmm3 \n\t"/* for "pshufw $9,%%mm2, %%mm3" - fix by Fizick */\\r
             "punpcklbw   %%xmm7, %%xmm2 \n\t" /* ABS(cur[x-refs-1] - cur[x+refs-1]) */\\r
             "punpcklbw   %%xmm7, %%xmm3 \n\t" /* ABS(cur[x-refs+1] - cur[x+refs+1]) */\\r
             "paddw       %%xmm2, %%xmm0 \n\t"\\r
@@ -163,7 +163,7 @@ static attribute_align_arg void FILTER_LINE_FUNC_NAME(int mode, uint8_t *dst, co
 \\r
             /* if(yadctx->mode<2) ... */\\r
             "movdqa      %[tmp3], %%xmm6 \n\t" /* diff */\\r
-            "cmp         $2, %[mode] \n\t"\\r
+            "cmpl        $2, %[mode] \n\t"\\r
             "jge         1f \n\t"\\r
             LOAD8("(%["prev2"],%[mrefs],2)", %%xmm2) /* prev2[x-2*refs] */\\r
             LOAD8("(%["next2"],%[mrefs],2)", %%xmm4) /* next2[x-2*refs] */\\r
index 3995a074e4ca75db8529d1b3dbad075e328c6a64..f072c4c9f6e7160173e75d4b532f931c2dddd8a6 100644 (file)
@@ -169,7 +169,7 @@ static void filter_line_mmx2(int mode, uint8_t *dst, const uint8_t *prev, const
 \
             /* if(p->mode<2) ... */\
             "movq    %[tmp3], %%mm6 \n\t" /* diff */\
-            "cmp       $2, %[mode] \n\t"\
+            "cmpl      $2, %[mode] \n\t"\
             "jge       1f \n\t"\
             LOAD4("(%["prev2"],%[mrefs],2)", %%mm2) /* prev2[x-2*refs] */\
             LOAD4("(%["next2"],%[mrefs],2)", %%mm4) /* next2[x-2*refs] */\
@@ -452,7 +452,7 @@ static attribute_align_arg void  YUY2ToPlanes_mmx(const unsigned char *srcYUY2,
         "packuswb %%mm4, %%mm4 \n\t" /* xxxxVVVV */\
         "movd %%mm2, (%%edx,%%eax) \n\t" /* store u */\
         "add $4, %%eax \n\t" \
-        "cmp %%ecx, %%eax \n\t" \
+        "cmpl %%ecx, %%eax \n\t" \
         "movd %%mm4, -4(%%esi,%%eax) \n\t" /* store v */\
         "jl xloop%= \n\t"\
         : : "D"(srcYUY2), "b"(py), "d"(pu), "S"(pv), "c"(widthdiv2) : "%eax");
@@ -486,7 +486,7 @@ static attribute_align_arg void YUY2FromPlanes_mmx(unsigned char *dstYUY2, int p
         "punpckhbw %%mm1, %%mm3 \n\t" /* VYUYVYUY */\
         "movntq %%mm0, -16(%%edi,%%eax,4) \n\t" /*store */\
         "movntq %%mm3, -8(%%edi,%%eax,4) \n\t" /*  store */\
-        "cmp %%ecx, %%eax \n\t"\
+        "cmpl %%ecx, %%eax \n\t"\
         "jl xloop%= \n\t"\
         : : "b"(py), "d"(pu), "S"(pv), "D"(dstYUY2), "c"(widthdiv2) : "%eax");
         py += pitch_y;
index caa092c99fef19b1bb15ec2c2d8718fcbd03982e..fafc540c187d565aa45acb19bd79cddcf30eb9d6 100644 (file)
@@ -31,10 +31,10 @@ clean:
                rm -f $(OBJS) $(TARGET) 
 
 install: all
-       install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
-       install -d "$(DESTDIR)$(datadir)/mlt/xml"
-       install -m 644 mlt-xml.dtd "$(DESTDIR)$(datadir)/mlt/xml"
-       install -m 644 *.yml "$(DESTDIR)$(datadir)/mlt/xml"
+       install -m 755 $(TARGET) "$(DESTDIR)$(moduledir)"
+       install -d "$(DESTDIR)$(mltdatadir)/xml"
+       install -m 644 mlt-xml.dtd "$(DESTDIR)$(mltdatadir)/xml"
+       install -m 644 *.yml "$(DESTDIR)$(mltdatadir)/xml"
 
 ifneq ($(wildcard .depend),)
 include .depend
index f744fcb91cf099530f6a3971679f66f213b97d70..58c22ed6cae27346a0ee197f5e1e6b06a51aed8c 100644 (file)
 #include <locale.h>
 #include <libxml/tree.h>
 #include <pthread.h>
+#include <wchar.h>
 
 #define ID_SIZE 128
+#define TIME_PROPERTY "_consumer_xml"
 
 #define _x (const xmlChar*)
 #define _s (const char*)
@@ -47,6 +49,8 @@ struct serialise_context_s
        char *root;
        char *store;
        int no_meta;
+       mlt_profile profile;
+       mlt_time_format time_format;
 };
 typedef struct serialise_context_s* serialise_context;
 
@@ -59,7 +63,37 @@ static int consumer_is_stopped( mlt_consumer this );
 static void *consumer_thread( void *arg );
 static void serialise_service( serialise_context context, mlt_service service, xmlNode *node );
 
-typedef enum 
+static char* filter_restricted( const char *in )
+{
+       if ( !in ) return NULL;
+       size_t n = strlen( in );
+       char *out = calloc( 1, n + 1 );
+       char *p = out;
+       mbstate_t mbs;
+       memset( &mbs, 0, sizeof(mbs) );
+       while ( *in )
+       {
+               wchar_t w;
+               size_t c = mbrtowc( &w, in, n, &mbs );
+               if ( c <= 0 || c > n ) break;
+               n -= c;
+               in += c;
+               if ( w == 0x9 || w == 0xA || w == 0xD ||
+                               ( w >= 0x20 && w <= 0xD7FF ) ||
+                               ( w >= 0xE000 && w <= 0xFFFD ) ||
+                               ( w >= 0x10000 && w <= 0x10FFFF ) )
+               {
+                       mbstate_t ps;
+                       memset( &ps, 0, sizeof(ps) );
+                       c = wcrtomb( p, w, &ps );
+                       if ( c > 0 )
+                               p += c;
+               }
+       }
+       return out;
+}
+
+typedef enum
 {
        xml_existing,
        xml_producer,
@@ -91,7 +125,7 @@ static char *xml_get_id( serialise_context context, mlt_service service, xml_typ
                // 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 
+               // 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 )
                {
@@ -152,7 +186,7 @@ static char *xml_get_id( serialise_context context, mlt_service service, xml_typ
 mlt_consumer consumer_xml_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 );
+       mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) );
 
        // If no malloc'd and consumer init ok
        if ( this != NULL && mlt_consumer_init( this, NULL, profile ) == 0 )
@@ -182,7 +216,7 @@ static void serialise_properties( serialise_context context, mlt_properties prop
 {
        int i;
        xmlNode *p;
-       
+
        // Enumerate the properties
        for ( i = 0; i < mlt_properties_count( properties ); i++ )
        {
@@ -200,12 +234,26 @@ static void serialise_properties( serialise_context context, mlt_properties prop
                         strcmp( name, "width" ) &&
                         strcmp( name, "height" ) )
                {
-                       char *value = mlt_properties_get_value( properties, i );
-                       int rootlen = strlen( context->root );
-                       if ( rootlen && !strncmp( value, context->root, rootlen ) && value[ rootlen ] == '/' )
-                               value += rootlen + 1;
-                       p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
-                       xmlNewProp( p, _x("name"), _x(name) );
+                       char *value = NULL;
+                       if ( !strcmp( name, "length" ) )
+                       {
+                               char *time = mlt_properties_get_time( properties, name, context->time_format );
+                               if ( time )
+                                       value = strdup( time );
+                       }
+                       else
+                               value = filter_restricted( mlt_properties_get_value( properties, i ) );
+                       if ( value )
+                       {
+                               int rootlen = strlen( context->root );
+                               // convert absolute path to relative
+                               if ( rootlen && !strncmp( value, context->root, rootlen ) && value[ rootlen ] == '/' )
+                                       p = xmlNewTextChild( node, NULL, _x("property"), _x(value + rootlen + 1 ) );
+                               else
+                                       p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
+                               xmlNewProp( p, _x("name"), _x(name) );
+                               free( value );
+                       }
                }
        }
 }
@@ -214,21 +262,24 @@ static void serialise_store_properties( serialise_context context, mlt_propertie
 {
        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 )
+                       char *value = filter_restricted( mlt_properties_get_value( properties, i ) );
+                       if ( value )
                        {
                                int rootlen = strlen( context->root );
+                               // convert absolute path to relative
                                if ( rootlen && !strncmp( value, context->root, rootlen ) && value[ rootlen ] == '/' )
-                                       value += rootlen + 1;
-                               p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
+                                       p = xmlNewTextChild( node, NULL, _x("property"), _x(value + rootlen + 1) );
+                               else
+                                       p = xmlNewTextChild( node, NULL, _x("property"), _x(value) );
                                xmlNewProp( p, _x("name"), _x(name) );
+                               free( value );
                        }
                }
        }
@@ -239,7 +290,7 @@ static inline void serialise_service_filters( serialise_context context, mlt_ser
        int i;
        xmlNode *p;
        mlt_filter filter = NULL;
-       
+
        // Enumerate the filters
        for ( i = 0; ( filter = mlt_producer_filter( MLT_PRODUCER( service ), i ) ) != NULL; i ++ )
        {
@@ -250,20 +301,14 @@ static inline void serialise_service_filters( serialise_context context, mlt_ser
                        char *id = xml_get_id( context, MLT_FILTER_SERVICE( filter ), xml_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) );
-                               }
+                               if ( mlt_properties_get_position( properties, "in" ) )
+                                       xmlNewProp( p, _x("in"), _x( mlt_properties_get_time( properties, "in", context->time_format ) ) );
+                               if ( mlt_properties_get_position( properties, "out" ) )
+                                       xmlNewProp( p, _x("out"), _x( mlt_properties_get_time( properties, "out", context->time_format ) ) );
                                serialise_properties( context, properties, p );
                                serialise_service_filters( context, MLT_FILTER_SERVICE( filter ), p );
                        }
@@ -275,7 +320,7 @@ static void serialise_producer( serialise_context context, mlt_service service,
 {
        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 );
@@ -290,8 +335,8 @@ static void serialise_producer( serialise_context context, mlt_service service,
                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" )) );
+               xmlNewProp( child, _x("in"), _x(mlt_properties_get_time( properties, "in", context->time_format )) );
+               xmlNewProp( child, _x("out"), _x(mlt_properties_get_time( properties, "out", context->time_format )) );
                serialise_properties( context, properties, child );
                serialise_service_filters( context, service, child );
 
@@ -303,8 +348,8 @@ static void serialise_producer( serialise_context context, mlt_service service,
                char *id = xml_get_id( context, parent, xml_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" )) );
+               xmlNewProp( node, _x("in"), _x(mlt_properties_get_time( properties, "in", context->time_format )) );
+               xmlNewProp( node, _x("out"), _x(mlt_properties_get_time( properties, "out", context->time_format )) );
        }
 }
 
@@ -313,7 +358,7 @@ static void serialise_tractor( serialise_context context, mlt_service service, x
 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
@@ -344,14 +389,14 @@ static void serialise_multitrack( serialise_context context, mlt_service service
                        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" )) );
+                               xmlNewProp( track, _x("in"), _x( mlt_properties_get_time( properties, "in", context->time_format ) ) );
+                               xmlNewProp( track, _x("out"), _x( mlt_properties_get_time( properties, "out", context->time_format ) ) );
                                serialise_store_properties( context, MLT_PRODUCER_PROPERTIES( producer ), track, context->store );
                                if ( !context->no_meta )
                                        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" ) ) );
@@ -366,7 +411,7 @@ static void serialise_playlist( serialise_context context, mlt_service service,
        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
@@ -391,7 +436,7 @@ static void serialise_playlist( serialise_context context, mlt_service service,
                                }
                        }
                }
-               
+
                child = xmlNewChild( node, NULL, _x("playlist"), NULL );
 
                // Set the id
@@ -406,21 +451,21 @@ static void serialise_playlist( serialise_context context, mlt_service service,
 
                // 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" );
+                               mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer );
+                               char *service_s = mlt_properties_get( producer_props, "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) );
+                                       mlt_properties_set_data( producer_props, "_profile", context->profile, 0, NULL, NULL );
+                                       mlt_properties_set_position( producer_props, TIME_PROPERTY, info.frame_count );
+                                       xmlNewProp( entry, _x("length"), _x( mlt_properties_get_time( producer_props, TIME_PROPERTY, context->time_format ) ) );
                                }
                                else
                                {
@@ -428,10 +473,10 @@ static void serialise_playlist( serialise_context context, mlt_service service,
                                        xmlNode *entry = xmlNewChild( child, NULL, _x("entry"), NULL );
                                        id = xml_get_id( context, MLT_SERVICE( producer ), xml_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) );
+                                       mlt_properties_set_position( producer_props, TIME_PROPERTY, info.frame_in );
+                                       xmlNewProp( entry, _x("in"), _x( mlt_properties_get_time( producer_props, TIME_PROPERTY, context->time_format ) ) );
+                                       mlt_properties_set_position( producer_props, TIME_PROPERTY, info.frame_out );
+                                       xmlNewProp( entry, _x("out"), _x( mlt_properties_get_time( producer_props, TIME_PROPERTY, context->time_format ) ) );
                                        if ( info.repeat > 1 )
                                        {
                                                sprintf( temp, "%d", info.repeat );
@@ -461,7 +506,7 @@ static void serialise_tractor( serialise_context context, mlt_service service, x
 {
        xmlNode *child = node;
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-       
+
        if ( context->pass == 0 )
        {
                // Recurse on connected producer
@@ -482,8 +527,8 @@ static void serialise_tractor( serialise_context context, mlt_service service, x
                        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" )) );
+               xmlNewProp( child, _x("in"), _x(mlt_properties_get_time( properties, "in", context->time_format )) );
+               xmlNewProp( child, _x("out"), _x(mlt_properties_get_time( properties, "out", context->time_format )) );
 
                // Store application specific properties
                serialise_store_properties( context, MLT_SERVICE_PROPERTIES( service ), child, context->store );
@@ -500,7 +545,7 @@ static void serialise_filter( serialise_context context, mlt_service service, xm
 {
        xmlNode *child = node;
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-       
+
        // Recurse on connected producer
        serialise_service( context, mlt_service_producer( service ), node );
 
@@ -517,8 +562,10 @@ static void serialise_filter( serialise_context context, mlt_service service, xm
                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" )) );
+               if ( mlt_properties_get_position( properties, "in" ) )
+                       xmlNewProp( child, _x("in"), _x( mlt_properties_get_time( properties, "in", context->time_format ) ) );
+               if ( mlt_properties_get_position( properties, "out" ) )
+                       xmlNewProp( child, _x("out"), _x( mlt_properties_get_time( properties, "out", context->time_format ) ) );
 
                serialise_properties( context, properties, child );
                serialise_service_filters( context, service, child );
@@ -529,7 +576,7 @@ static void serialise_transition( serialise_context context, mlt_service service
 {
        xmlNode *child = node;
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
-       
+
        // Recurse on connected producer
        serialise_service( context, MLT_SERVICE( MLT_TRANSITION( service )->producer ), node );
 
@@ -541,13 +588,15 @@ static void serialise_transition( serialise_context context, mlt_service service
                        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" )) );
+               if ( mlt_properties_get_position( properties, "in" ) )
+                       xmlNewProp( child, _x("in"), _x( mlt_properties_get_time( properties, "in", context->time_format ) ) );
+               if ( mlt_properties_get_position( properties, "out" ) )
+                       xmlNewProp( child, _x("out"), _x( mlt_properties_get_time( properties, "out", context->time_format ) ) );
 
                serialise_properties( context, properties, child );
                serialise_service_filters( context, service, child );
@@ -561,7 +610,7 @@ static void serialise_service( serialise_context context, mlt_service service, x
        {
                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 )
                {
@@ -587,20 +636,20 @@ static void serialise_service( serialise_context context, mlt_service service, x
                else if ( strcmp( mlt_type, "mlt_producer" ) == 0 )
                {
                        char *resource = mlt_properties_get( properties, "resource" );
-                       
+
                        // Recurse on multitrack's tracks
                        if ( resource && strcmp( resource, "<multitrack>" ) == 0 )
                        {
                                serialise_multitrack( context, service, node );
                                break;
                        }
-                       
+
                        // Recurse on playlist's clips
                        else if ( resource && strcmp( resource, "<playlist>" ) == 0 )
                        {
                                serialise_playlist( context, service, node );
                        }
-                       
+
                        // Recurse on tractor's producer
                        else if ( resource && strcmp( resource, "<tractor>" ) == 0 )
                        {
@@ -618,21 +667,21 @@ static void serialise_service( serialise_context context, mlt_service service, x
                                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 );
        }
@@ -669,6 +718,12 @@ xmlDocPtr xml_make_doc( mlt_consumer consumer, mlt_service service )
        // Assign the additional 'storage' pattern for properties
        context->store = mlt_properties_get( MLT_CONSUMER_PROPERTIES( consumer ), "store" );
        context->no_meta = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "no_meta" );
+       const char *time_format = mlt_properties_get( MLT_CONSUMER_PROPERTIES( consumer ), "time_format" );
+       if ( time_format && ( !strcmp( time_format, "smpte" ) || !strcmp( time_format, "SMPTE" )
+                       || !strcmp( time_format, "timecode" ) ) )
+               context->time_format = mlt_time_smpte;
+       else if ( time_format && ( !strcmp( time_format, "clock" ) || !strcmp( time_format, "CLOCK" ) ) )
+               context->time_format = mlt_time_clock;
 
        // Assign a title property
        if ( mlt_properties_get( properties, "title" ) != NULL )
@@ -701,12 +756,13 @@ xmlDocPtr xml_make_doc( mlt_consumer consumer, mlt_service service )
                xmlNewProp( profile_node, _x("frame_rate_den"), _x(tmpstr) );
                sprintf( tmpstr, "%d", profile->colorspace );
                xmlNewProp( profile_node, _x("colorspace"), _x(tmpstr) );
+               context->profile = profile;
        }
 
        // 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" );
 
@@ -724,7 +780,7 @@ xmlDocPtr xml_make_doc( mlt_consumer consumer, mlt_service service )
        mlt_properties_close( context->hide_map );
        free( context->root );
        free( context );
-       
+
        return doc;
 }
 
index de09c11af1a00bb1c374164bddac30c471ed0d53..a310b953fff50cf84fc484a4e2b4dd316eec7e50 100644 (file)
@@ -71,3 +71,15 @@ parameters:
     maximum: 1
     default: 0
     widget: checkbox
+
+  - identifier: time_format
+    title: Time format
+    type: string
+    description: Output time-based values as timecode or clock formats.
+    values:
+      - frames
+      - smpte # or SMPTE
+      - timecode # same as smpte
+      - clock # or CLOCK
+    default: frames
+    widget: dropdown
index d863f70bb1ea02d81c6fa903dadf64dff6431a36..29caa136f6df6c8b1d276997bec892b3e452fed2 100644 (file)
@@ -22,9 +22,9 @@
 //       when the returned producer is closed).
 
 #include <framework/mlt.h>
+#include <framework/mlt_log.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <ctype.h>
 #include <unistd.h>
 
@@ -88,6 +88,8 @@ struct deserialise_context_s
        mlt_consumer consumer;
        int multi_consumer;
        int consumer_count;
+       int seekable;
+       mlt_consumer qglsl;
 };
 typedef struct deserialise_context_s *deserialise_context;
 
@@ -152,12 +154,18 @@ static mlt_service context_pop_service( deserialise_context context, enum servic
 {
        mlt_service result = NULL;
        
-       *type = invalid_type;
+       if ( type ) *type = invalid_type;
        if ( context->stack_service_size > 0 )
        {
                result = context->stack_service[ -- context->stack_service_size ];
                if ( type != NULL )
                        *type = context->stack_types[ context->stack_service_size ];
+               // Set the service's profile and locale so mlt_property time-to-position conversions can get fps
+               if ( result )
+               {
+                       mlt_properties_set_data( MLT_SERVICE_PROPERTIES( result ), "_profile", context->profile, 0, NULL, NULL );
+                       mlt_properties_set_lcnumeric( MLT_SERVICE_PROPERTIES( result ), context->lc_numeric );
+               }
        }
        return result;
 }
@@ -274,7 +282,7 @@ static int add_producer( deserialise_context context, mlt_service service, mlt_p
                                break;
                        default:
                                result = 0;
-                               fprintf( stderr, "Producer defined inside something that isn't a container\n" );
+                               mlt_log_warning( NULL, "[producer_xml] Producer defined inside something that isn't a container\n" );
                                break;
                };
 
@@ -403,7 +411,7 @@ static void on_end_tractor( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               fprintf( stderr, "Invalid state for tractor\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state for tractor\n" );
        }
 }
 
@@ -446,7 +454,7 @@ static void on_start_multitrack( deserialise_context context, const xmlChar *nam
        }
        else
        {
-               fprintf( stderr, "Invalid multitrack position\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid multitrack position\n" );
        }
 }
 
@@ -457,12 +465,12 @@ static void on_end_multitrack( deserialise_context context, const xmlChar *name
        mlt_service service = context_pop_service( context, &type );
 
        if ( service == NULL || type != mlt_multitrack_type )
-               fprintf( stderr, "End multitrack in the wrong state...\n" );
+               mlt_log_error( NULL, "[producer_xml] 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_playlist playlist = mlt_playlist_new( context->profile );
        mlt_service service = MLT_PLAYLIST_SERVICE( playlist );
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
 
@@ -506,7 +514,7 @@ static void on_end_playlist( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               fprintf( stderr, "Invalid state of playlist end %d\n", type );
+               mlt_log_error( NULL, "[producer_xml] Invalid state of playlist end %d\n", type );
        }
 }
 
@@ -524,44 +532,6 @@ static void on_start_producer( deserialise_context context, const xmlChar *name,
                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;
@@ -605,7 +575,7 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                if ( !producer && resource )
                        producer = MLT_SERVICE( mlt_factory_producer( context->profile, NULL, resource ) );
                if ( !producer )
-                       fprintf( stderr, "failed to load producer \"%s\"\n", resource );
+                       mlt_log_error( NULL, "[producer_xml] failed to load producer \"%s\"\n", resource );
                if ( !producer )
                        producer = MLT_SERVICE( mlt_factory_producer( context->profile, NULL, "+INVALID.txt" ) );
                if ( !producer )
@@ -613,14 +583,16 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                if ( !producer )
                {
                        mlt_service_close( service );
+                       free( service );
                        return;
                }
 
                // Track this producer
                track_service( context->destructors, producer, (mlt_destructor) mlt_producer_close );
                mlt_properties_set_lcnumeric( MLT_SERVICE_PROPERTIES( producer ), context->lc_numeric );
+               context->seekable &= mlt_properties_get_int( MLT_SERVICE_PROPERTIES( producer ), "seekable" );
 
-               // Propogate the properties
+               // Propagate the properties
                qualify_property( context, properties, "resource" );
                qualify_property( context, properties, "luma" );
                qualify_property( context, properties, "luma.resource" );
@@ -632,33 +604,17 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                mlt_position out = -1;
        
                // Get in
-               if ( mlt_properties_get( properties, "in" ) != NULL )
+               if ( mlt_properties_get( properties, "in" ) )
                        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" );
-               }
+               else if ( mlt_properties_get( properties, "clipBegin" ) )
+                       in = mlt_properties_get_position( properties, "clipBegin" );
                // Get out
-               if ( mlt_properties_get( properties, "out" ) != NULL )
+               if ( mlt_properties_get( properties, "out" ) )
                        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" );
-               }
+               else if ( mlt_properties_get( properties, "clipEnd" ) )
+                       out = mlt_properties_get_position( properties, "clipEnd" );
                // Remove in and out
                mlt_properties_set( properties, "in", NULL );
                mlt_properties_set( properties, "out", NULL );
@@ -714,8 +670,12 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                        // Push the producer onto the stack
                        context_push_service( context, producer, mlt_producer_type );
                }
+       }
 
+       if ( service )
+       {
                mlt_service_close( service );
+               free( service );
        }
 }
 
@@ -724,7 +684,6 @@ static void on_start_blank( deserialise_context context, const xmlChar *name, co
        // 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 )
        {
@@ -733,20 +692,18 @@ static void on_start_blank( deserialise_context context, const xmlChar *name, co
                {
                        if ( xmlStrcmp( atts[0], _x("length") ) == 0 )
                        {
-                               length = atoll( _s(atts[1]) );
+                               // Append a blank to the playlist
+                               mlt_playlist_blank_time( MLT_PLAYLIST( service ), _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" );
+               mlt_log_error( NULL, "[producer_xml] blank without a playlist - a definite no no\n" );
        }
 }
 
@@ -754,6 +711,8 @@ static void on_start_entry( deserialise_context context, const xmlChar *name, co
 {
        mlt_producer entry = NULL;
        mlt_properties temp = mlt_properties_new( );
+       mlt_properties_set_data( temp, "_profile", context->profile, 0, NULL, NULL );
+       mlt_properties_set_lcnumeric( temp, context->lc_numeric );
 
        for ( ; atts != NULL && *atts != NULL; atts += 2 )
        {
@@ -800,7 +759,7 @@ static void on_start_entry( deserialise_context context, const xmlChar *name, co
                }
                else
                {
-                       fprintf( stderr, "Entry not part of a playlist...\n" );
+                       mlt_log_error( NULL, "[producer_xml] Entry not part of a playlist...\n" );
                }
 
                context_push_service( context, parent, parent_type );
@@ -820,7 +779,7 @@ static void on_end_entry( deserialise_context context, const xmlChar *name )
 
        if ( entry == NULL && entry_type != mlt_entry_type )
        {
-               fprintf( stderr, "Invalid state at end of entry\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state at end of entry\n" );
        }
 }
 
@@ -870,7 +829,7 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
                else if ( parent_type == mlt_multitrack_type )
                        multitrack = MLT_MULTITRACK( parent );
                else
-                       fprintf( stderr, "track contained in an invalid container\n" );
+                       mlt_log_error( NULL, "[producer_xml] track contained in an invalid container\n" );
 
                if ( multitrack != NULL )
                {
@@ -910,12 +869,16 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
 
                if ( parent != NULL )
                        context_push_service( context, parent, parent_type );
-
-               mlt_service_close( track );
        }
        else
        {
-               fprintf( stderr, "Invalid state at end of track\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state at end of track\n" );
+       }
+
+       if ( track )
+       {
+               mlt_service_close( track );
+               free( track );
        }
 }
 
@@ -951,10 +914,11 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
 
                if ( !filter )
                {
-                       fprintf( stderr, "failed to load filter \"%s\"\n", id );
+                       mlt_log_error( NULL, "[producer_xml] failed to load filter \"%s\"\n", id );
                        if ( parent )
                                context_push_service( context, parent, parent_type );
                        mlt_service_close( service );
+                       free( service );
                        return;
                }
 
@@ -993,15 +957,18 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
                }
                else
                {
-                       fprintf( stderr, "filter closed with invalid parent...\n" );
+                       mlt_log_error( NULL, "[producer_xml] 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" );
+               mlt_log_error( NULL, "[producer_xml] Invalid top of stack on filter close\n" );
+       }
+
+       if ( service )
+       {
+               mlt_service_close( service );
+               free(service);
        }
 }
 
@@ -1037,10 +1004,11 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
 
                if ( !effect )
                {
-                       fprintf( stderr, "failed to load transition \"%s\"\n", id );
+                       mlt_log_error( NULL, "[producer_xml] failed to load transition \"%s\"\n", id );
                        if ( parent )
                                context_push_service( context, parent, parent_type );
                        mlt_service_close( service );
+                       free( service );
                        return;
                }
                track_service( context->destructors, effect, (mlt_destructor) mlt_transition_close );
@@ -1074,7 +1042,7 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
                        }
                        else
                        {
-                               fprintf( stderr, "Misplaced transition - ignoring\n" );
+                               mlt_log_warning( NULL, "[producer_xml] Misplaced transition - ignoring\n" );
                        }
 
                        // Put the parent back on the stack
@@ -1082,15 +1050,19 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
                }
                else
                {
-                       fprintf( stderr, "transition closed with invalid parent...\n" );
+                       mlt_log_error( NULL, "[producer_xml] 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" );
+               mlt_log_error( NULL, "[producer_xml] Invalid top of stack on transition close\n" );
+       }
+
+       if ( service )
+       {
+               mlt_service_close( service );
+               free( service );
        }
 }
 
@@ -1098,11 +1070,10 @@ static void on_start_consumer( deserialise_context context, const xmlChar *name,
 {
        if ( context->pass == 1 )
        {
-               mlt_consumer consumer = mlt_consumer_new( context->profile );
-               mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+               mlt_properties properties = mlt_properties_new();
 
                mlt_properties_set_lcnumeric( properties, context->lc_numeric );
-               context_push_service( context, MLT_CONSUMER_SERVICE(consumer), mlt_dummy_consumer_type );
+               context_push_service( context, (mlt_service) properties, mlt_dummy_consumer_type );
 
                // Set the properties from attributes
                for ( ; atts != NULL && *atts != NULL; atts += 2 )
@@ -1116,21 +1087,23 @@ static void on_end_consumer( deserialise_context context, const xmlChar *name )
        {
                // Get the consumer from the stack
                enum service_type type;
-               mlt_service service = context_pop_service( context, &type );
+               mlt_properties properties = (mlt_properties) context_pop_service( context, &type );
 
-               if ( service && type == mlt_dummy_consumer_type )
+               if ( properties && type == mlt_dummy_consumer_type )
                {
-                       mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
                        qualify_property( context, properties, "resource" );
                        qualify_property( context, properties, "target" );
                        char *resource = trim( mlt_properties_get( properties, "resource" ) );
 
-                       if ( context->multi_consumer > 1 )
+                       if ( context->multi_consumer > 1 || context->qglsl )
                        {
                                // Instantiate the multi consumer
                                if ( !context->consumer )
                                {
-                                       context->consumer = mlt_factory_consumer( context->profile, "multi", NULL );
+                                       if ( context->qglsl )
+                                               context->consumer = context->qglsl;
+                                       else
+                                               context->consumer = mlt_factory_consumer( context->profile, "multi", NULL );
                                        if ( context->consumer )
                                        {
                                                // Track this consumer
@@ -1140,11 +1113,12 @@ static void on_end_consumer( deserialise_context context, const xmlChar *name )
                                }
                                if ( context->consumer )
                                {
-                                       // Set this service instance on multi consumer
+                                       // Set this properties object on multi consumer
                                        char key[20];
                                        snprintf( key, sizeof(key), "%d", context->consumer_count++ );
-                                       mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(context->consumer), key, service, 0,
-                                               (mlt_destructor) mlt_service_close, NULL );
+                                       mlt_properties_inc_ref( properties );
+                                       mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(context->consumer), key, properties, 0,
+                                               (mlt_destructor) mlt_properties_close, NULL );
                                }
                        }
                        else
@@ -1161,10 +1135,11 @@ static void on_end_consumer( deserialise_context context, const xmlChar *name )
                                        // Inherit the properties
                                        mlt_properties_inherit( MLT_CONSUMER_PROPERTIES(context->consumer), properties );
                                }
-                               // Close the dummy
-                               mlt_service_close( service );
                        }
                }
+               // Close the dummy
+               if ( properties )
+                       mlt_properties_close( properties );
        }
 }
 
@@ -1196,7 +1171,7 @@ static void on_start_property( deserialise_context context, const xmlChar *name,
        }
        else
        {
-               fprintf( stderr, "Property without a service '%s'?\n", ( const char * )name );
+               mlt_log_error( NULL, "[producer_xml] Property without a service '%s'?\n", ( const char * )name );
        }
 }
 
@@ -1237,7 +1212,7 @@ static void on_end_property( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               fprintf( stderr, "Property without a service '%s'??\n", (const char *)name );
+               mlt_log_error( NULL, "[producer_xml] Property without a service '%s'??\n", (const char *)name );
        }
 }
 
@@ -1246,7 +1221,6 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at
        struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
        deserialise_context context = ( deserialise_context )( xmlcontext->_private );
        
-//printf("on_start_element: %s\n", name );
        if ( context->pass == 0 )
        {
                if ( xmlStrcmp( name, _x("mlt") ) == 0 ||
@@ -1255,6 +1229,14 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at
                        on_start_profile( context, name, atts );
                if ( xmlStrcmp( name, _x("consumer") ) == 0 )
                        context->multi_consumer++;
+
+               // Check for a service beginning with glsl. or movit.
+               for ( ; atts != NULL && *atts != NULL; atts += 2 ) {
+                       if ( !xmlStrncmp( atts[1], _x("glsl."), 5 ) || !xmlStrncmp( atts[1], _x("movit."), 6 ) ) {
+                               mlt_properties_set_int( context->params, "qglsl", 1 );
+                               break;
+                       }
+               }
                return;
        }
        context->branch[ context->depth ] ++;
@@ -1321,7 +1303,6 @@ 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 && context->pass == 1 && xmlStrcmp( name, _x("property") ) != 0 )
                context_pop_node( context );
        else if ( xmlStrcmp( name, _x("multitrack") ) == 0 )
@@ -1353,7 +1334,7 @@ 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 );
+       char *value = calloc( 1, len + 1 );
        enum service_type type;
        mlt_service service = context_pop_service( context, &type );
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
@@ -1376,7 +1357,7 @@ static void on_characters( void *ctx, const xmlChar *ch, int len )
                if ( s != NULL )
                {
                        // Append new text to existing content
-                       char *new = calloc( strlen( s ) + len + 1, 1 );
+                       char *new = calloc( 1, strlen( s ) + len + 1 );
                        strcat( new, s );
                        strcat( new, value );
                        mlt_properties_set( properties, context->property, new );
@@ -1386,7 +1367,11 @@ static void on_characters( void *ctx, const xmlChar *ch, int len )
                        mlt_properties_set( properties, context->property, value );
        }
        context->entity_is_replace = 0;
-       
+
+       // Check for a service beginning with glsl. or movit.
+       if ( !strncmp( value, "glsl.", 5 ) || !strncmp( value, "movit.", 6 ) )
+               mlt_properties_set_int( context->params, "qglsl", 1 );
+
        free( value);
 }
 
@@ -1469,6 +1454,28 @@ static xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
        return e;
 }
 
+static void    on_error( void * ctx, const char * msg, ... )
+{
+       struct _xmlError* err_ptr = xmlCtxtGetLastError( ctx );
+
+       switch( err_ptr->level )
+       {
+       case XML_ERR_WARNING:
+               mlt_log_warning( NULL, "[producer_xml] parse warning: %s\trow: %d\tcol: %d\n",
+                                        err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       case XML_ERR_ERROR:
+               mlt_log_error( NULL, "[producer_xml] parse error: %s\trow: %d\tcol: %d\n",
+                                      err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       default:
+       case XML_ERR_FATAL:
+               mlt_log_fatal( NULL, "[producer_xml] parse fatal: %s\trow: %d\tcol: %d\n",
+                                      err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       }
+}
+
 /** Convert a hexadecimal character to its value.
 */
 static int tohex( char p )
@@ -1519,8 +1526,15 @@ static void parse_url( mlt_properties properties, char *url )
                        
                        case ':':
                        case '=':
-                               url[ i++ ] = '\0';
-                               value = &url[ i ];
+#ifdef WIN32
+                               if ( url[i] == ':' && url[i + 1] != '/' )
+                               {
+#endif
+                                       url[ i++ ] = '\0';
+                                       value = &url[ i ];
+#ifdef WIN32
+                               }
+#endif
                                break;
                        
                        case '&':
@@ -1555,16 +1569,20 @@ static int file_exists( char *file )
 
 mlt_producer producer_xml_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 ) );
+       xmlSAXHandler *sax, *sax_orig;
+       struct deserialise_context_s *context;
        mlt_properties properties = NULL;
        int i = 0;
        struct _xmlParserCtxt *xmlcontext;
        int well_formed = 0;
        char *filename = NULL;
-       int info = strcmp( id, "xml-string" ) ? 0 : 1;
+       int is_filename = strcmp( id, "xml-string" );
+
+       // Strip file:// prefix
+       if ( data && strlen( data ) >= 7 && strncmp( data, "file://", 7 ) == 0 )
+               data += 7;
 
-       if ( data == NULL || !strcmp( data, "" ) || ( info == 0 && !file_exists( data ) ) )
+       if ( data == NULL || !strcmp( data, "" ) || ( is_filename && !file_exists( data ) ) )
                return NULL;
 
        context = calloc( 1, sizeof( struct deserialise_context_s ) );
@@ -1575,10 +1593,11 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        context->destructors = mlt_properties_new();
        context->params = mlt_properties_new();
        context->profile = profile;
+       context->seekable = 1;
 
        // Decode URL and parse parameters
        mlt_properties_set( context->producer_map, "root", "" );
-       if ( info == 0 )
+       if ( is_filename )
        {
                filename = strdup( data );
                parse_url( context->params, url_decode( filename, data ) );
@@ -1607,15 +1626,20 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        // We need to track the number of registered filters
        mlt_properties_set_int( context->destructors, "registered", 0 );
 
-       // Setup SAX callbacks
+       // Setup SAX callbacks for first pass
+       sax = calloc( 1, sizeof( xmlSAXHandler ) );
        sax->startElement = on_start_element;
+       sax->characters = on_characters;
+       sax->warning = on_error;
+       sax->error = on_error;
+       sax->fatalError = on_error;
 
        // 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 )
+       if ( is_filename )
                xmlcontext = xmlCreateFileParserCtxt( filename );
        else
                xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
@@ -1633,20 +1657,37 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        }
 
        // Parse
+       sax_orig = xmlcontext->sax;
        xmlcontext->sax = sax;
        xmlcontext->_private = ( void* )context;        
        xmlParseDocument( xmlcontext );
+       well_formed = xmlcontext->wellFormed;
        
        // Cleanup after parsing
-       xmlcontext->sax = NULL;
+       xmlcontext->sax = sax_orig;
        xmlcontext->_private = NULL;
+       if ( xmlcontext->myDoc )
+               xmlFreeDoc( xmlcontext->myDoc );
        xmlFreeParserCtxt( xmlcontext );
        context->stack_node_size = 0;
        context->stack_service_size = 0;
 
+       // Bad xml - clean up and return NULL
+       if ( !well_formed )
+       {
+               mlt_properties_close( context->producer_map );
+               mlt_properties_close( context->destructors );
+               mlt_properties_close( context->params );
+               xmlFreeDoc( context->entity_doc );
+               free( context );
+               free( sax );
+               free( filename );
+               return NULL;
+       }
+
        // Setup the second pass
        context->pass ++;
-       if ( info == 0 )
+       if ( is_filename )
                xmlcontext = xmlCreateFileParserCtxt( filename );
        else
                xmlcontext = xmlCreateMemoryParserCtxt( data, strlen( data ) );
@@ -1664,15 +1705,22 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
                return NULL;
        }
 
-       // Setup SAX callbacks
+       // Create the qglsl consumer now, if requested, so that glsl.manager
+       // may exist when trying to load glsl. or movit. services.
+       // The "if requested" part can come from query string qglsl=1 or when
+       // a service beginning with glsl. or movit. appears in the XML.
+       if ( mlt_properties_get_int( context->params, "qglsl" ) )
+               context->qglsl = mlt_factory_consumer( profile, "qglsl", NULL );
+
+       // Setup SAX callbacks for second pass
        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;
 
        // Parse
+       sax_orig = xmlcontext->sax;
        xmlcontext->sax = sax;
        xmlcontext->_private = ( void* )context;
        xmlParseDocument( xmlcontext );
@@ -1682,6 +1730,11 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        xmlFreeDoc( context->entity_doc );
        free( sax );
        xmlMemoryDump( ); // for debugging
+       xmlcontext->sax = sax_orig;
+       xmlcontext->_private = NULL;
+       if ( xmlcontext->myDoc )
+               xmlFreeDoc( xmlcontext->myDoc );
+       xmlFreeParserCtxt( xmlcontext );
 
        // Get the last producer on the stack
        enum service_type type;
@@ -1734,8 +1787,17 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
                if ( getenv( "MLT_XML_DEEP" ) == NULL )
                {
                        // Now assign additional properties
-                       if ( info == 0 )
+                       if ( is_filename && (
+                               mlt_service_identify( service ) == tractor_type ||
+                               mlt_service_identify( service ) == playlist_type ||
+                               mlt_service_identify( service ) == multitrack_type ) )
+                       {
+                               mlt_properties_set_int( properties, "_original_type",
+                                       mlt_service_identify( service ) );
+                               mlt_properties_set( properties, "_original_resource",
+                                       mlt_properties_get( properties, "resource" ) );
                                mlt_properties_set( properties, "resource", data );
+                       }
 
                        // This tells consumer_xml not to deep copy
                        mlt_properties_set( properties, "xml", "was here" );
@@ -1751,6 +1813,8 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
                mlt_properties_inc_ref( MLT_CONSUMER_PROPERTIES( context->consumer ) );
                mlt_properties_set_data( properties, "consumer", context->consumer, 0,
                        (mlt_destructor) mlt_consumer_close, NULL );
+
+               mlt_properties_set_int( properties, "seekable", context->seekable );
        }
        else
        {
@@ -1759,6 +1823,8 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        }
 
        // Clean up
+       if ( context->qglsl && context->consumer != context->qglsl )
+               mlt_consumer_close( context->qglsl );
        mlt_properties_close( context->producer_map );
        if ( context->params != NULL )
                mlt_properties_close( context->params );
index 77d386c5a51f86d94418082b8326e6e0f82f9371..b263644376cba1ce1d85a4d001493e3538d3c47c 100644 (file)
@@ -6,7 +6,7 @@ all clean:
        for subdir in $$list; do \
                if [ -x $$subdir/build -a ! -f .$$subdir -o $@ = clean ] ; \
                then echo -n Building $$subdir... ; \
-                       cd $$subdir && output=`./build $@ 2>&1` ; \
+                       cd $$subdir && output=`CXXFLAGS="$(CXXFLAGS)" ./build $@ 2>&1` ; \
                        if [ $$? -eq 0 ] ; \
                        then echo OK && touch ../.$$subdir ; \
                        else echo $$output && exit 1 ; \
index 7ca1aa02fd270abf296cea879ce63a5eca041c09..c67142d7a97ad3cbd60f3e7976caa243d1ed18f9 100755 (executable)
@@ -17,10 +17,10 @@ then
        swig -c++ -I../../mlt++ -I../.. -csharp -dllimport libmltsharp -outdir src_swig -namespace Mlt mlt.i || exit $?
 
        # Compile the wrapper
-       g++ -fPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit $?
+       g++ -fPIC -D_GNU_SOURCE ${CXXFLAGS} -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit $?
        
        # Create the module
-       g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o libmltsharp.so || exit $?
+       g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o libmltsharp.so || exit $?
 
        # Compile the library assembly
        mcs -out:mlt-sharp.dll -target:library src_swig/*.cs
index 09ff1f112954d0e3702da29612eb4557c9344604..d6d0d558b2aff233d9d3579eacdc681ab625d5e2 100755 (executable)
@@ -24,10 +24,10 @@ then
        swig -c++ -I../../mlt++ -I../.. -java -outdir src_swig/org/mltframework -package org.mltframework mlt.i || exit $?
 
        # Compile the wrapper
-       g++ -fPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. mlt_wrap.cxx $JAVA_INCLUDE || exit $?
+       g++ -fPIC -D_GNU_SOURCE ${CXXFLAGS} -c -rdynamic -pthread -I../.. mlt_wrap.cxx $JAVA_INCLUDE || exit $?
        
        # Create the module
-       g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o libmlt_java.so || exit $?
+       g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o libmlt_java.so || exit $?
 
        # Compile the test
        javac `find src_swig -name '*.java'` || exit $?
index 2187bf30a447529e9d7f069d6c64f6ee97752a18..434e4d12afcddc8e42774741f123232c31cbd0f0 100755 (executable)
@@ -16,10 +16,10 @@ then
        swig -c++ -I../../mlt++ -I../.. -lua mlt.i || exit $?
 
        # Compile the wrapper
-       g++ -fPIC -DPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit $?
+       g++ -fPIC -DPIC -D_GNU_SOURCE ${CXXFLAGS} -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit $?
 
        # Create the module
-       g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit $?
+       g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit $?
 else
        echo Lua not installed.
        exit 1
index 4bb129638f125fa0157048e0a0dc3fb73e60f3c0..c3deaeb9af87c85c6fec2a6c5eedb104512ea633 100644 (file)
@@ -101,6 +101,8 @@ void mlt_log_set_level( int );
 %include <MltParser.h>
 %include <MltFilteredConsumer.h>
 
+
+
 #if defined(SWIGRUBY)
 
 %{
@@ -109,28 +111,31 @@ static void ruby_listener( mlt_properties owner, void *object );
 
 class RubyListener
 {
-       private:
+       protected:
                VALUE callback;
                Mlt::Event *event;
 
        public:
-               RubyListener( Mlt::Properties &properties, char *id, VALUE callback ) : 
+               RubyListener( VALUE callback ) : callback( callback )
+               {}
+
+               RubyListener( Mlt::Properties &properties, char *id, VALUE callback ) :
                        callback( callback ) 
                {
                        event = properties.listen( id, this, ( mlt_listener )ruby_listener );
                }
 
-               ~RubyListener( )
+               virtual ~RubyListener( )
                {
                        delete event;
                }
 
-       void mark( ) 
+               void mark( )
                { 
                        ((void (*)(VALUE))(rb_gc_mark))( callback ); 
                }
 
-       void doit( ) 
+               void doit( )
                {
                ID method = rb_intern( "call" );
                rb_funcall( callback, method, 0 );
@@ -149,19 +154,60 @@ void markRubyListener( void* p )
     o->mark( );
 }
 
+static void on_playlist_next( mlt_properties owner, void *object, int i );
+
+class PlaylistNextListener : RubyListener
+{
+       private:
+               Mlt::Event *event;
+
+       public:
+               PlaylistNextListener( Mlt::Properties *properties, VALUE proc )
+                       : RubyListener( proc )
+               {
+                       event = properties->listen( "playlist-next", this, ( mlt_listener )on_playlist_next );
+               }
+
+               ~PlaylistNextListener()
+               {
+                       delete event;
+               }
+
+               void yield( int i )
+               {
+                       ID method = rb_intern( "call" );
+                       rb_funcall( callback, method, 1, INT2FIX( i ) );
+               }
+};
+
+static void on_playlist_next( mlt_properties owner, void *object, int i )
+{
+       PlaylistNextListener *o = static_cast< PlaylistNextListener * >( object );
+       o->yield( i );
+}
+
 %}
 
 // Ruby wrapper
 %rename( Listener )  RubyListener;
 %markfunc RubyListener "markRubyListener";
+%markfunc PlaylistNextListener "markRubyListener";
 
-class RubyListener 
+class RubyListener
 {
        public:
                RubyListener( Mlt::Properties &properties, char *id, VALUE callback );
 };
 
-#endif
+class PlaylistNextListener
+{
+       public:
+               PlaylistNextListener( Mlt::Properties *properties, VALUE proc );
+};
+
+#endif // SWIGGRUBY
+
+
 
 #if defined(SWIGPYTHON)
 %{
index dc58c4c873b34f1bf0741c73407d6aa9d3a09350..1cab0dd437f24dad01fe887749451ba09dd380a4 100644 (file)
@@ -7,7 +7,7 @@ system( "ln -sf ../mlt.i" );
 system( "swig -c++ -I../../mlt++ -I../.. -perl5 mlt.i" ); 
 WriteMakefile(
        'NAME'    => 'mlt',
-       'CC'      => '${CXX} -fPIC -I../..',
+       'CC'      => '${CXX} -fPIC ${CXXFLAGS} -I../..',
        'OPTIMIZE' => '-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions',
        'LIBS'    => ['-L../../mlt++ -lmlt++'],
        'OBJECT'  => 'mlt_wrap.o',
index 1a5b6e236b439f6acb2aeb5532c1fe95e74e6d1f..c57baf597853a1ddd4173e106451f3746c61ab23 100755 (executable)
@@ -6,5 +6,5 @@ then
        exit 0
 fi
 
-perl Makefile.PL || exit 1
+CXXFLAGS="$CXXFLAGS" perl Makefile.PL || exit 1
 make
index 1c53e1c384de2127ad3db20431df03508c9ce612..21be7a80133e88dc5f8124ca394c7819fedbf746 100755 (executable)
@@ -9,5 +9,5 @@ fi
 
 ln -sf ../mlt.i
 swig -c++ -I../../mlt++ -I../.. -php5 -noproxy mlt.i
-g++ -fPIC -DPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. `php-config --includes` mlt_wrap.cpp
-g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit $?
+g++ -fPIC -DPIC -D_GNU_SOURCE ${CXXFLAGS} -c -rdynamic -pthread -I../.. `php-config --includes` mlt_wrap.cpp
+g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit $?
index bf930da9b3aff1e320ba4946a440388e936aa988..3e9e9a00151cd08b1207aa0b43a1447151b7d267 100755 (executable)
@@ -21,10 +21,10 @@ then
        swig -c++ -I../../mlt++ -I../.. -python mlt.i || exit $?
 
        # Compile the wrapper
-       g++ -fPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. -I$PYTHON_INCLUDE mlt_wrap.cxx || exit $?
+       g++ -fPIC -D_GNU_SOURCE ${CXXFLAGS} -c -I../.. -I$PYTHON_INCLUDE mlt_wrap.cxx || exit $?
 
        # Create the module
-       g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -L../../framework -lmlt $(python-config --ldflags) -o _mlt.so || exit $?
+       g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -L../../framework -lmlt $(python-config --ldflags) -o _mlt.so || exit $?
 else
        echo Python not installed.
        exit 1
diff --git a/src/swig/python/switcher.py b/src/swig/python/switcher.py
new file mode 100755 (executable)
index 0000000..d0994a5
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Import required modules
+import mlt
+import time
+import sys
+import tornado.ioloop
+import tornado.web
+
+# Start the mlt system
+mlt.mlt_log_set_level(40) # verbose
+mlt.Factory.init()
+
+# Establish a pipeline
+profile = mlt.Profile("atsc_1080i_5994")
+profile.set_explicit(1)
+tractor = mlt.Tractor()
+tractor.set("eof", "loop")
+fg_resource = "decklink:0"
+bg_resource = "decklink:1"
+if len(sys.argv) > 2:
+  fg_resource = sys.argv[1]
+  bg_resource = sys.argv[2]
+fg = mlt.Producer(profile, fg_resource)
+bg = mlt.Producer(profile, bg_resource)
+tractor.set_track(bg, 0)
+tractor.set_track(fg, 1)
+composite = mlt.Transition(profile, "composite")
+composite.set("fill", 1)
+tractor.plant_transition(composite)
+
+# Setup the consumer
+consumer = "decklink:2"
+if len(sys.argv) > 3:
+  consumer = sys.argv[3]
+consumer = mlt.Consumer(profile, consumer)
+consumer.connect(tractor)
+consumer.set("real_time", -2)
+consumer.start()
+
+flip_flop = False
+def switch():
+  global composite, flip_flop
+  frame = fg.frame() + 2
+  if flip_flop:
+    s = "0=20%%/0:100%%x80%%; %d=20%%/0:100%%x80%%; %d=0/0:100%%x100%%" % (frame, frame + 30)
+    composite.set("geometry", s)
+  else:
+    s = "0=0/0:100%%x100%%; %d=0/0:100%%x100%%; %d=20%%/0:100%%x80%%" % (frame, frame + 30)
+    composite.set("geometry", s)
+  flip_flop = not flip_flop
+
+
+def output_form(handler):
+  handler.write('<form action="/" method="post"><input type="submit" value="Switch"></form>')
+
+class SwitchHandler(tornado.web.RequestHandler):
+  def get(self):
+    switch()
+
+class MainHandler(tornado.web.RequestHandler):
+  def get(self):
+    output_form(self)
+
+  def post(self):
+    switch()
+    output_form(self)
+
+application = tornado.web.Application([
+    (r"/", MainHandler),
+    (r"/switch", SwitchHandler)
+])
+
+application.listen(8888)
+tornado.ioloop.IOLoop.instance().start()
diff --git a/src/swig/python/webvfx_generator.py b/src/swig/python/webvfx_generator.py
new file mode 100755 (executable)
index 0000000..304dec9
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# webvfx_generator.py
+# Copyright (C) 2013 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.
+
+# Import required modules
+import mlt
+import time
+import sys
+import tornado.ioloop
+import tornado.web
+import shutil
+import tempfile
+import os
+import os.path
+
+# Start the mlt system
+mlt.mlt_log_set_level(40) # verbose
+mlt.Factory.init()
+
+# Establish a pipeline
+profile = mlt.Profile("atsc_1080i_5994")
+#profile = mlt.Profile('square_ntsc_wide')
+profile.set_explicit(1)
+tractor = mlt.Tractor()
+tractor.set('eof', 'loop')
+playlist = mlt.Playlist()
+playlist.append(mlt.Producer(profile, 'color:'))
+
+# Setup the consumer
+consumer = 'decklink:0'
+if len(sys.argv) > 1:
+  consumer = sys.argv[1]
+consumer = mlt.Consumer(profile, consumer)
+consumer.connect(playlist)
+#consumer.set("real_time", -2)
+consumer.start()
+
+def switch(resource):
+  global playlist
+  resource = resource
+  playlist.lock()
+  playlist.append(mlt.Producer(profile, str(resource)))
+  playlist.remove(0)
+  playlist.unlock()
+
+state = {}
+state['tempdir'] = None
+
+class MainHandler(tornado.web.RequestHandler):
+  def get(self):
+    resource = self.get_argument('url', None)
+    if resource:
+      global state
+
+      self.write('Playing %s\n' % (resource))
+      switch(resource)
+
+      olddir = state['tempdir']
+      if olddir:
+        shutil.rmtree(olddir, True)
+      state['tempdir'] = None
+
+    else:
+      self.write('''
+<p>POST a bunch of files to / to change the output.</p>
+<p>Or GET / with query string parameter "url" to display something from the network.</p>
+''')
+
+  def post(self):
+    if len(self.request.files) == 0:
+      self.write('POST a bunch of files to / to change the output')
+    else:
+      global state
+      olddir = state['tempdir']
+      resource = None
+      state['tempdir'] = tempfile.mkdtemp()
+      for key, items in self.request.files.iteritems():
+        for item in items:
+          path = os.path.dirname(key)
+          fn = item.filename
+          if path: 
+            if not os.path.exists(os.path.join(state['tempdir'], path)):
+              os.makedirs(os.path.join(state['tempdir'], path))
+            fn = os.path.join(path, fn)
+          fn = os.path.join(state['tempdir'], fn)
+          if not path and fn.endswith('.html') or fn.endswith('.qml'):
+            resource = fn
+          with open(fn, 'w') as fo:
+            fo.write(item.body)
+          self.write("Uploaded %s\n" % (fn))
+      if resource:
+        self.write('Playing %s\n' % (resource))
+        switch(resource)
+      if olddir:
+        shutil.rmtree(olddir, True)
+
+application = tornado.web.Application([
+    (r"/", MainHandler),
+])
+
+application.listen(8888)
+try:
+  tornado.ioloop.IOLoop.instance().start()
+except:
+  pass
+
+consumer.stop()
+if state['tempdir']:
+  shutil.rmtree(state['tempdir'], True)
index 5ef45d29afa2c00d54bf3b18eab3695527d9e253..6c6e9cab49531e397178bf2fcd137ca2b897c776 100755 (executable)
@@ -6,7 +6,7 @@ if ARGV.shift == 'clean'
 end
 system( "ln -sf ../mlt.i" )
 system( "swig -c++ -ruby -I../../mlt++ -I../.. mlt.i" )
-$CFLAGS += " -I../.."
+$CFLAGS += " -I../.. " + ENV['CXXFLAGS']
 $LDFLAGS += " -L../../mlt++ -lmlt++"
 create_makefile('mlt')
 system( "make" )
index 80f3977055227eb2f570cb0d28e2fdc5b2c8b4ea..9559b96aabc8af7ee0af350700acd9256dfcb887 100755 (executable)
 #!/usr/bin/env ruby
+require 'erb'
+require 'yaml'
 require 'mlt'
 
 $repo = Mlt::Factory::init
 
+$optional_params = [
+  'minimum',
+  'maximum',
+  'default',
+  'unit',
+  'scale',
+  'format',
+  'widget'
+]
+template = %q{%%META:TOPICPARENT{name="Plugins<%= type_title %>s"}%
+<noautolink>
+---+ <%= type_title %>: <%= yml['identifier'] %> 
+%%TOC%
+---++ Plugin Information
+title: <%= yml['title'] %> %BR%
+% if yml['tags']
+media types:
+%   yml['tags'].each do |x|
+<%= x %> 
+%   end
+%%BR%
+% end
+description: <%= yml['description'] %> %BR%
+version: <%= yml['version'] %> %BR%
+creator: <%= yml['creator'] %> %BR%
+% yml['contributor'] and yml['contributor'].each do |x|
+contributor: <%= x %> %BR%
+% end 
+<%= "license: #{yml['license']} %BR%\n" if yml['license'] %>
+<%= "URL: [[#{yml['url']}]] %BR%\n" if yml['url'] %>
+
+% if yml['notes']
+---++ Notes
+%   yml['notes'].each do |x|
+<%= x %>
+%   end
+% end
+
+% if yml['bugs']
+---++ Bugs
+%   yml['bugs'].each do |x|
+   * <%= x %>
+%   end
+% end
+
+% if yml['parameters']
+---++ Parameters
+%   yml['parameters'].each do |param|
+---+++ <%= param['identifier'] %>
+<%= "title: #{param['title']} %BR%\n" if param['title'] %>
+<%= "description: #{param['description']} %BR%\n" if param['description'] %>
+type: <%= param['type'] %> %BR%
+readonly: <%= param['readonly'] or 'no' %> %BR%
+required: <%= param['required'] or 'no' %> %BR%
+%     $optional_params.each do |key|
+<%= "#{key}: #{param[key]} %BR%\n" if param[key] %>
+%     end
+%     if param['values']
+values:
+%       param['values'].each do |value|
+   * <%= value %>
+%       end
+%     end 
+
+%   end
+% end
+</noautolink>
+}
+
+$processor = ERB.new(template, 0, "%<>")
+
+
 def output(mlt_type, services, type_title)
   index = File.open("Plugins#{type_title}s.txt", 'w')
   index.puts '%META:TOPICPARENT{name="Documentation"}%'
+  index.puts '<noautolink>'
   index.puts "---+ #{type_title} Plugins"
-  (0..(services.count - 1)).each {|i|
-    name = services.get_name(i)
+  unsorted = []
+  (0..(services.count - 1)).each do |i|
+    unsorted << services.get_name(i)
+  end
+  unsorted.sort().each do |name|
     meta = $repo.metadata(mlt_type, name)
     if meta.is_valid
       filename = type_title + name.capitalize.gsub('.', '-')
-      File.open(filename + '.txt', 'w') do |f|
-        f.puts %Q/%META:TOPICPARENT{name="Plugins#{type_title}s"}%/
-        f.puts "---+ #{type_title} Plugin"
-        f.puts "---++ #{name}"
-        f.puts '<verbatim>'
-        f.puts meta.serialise_yaml
-        f.puts '</verbatim>'
-        puts "Wrote file #{filename}.txt"
-        index.puts "   * [[#{filename}][#{name}]]: #{meta.get('title')}\n"
+      puts "Processing #{filename}"
+      yml = YAML.load(meta.serialise_yaml)
+      if yml
+        File.open(filename + '.txt', 'w') do |f|
+          f.puts $processor.result(binding)
+        end
+      else
+        puts "Failed to write file for #{filename}"
       end
+      index.puts "   * [[#{filename}][#{name}]]: #{meta.get('title')}\n"
     end
-  }
+  end 
+  index.puts '</noautolink>'
   index.close
 end
 
diff --git a/src/swig/ruby/playlist.rb b/src/swig/ruby/playlist.rb
new file mode 100755 (executable)
index 0000000..99bb341
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/env ruby
+
+# Import required modules
+require 'mlt'
+
+# Create the mlt system
+Mlt::Factory::init
+
+# Establish the mlt profile
+profile = Mlt::Profile.new
+
+# Get and check the argument
+file = ARGV.shift
+raise "Usage: test.rb file1 file2" if file.nil?
+file2 = ARGV.shift
+raise "Usage: test.rb file1 file2" if file2.nil?
+
+pls = Mlt::Playlist.new(profile)
+
+# Create the producer
+producer = Mlt::Factory::producer( profile, file )
+raise "Unable to load #{file}" if !producer.is_valid
+
+producer2 = Mlt::Factory::producer( profile, file2 )
+raise "Unable to load #{file2}" if !producer2.is_valid
+
+pls.append(producer)
+#pls.repeat(0, 2)
+pls.append(producer2)
+
+# Create the consumer
+consumer = Mlt::Consumer.new( profile, "sdl" )
+raise "Unable to open sdl consumer" if !consumer.is_valid
+
+# Turn off the default rescaling
+consumer.set( "rescale", "none" )
+consumer.set("volume", 0.1)
+consumer.set("terminate_on_pause", 1)
+
+Mlt::PlaylistNextListener.new(pls, Proc.new { |i|
+    info = pls.clip_info(i)
+    puts "finished playing #{info.resource}\n"
+})
+
+
+# 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( pls )
+
+# Wait until the user stops the consumer
+consumer.wait_for( event )
+
+# Clean up consumer
+consumer.stop
+
index eeb7a8e90180982178b67a65bf3aa6c70c7378fc..78c839b8b8357ffffc9a8e1514850ac1157902b2 100755 (executable)
@@ -16,10 +16,10 @@ then
        swig -c++ -I../../mlt++ -I../.. -tcl mlt.i || exit 1
 
        # Compile the wrapper
-       g++ -fPIC -D_GNU_SOURCE -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit 1
+       g++ -fPIC -D_GNU_SOURCE ${CXXFLAGS} -c -rdynamic -pthread -I../.. mlt_wrap.cxx || exit 1
 
        # Create the module
-       g++ -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit 1
+       g++ ${CXXFLAGS} -shared mlt_wrap.o -L../../mlt++ -lmlt++ -o mlt.so || exit 1
 else
        echo "Unable to locate tclsh."
        exit 1