]> git.sesse.net Git - mlt/commitdiff
Change how the Movit chain is built.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 1 Jan 2014 17:14:18 +0000 (18:14 +0100)
committerDan Dennedy <dan@dennedy.org>
Tue, 14 Jan 2014 06:01:55 +0000 (22:01 -0800)
* Build the chain in GlslManager.

  This allows us to get rid of effects that don't actually do anything
  (like all the normalizers in the common case); in Movit, they tend
  to burn a lot of memory bandwidth. We solve this by a new OptionalEffect
  template, that can rewrite itself out of the graph if it sees it is
  a no-op. We need to recreate the chain from scratch if this status
  should change (e.g. the input resolution changed from one frame to the
  next, and we thus suddenly need resizing after all), so we keep a
  "fingerprint" string that contains all the unique IDs of the services
  in use, as well as their disabled status, and compare against this frame.

  Building the chain in one piece also opens up for transitions to be more
  efficient; they are now built as part of one big Movit chain, instead of
  bouncing to an 8-bit sRGB buffer and back.

* Change the mlt_glsl type.

  Now, the mlt_glsl image type has a defined value, which is the
  mlt_service pointer. Each filter is responsible for storing this input
  service. This, together with the mlt_frame, enables us to actually
  build the Movit chain based on the MLT relations, instead of just relying in
  the order in which they are called and assuming everything has a single input.

  As a special case, the value (mlt_service) -1 (which should never be a valid
  pointer) means that we read the information from an input rather than an
  effect. In this case, we take a copy of the pixel data we get in (since it
  will soon be garbage collected), store it in an MltInput and then store that
  MltInput for later use. This could probably be further simplified in the
  future to get completely rid of MltInput and just use the regular
  FlatInput/YCbCrInput instead.

  This also requires us to change so that the chain is built and finalized at
  the _end_ of the conversion steps (where it's logically needed), instead of at
  the beginning as before. The beginning (conversion from * -> mlt_glsl) now
  only stores the input as described below.

* Change Effect and EffectChain storage.

  This changes the storage of Movit stuff as follows:

   - The EffectChain (along with some associated information to be able
     to more easily locate the services and Effect pointers; together,
     called a GlslChain) is now stored on the output service, not on the input
     producer. This allows us to have multiple EffectChains floating around.
   - The Effect pointers no longer live permanently on the MLT graph, since
     each MLT service can have more than one Effect. Instead, they live
     temporarily on the frame (because the frame is not shared between
     threads, giving us a poor man's version of thread-local storage),
     until they reach the point where we decide if we need to rebuild the
     EffectChain or not. At this point, they are either made part of the
     chain (and owned by it), or disposed as unneeded.
   - The MltInput also lives on the frame. (If we have multiple inputs,
     we also have multiple frames.) As mentioned above, its use is signaled by
     an mlt_service of -1.

* Change how Movit parameter setting works.

  Services no longer set parameters directly on the Movit filters, since
  they cannot know before the graph construction time whether the correct
  destination is the newly created Effect, or a similar one in the EffectChain.
  Instead, they set special properties (movit.parms.<type>.<name>[<index>]),
  and then the convert filter uses these to set Movit parameters on the right
  Effects.

21 files changed:
src/modules/opengl/filter_glsl_manager.cpp
src/modules/opengl/filter_glsl_manager.h
src/modules/opengl/filter_movit_blur.cpp
src/modules/opengl/filter_movit_convert.cpp
src/modules/opengl/filter_movit_crop.cpp
src/modules/opengl/filter_movit_deconvolution_sharpen.cpp
src/modules/opengl/filter_movit_diffusion.cpp
src/modules/opengl/filter_movit_glow.cpp
src/modules/opengl/filter_movit_lift_gamma_gain.cpp
src/modules/opengl/filter_movit_mirror.cpp
src/modules/opengl/filter_movit_opacity.cpp
src/modules/opengl/filter_movit_resample.cpp
src/modules/opengl/filter_movit_resize.cpp
src/modules/opengl/filter_movit_saturation.cpp
src/modules/opengl/filter_movit_vignette.cpp
src/modules/opengl/filter_movit_white_balance.cpp
src/modules/opengl/mlt_movit_input.cpp
src/modules/opengl/mlt_movit_input.h
src/modules/opengl/optional_effect.h [new file with mode: 0644]
src/modules/opengl/transition_movit_mix.cpp
src/modules/opengl/transition_movit_overlay.cpp

index 9cb0855cb5da0ea530df2e7c02cbdfbfbff14290..d941f8e9f2d6ec0710b63c0e26d53cd55e609844 100644 (file)
@@ -290,9 +290,6 @@ 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();
 }
 
@@ -316,102 +313,95 @@ mlt_filter filter_glsl_manager_init( mlt_profile profile, mlt_service_type type,
 
 } // extern "C"
 
-Mlt::Properties GlslManager::effect_list( Mlt::Service& service )
+static void deleteChain( GlslChain* chain )
 {
-       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;
+       delete chain->effect_chain;
+       delete chain;
+}
+       
+void* GlslManager::get_frame_specific_data( mlt_service service, mlt_frame frame, const char *key, int *length )
+{
+       const char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
+       char buf[256];
+       snprintf( buf, sizeof(buf), "%s_%s", key, unique_id );
+       return mlt_properties_get_data( MLT_FRAME_PROPERTIES(frame), buf, length );
 }
 
-static void deleteChain( EffectChain* chain )
+int GlslManager::set_frame_specific_data( mlt_service service, mlt_frame frame, const char *key, void *value, int length, mlt_destructor destroy, mlt_serialiser serialise )
 {
-       delete chain;
+       const char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
+       char buf[256];
+       snprintf( buf, sizeof(buf), "%s_%s", key, unique_id );
+       return mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), buf, value, length, destroy, serialise );
 }
 
-bool GlslManager::init_chain( mlt_service aservice )
+void GlslManager::set_chain( mlt_service service, GlslChain* chain )
 {
-       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;
+       mlt_properties_set_data( MLT_SERVICE_PROPERTIES(service), "_movit chain", chain, 0, (mlt_destructor) deleteChain, NULL );
 }
 
-EffectChain* GlslManager::get_chain( mlt_service service )
+GlslChain* GlslManager::get_chain( mlt_service service )
 {
-       return (EffectChain*) mlt_properties_get_data( MLT_SERVICE_PROPERTIES(service), "movit chain", NULL );
+       return (GlslChain*) mlt_properties_get_data( MLT_SERVICE_PROPERTIES(service), "_movit chain", NULL );
+}
+       
+Effect* GlslManager::get_effect( mlt_service service, mlt_frame frame )
+{
+       return (Effect*) get_frame_specific_data( service, frame, "_movit effect", NULL );
 }
 
-MltInput *GlslManager::get_input( mlt_service service )
+Effect* GlslManager::set_effect( mlt_service service, mlt_frame frame, Effect* effect )
 {
-       return (MltInput*) mlt_properties_get_data( MLT_SERVICE_PROPERTIES(service), "movit input", NULL );
+       set_frame_specific_data( service, frame, "_movit effect", effect, 0, NULL, NULL );
+       return effect;
 }
 
-void GlslManager::reset_finalized( mlt_service service )
+MltInput* GlslManager::get_input( mlt_producer producer, mlt_frame frame )
 {
-       mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_movit finalized", 0 );
+       return (MltInput*) get_frame_specific_data( MLT_PRODUCER_SERVICE(producer), frame, "_movit input", NULL );
 }
 
-Effect* GlslManager::get_effect( mlt_service service, mlt_frame frame )
+MltInput* GlslManager::set_input( mlt_producer producer, mlt_frame frame, MltInput* input )
 {
-       Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
-       char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
-       return (Effect*) GlslManager::get_instance()->effect_list( producer ).get_data( unique_id );
+       set_frame_specific_data( MLT_PRODUCER_SERVICE(producer), frame, "_movit input", input, 0, NULL, NULL );
+       return input;
 }
 
-Effect* GlslManager::add_effect( mlt_service service, mlt_frame frame, Effect* effect )
+uint8_t* GlslManager::get_input_pixel_pointer( mlt_producer producer, mlt_frame frame )
 {
-       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_SERVICE_PROPERTIES(service), "_unique_id" );
-       GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
-       return effect;
+       return (uint8_t*) get_frame_specific_data( MLT_PRODUCER_SERVICE(producer), frame, "_movit input pp", NULL );
 }
 
-Effect* GlslManager::add_effect( mlt_service service, mlt_frame frame, Effect* effect, Effect* input_b )
+uint8_t* GlslManager::set_input_pixel_pointer( mlt_producer producer, mlt_frame frame, uint8_t* image )
 {
-       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_SERVICE_PROPERTIES(service), "_unique_id" );
-       GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
-       return effect;
+       set_frame_specific_data( MLT_PRODUCER_SERVICE(producer), frame, "_movit input pp", image, 0, NULL, NULL );
+       return image;
 }
 
-void GlslManager::render_fbo( mlt_service service, void* chain, GLuint fbo, int width, int height )
+mlt_service GlslManager::get_effect_input( mlt_service service, mlt_frame frame )
 {
-       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 );
+       return (mlt_service) get_frame_specific_data( service, frame, "_movit effect input", NULL );
+}
+
+void GlslManager::set_effect_input( mlt_service service, mlt_frame frame, mlt_service input_service )
+{
+       set_frame_specific_data( service, frame, "_movit effect input", input_service, 0, NULL, NULL );
+}
+
+void GlslManager::get_effect_secondary_input( mlt_service service, mlt_frame frame, mlt_service *input_service, mlt_frame *input_frame)
+{
+       *input_service = (mlt_service) get_frame_specific_data( service, frame, "_movit effect secondary input", NULL );
+       *input_frame = (mlt_frame) get_frame_specific_data( service, frame, "_movit effect secondary input frame", NULL );
+}
+
+void GlslManager::set_effect_secondary_input( mlt_service service, mlt_frame frame, mlt_service input_service, mlt_frame input_frame )
+{
+       set_frame_specific_data( service, frame, "_movit effect secondary input", input_service, 0, NULL, NULL );
+       set_frame_specific_data( service, frame, "_movit effect secondary input frame", input_frame, 0, NULL, NULL );
 }
 
-int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int width, int height, uint8_t **image)
+int GlslManager::render_frame_texture(EffectChain *chain, mlt_frame frame, int width, int height, uint8_t **image)
 {
-       EffectChain* chain = get_chain( service );
-       if (!chain) return 1;
        glsl_fbo fbo = get_fbo( width, height );
        if (!fbo) return 1;
        glsl_texture texture = get_texture( width, height, GL_RGBA );
@@ -442,7 +432,7 @@ int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int
                glClientWaitSync( prev_sync, 0, GL_TIMEOUT_IGNORED );
                glDeleteSync( prev_sync );
        }
-       render_fbo( service, chain, fbo->fbo, width, height );
+       chain->render_to_fbo( fbo->fbo, width, height );
        prev_sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
        GLsync sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
 
@@ -461,10 +451,8 @@ int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int
        return 0;
 }
 
-int GlslManager::render_frame_rgba(mlt_service service, mlt_frame frame, int width, int height, uint8_t **image)
+int GlslManager::render_frame_rgba(EffectChain *chain, mlt_frame frame, int width, int height, uint8_t **image)
 {
-       EffectChain* chain = get_chain( service );
-       if (!chain) return 1;
        glsl_fbo fbo = get_fbo( width, height );
        if (!fbo) return 1;
        glsl_texture texture = get_texture( width, height, GL_RGBA );
@@ -492,7 +480,7 @@ int GlslManager::render_frame_rgba(mlt_service service, mlt_frame frame, int wid
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        check_error();
 
-       render_fbo( service, chain, fbo->fbo, width, height );
+       chain->render_to_fbo( fbo->fbo, width, height );
 
        // Read FBO into PBO
        glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
index 4bc3836b1e0a341277a06b16b04825221e3fdceb..c850c86ab567a03659b2efcc22ecb288ab0ac9b4 100644 (file)
@@ -23,6 +23,8 @@
 #include <glew.h>
 #include <mlt++/MltFilter.h>
 #include <mlt++/MltDeque.h>
+#include <map>
+#include <string>
 
 #define MAXLISTCOUNT 1024
 typedef struct glsl_list_s *glsl_list;
@@ -68,6 +70,19 @@ class Effect;
 class EffectChain;
 class MltInput;
 
+struct GlslChain
+{
+       EffectChain *effect_chain;
+
+       // All services owned by the effect chain and their associated Movit effect.
+       std::map<mlt_service, Effect*> effects;
+
+       // For each effect in the Movit graph, a unique identifier for the service
+       // and whether it's disabled or not, using post-order traversal.
+       // We need to generate the chain if and only if this has changed.
+       std::string fingerprint;
+};
+
 class GlslManager : public Mlt::Filter
 {
 public:
@@ -83,21 +98,30 @@ public:
        glsl_pbo get_pbo(int size);
        void cleanupContext();
 
-       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 void set_chain(mlt_service, GlslChain*);
+       static GlslChain* get_chain(mlt_service);
+
        static Effect* get_effect(mlt_service, mlt_frame);
-       static Effect* add_effect(mlt_service, mlt_frame, Effect*);
-       static Effect* add_effect(mlt_service, mlt_frame, Effect*, Effect* input_b);
-       static void render_fbo(mlt_service, void *chain, GLuint fbo, int width, int height);
-       int render_frame_texture(mlt_service, mlt_frame, int width, int height, uint8_t **image);
-       int render_frame_rgba(mlt_service, mlt_frame, int width, int height, uint8_t **image);
+       static Effect* set_effect(mlt_service, mlt_frame, Effect*);
+       static MltInput* get_input(mlt_producer, mlt_frame);
+       static MltInput* set_input(mlt_producer, mlt_frame, MltInput*);
+       static uint8_t* get_input_pixel_pointer(mlt_producer, mlt_frame);
+       static uint8_t* set_input_pixel_pointer(mlt_producer, mlt_frame, uint8_t*);
+
+       static mlt_service get_effect_input(mlt_service, mlt_frame);
+       static void set_effect_input(mlt_service, mlt_frame, mlt_service);
+       static void get_effect_secondary_input(mlt_service, mlt_frame, mlt_service*, mlt_frame*);
+       static void set_effect_secondary_input(mlt_service, mlt_frame, mlt_service, mlt_frame);
+
+       int render_frame_texture(EffectChain*, mlt_frame, int width, int height, uint8_t **image);
+       int render_frame_rgba(EffectChain*, mlt_frame, int width, int height, uint8_t **image);
        static void lock_service(mlt_frame frame);
        static void unlock_service(mlt_frame frame);
 
 private:
+       static void* get_frame_specific_data( mlt_service service, mlt_frame frame, const char *key, int *length );
+       static int set_frame_specific_data( mlt_service service, mlt_frame frame, const char *key, void *value, int length, mlt_destructor destroy, mlt_serialiser serialise );
+
        static void onInit( mlt_properties owner, GlslManager* filter );
        static void onClose( mlt_properties owner, GlslManager* filter );
        static void onServiceChanged( mlt_properties owner, mlt_service service );
index 54ccd92f4b2262b8bec7a5ae3210c5584032d88d..79acaaae3504d9360bc7085487d3e7930e54a9d3 100644 (file)
@@ -29,28 +29,22 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               double radius = mlt_properties_anim_get_double( properties, "radius",
-                       mlt_filter_get_position( filter, frame ),
-                       mlt_filter_get_length2( filter, frame ) );
-               bool ok = effect->set_float( "radius", radius );
-               assert(ok);
-       }
+       double radius = mlt_properties_anim_get_double( properties, "radius",
+               mlt_filter_get_position( filter, frame ),
+               mlt_filter_get_length2( filter, frame ) );
+       mlt_properties_set_double( properties, "movit.parms.float.radius",
+               radius );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new BlurEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame );
-               if ( !effect ) {
-                       effect = GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new BlurEffect() );
-                       assert(effect);
-               }
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 2229aebcf1757967a6dee88490ae82e39771c945..3e61dffcba6b1a846f81c6906e171d9ec640a46a 100644 (file)
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <string>
 
 #include "filter_glsl_manager.h"
 #include <movit/effect_chain.h>
@@ -103,6 +104,277 @@ static void get_format_from_properties( mlt_properties properties, ImageFormat*
        ycbcr_format->cb_y_position = ycbcr_format->cr_y_position = 0.5f;
 }
 
+static void build_fingerprint( mlt_service service, mlt_frame frame, std::string *fingerprint )
+{
+       if ( service == (mlt_service) -1 ) {
+               fingerprint->append( "input" );
+               return;
+       }
+
+       Effect* effect = GlslManager::get_effect( service, frame );
+       assert( effect );
+       mlt_service input_a = GlslManager::get_effect_input( service, frame );
+       fingerprint->push_back( '(' );
+       build_fingerprint( input_a, frame, fingerprint );
+       fingerprint->push_back( ')' );
+
+       mlt_frame frame_b;
+       mlt_service input_b;
+       GlslManager::get_effect_secondary_input( service, frame, &input_b, &frame_b );
+       if ( input_b ) {
+               fingerprint->push_back( '(' );
+               build_fingerprint( input_b, frame_b, fingerprint );
+               fingerprint->push_back( ')' );
+       }
+
+       fingerprint->push_back( '(' );
+       fingerprint->append( mlt_properties_get( MLT_SERVICE_PROPERTIES( service ), "_unique_id" ) );
+       bool disable = mlt_properties_get_int( MLT_SERVICE_PROPERTIES( service ), "movit.disable" );
+       if ( disable ) {
+               fingerprint->push_back( 'd' );
+               bool ok = effect->set_int( "disable", 1 );
+               assert(ok);
+       }
+       fingerprint->push_back( ')' );
+}
+
+static Effect* build_movit_chain( mlt_service service, mlt_frame frame, GlslChain *chain )
+{
+       if ( service == (mlt_service) -1 ) {
+               mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+               MltInput* input = GlslManager::get_input( producer, frame );
+               GlslManager::set_input( producer, frame, NULL );
+               chain->effect_chain->add_input( input );
+               chain->effects.insert(std::make_pair( MLT_SERVICE( producer ), input ) );
+               return input;
+       }
+
+       Effect* effect = GlslManager::get_effect( service, frame );
+       assert( effect );
+       GlslManager::set_effect( service, frame, NULL );
+
+       mlt_service input_a = GlslManager::get_effect_input( service, frame );
+       mlt_service input_b;
+       mlt_frame frame_b;
+       GlslManager::get_effect_secondary_input( service, frame, &input_b, &frame_b );
+       Effect *effect_a = build_movit_chain( input_a, frame, chain );
+
+       if ( input_b ) {
+               Effect *effect_b = build_movit_chain( input_b, frame_b, chain );
+               chain->effect_chain->add_effect( effect, effect_a, effect_b );
+       } else {
+               chain->effect_chain->add_effect( effect, effect_a );
+       }
+               
+       chain->effects.insert(std::make_pair( service, effect ) );
+       return effect;
+}
+
+static void dispose_movit_effects( mlt_service service, mlt_frame frame )
+{
+       if ( service == (mlt_service) -1 ) {
+               mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+               delete GlslManager::get_input( producer, frame );
+               GlslManager::set_input( producer, frame, NULL );
+               return;
+       }
+
+       delete GlslManager::get_effect( service, frame );
+       GlslManager::set_effect( service, frame, NULL );
+
+       mlt_service input_a = GlslManager::get_effect_input( service, frame );
+       mlt_service input_b;
+       mlt_frame frame_b;
+       GlslManager::get_effect_secondary_input( service, frame, &input_b, &frame_b );
+       dispose_movit_effects( input_a, frame );
+
+       if ( input_b ) {
+               dispose_movit_effects( input_b, frame_b );
+       }
+}
+
+static void finalize_movit_chain( mlt_service leaf_service, mlt_frame frame )
+{
+       GlslChain* chain = GlslManager::get_chain( leaf_service );
+
+       std::string new_fingerprint;
+       build_fingerprint( leaf_service, frame, &new_fingerprint );
+
+       // Build the chain if needed.
+       if ( !chain || new_fingerprint != chain->fingerprint ) {
+               printf("=== CREATING NEW CHAIN (old chain=%p, leaf=%p, fingerprint=%s) ===\n", chain, leaf_service, new_fingerprint.c_str());
+               mlt_profile profile = mlt_service_profile( leaf_service );
+               chain = new GlslChain;
+               chain->effect_chain = new EffectChain( profile->display_aspect_num, profile->display_aspect_den );
+               chain->fingerprint = new_fingerprint;
+
+               build_movit_chain( leaf_service, frame, chain );
+               chain->effect_chain->add_effect( new Mlt::VerticalFlip );
+
+               ImageFormat output_format;
+               output_format.color_space = COLORSPACE_sRGB;
+               output_format.gamma_curve = GAMMA_sRGB;
+               chain->effect_chain->add_output(output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+               chain->effect_chain->set_dither_bits(8);
+               chain->effect_chain->finalize();
+
+               GlslManager::set_chain( leaf_service, chain );
+       } else {
+               // Delete all the created Effect instances to avoid memory leaks.
+               dispose_movit_effects( leaf_service, frame );
+       }
+}
+
+static void set_movit_parameters( GlslChain *chain, mlt_service service, mlt_frame frame )
+{
+       if ( service == (mlt_service) -1 ) {
+               mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+               MltInput* input = (MltInput *) chain->effects[ MLT_PRODUCER_SERVICE( producer ) ];
+               input->set_pixel_data( GlslManager::get_input_pixel_pointer( producer, frame ) );
+               return;
+       }
+
+       Effect* effect = chain->effects[ service ];
+       mlt_service input_a = GlslManager::get_effect_input( service, frame );
+       set_movit_parameters( chain, input_a, frame );
+
+       mlt_service input_b;
+       mlt_frame frame_b;
+       GlslManager::get_effect_secondary_input( service, frame, &input_b, &frame_b );
+       if ( input_b ) {
+               set_movit_parameters( chain, input_b, frame_b );
+       }
+               
+       mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
+       int count = mlt_properties_count( properties );
+       for (int i = 0; i < count; ++i) {
+               const char *name = mlt_properties_get_name( properties, i );
+               if (strncmp(name, "movit.parms.float.", strlen("movit.parms.float.")) == 0) {
+                       bool ok = effect->set_float(name + strlen("movit.parms.float."),
+                               mlt_properties_get_double( properties, name ));
+                       assert(ok);
+               }
+               if (strncmp(name, "movit.parms.int.", strlen("movit.parms.int.")) == 0) {
+                       bool ok = effect->set_int(name + strlen("movit.parms.int."),
+                               mlt_properties_get_int( properties, name ));
+                       assert(ok);
+               }
+               if (strncmp(name, "movit.parms.vec3.", strlen("movit.parms.vec3.")) == 0 &&
+                   strcmp(name + strlen(name) - 3, "[0]") == 0) {
+                       float val[3];
+                       char *name_copy = strdup(name);
+                       char *index_char = name_copy + strlen(name_copy) - 2;
+                       val[0] = mlt_properties_get_double( properties, name_copy );
+                       *index_char = '1';
+                       val[1] = mlt_properties_get_double( properties, name_copy );
+                       *index_char = '2';
+                       val[2] = mlt_properties_get_double( properties, name_copy );
+                       index_char[-1] = '\0';
+                       bool ok = effect->set_vec3(name_copy + strlen("movit.parms.vec3."), val);
+                       assert(ok);
+                       free(name_copy);
+               }
+               if (strncmp(name, "movit.parms.vec4.", strlen("movit.parms.vec4.")) == 0 &&
+                   strcmp(name + strlen(name) - 3, "[0]") == 0) {
+                       float val[4];
+                       char *name_copy = strdup(name);
+                       char *index_char = name_copy + strlen(name_copy) - 2;
+                       val[0] = mlt_properties_get_double( properties, name_copy );
+                       *index_char = '1';
+                       val[1] = mlt_properties_get_double( properties, name_copy );
+                       *index_char = '2';
+                       val[2] = mlt_properties_get_double( properties, name_copy );
+                       *index_char = '3';
+                       val[3] = mlt_properties_get_double( properties, name_copy );
+                       index_char[-1] = '\0';
+                       bool ok = effect->set_vec4(name_copy + strlen("movit.parms.vec4."), val);
+                       assert(ok);
+                       free(name_copy);
+               }
+       }
+}
+
+static void dispose_pixel_pointers( mlt_service service, mlt_frame frame )
+{
+       if ( service == (mlt_service) -1 ) {
+               mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+               mlt_pool_release( GlslManager::get_input_pixel_pointer( producer, frame ) );
+               return;
+       }
+
+       mlt_service input_a = GlslManager::get_effect_input( service, frame );
+       dispose_pixel_pointers( input_a, frame );
+
+       mlt_service input_b;
+       mlt_frame frame_b;
+       GlslManager::get_effect_secondary_input( service, frame, &input_b, &frame_b );
+       if ( input_b ) {
+               dispose_pixel_pointers( input_b, frame_b );
+       }
+}
+
+static int movit_render( EffectChain *chain, mlt_frame frame, mlt_image_format *format, mlt_image_format output_format, int width, int height, uint8_t **image )
+{
+       GlslManager* glsl = GlslManager::get_instance();
+       int error;
+       if ( output_format == mlt_image_glsl_texture ) {
+               error = glsl->render_frame_texture( chain, frame, width, height, image );
+       }
+       else {
+               error = glsl->render_frame_rgba( chain, frame, width, height, image );
+               if ( !error && output_format != mlt_image_rgb24a ) {
+                       *format = mlt_image_rgb24a;
+                       error = convert_on_cpu( frame, image, format, output_format );
+               }
+       }
+       return error;
+}
+
+// Create an MltInput for an image with the given format and dimensions.
+static MltInput* create_input( mlt_properties properties, mlt_image_format format, int aspect_width, int aspect_height, int width, int height )
+{
+       MltInput* input = new MltInput( aspect_width, aspect_height );
+       if ( format == mlt_image_rgb24a || format == mlt_image_opengl ) {
+               // TODO: Get the color space if available.
+               input->useFlatInput( FORMAT_RGBA_POSTMULTIPLIED_ALPHA, width, height );
+       }
+       else if ( format == mlt_image_rgb24 ) {
+               // TODO: Get the color space if available.
+               input->useFlatInput( FORMAT_RGB, width, height );
+       }
+       else if ( format == mlt_image_yuv420p ) {
+               ImageFormat image_format;
+               YCbCrFormat ycbcr_format;
+               get_format_from_properties( properties, &image_format, &ycbcr_format );
+               ycbcr_format.chroma_subsampling_x = ycbcr_format.chroma_subsampling_y = 2;
+               input->useYCbCrInput( image_format, ycbcr_format, width, height );
+       }
+       else if ( format == mlt_image_yuv422 ) {
+               ImageFormat image_format;
+               YCbCrFormat ycbcr_format;
+               get_format_from_properties( properties, &image_format, &ycbcr_format );
+               ycbcr_format.chroma_subsampling_x = 2;
+               ycbcr_format.chroma_subsampling_y = 1;
+               input->useYCbCrInput( image_format, ycbcr_format, width, height );
+       }
+       return input;
+}
+
+// Make a copy of the given image (allocated using mlt_pool_alloc) suitable
+// to pass as pixel pointer to an MltInput (created using create_input
+// with the same parameters), and return that pointer.
+static uint8_t* make_input_copy( mlt_image_format format, uint8_t *image, int width, int height )
+{
+       int img_size = mlt_image_format_size( format, width, height, NULL );
+       uint8_t* img_copy = (uint8_t*) mlt_pool_alloc( img_size );
+       if ( format == mlt_image_yuv422 ) {
+               yuv422_to_yuv422p( image, img_copy, width, height );
+       } else {
+               memcpy( img_copy, image, img_size );
+       }
+       return img_copy;
+}
+
 static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, mlt_image_format output_format )
 {
        // Nothing to do!
@@ -127,114 +399,94 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo
        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 we're at the beginning of a series of Movit effects, store the input
+       // sent into the chain.
+       if ( output_format == mlt_image_glsl ) {
+               mlt_producer producer = mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) );
+               mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) );
+               MltInput *input = create_input( properties, *format, profile->width, profile->height, width, height );
+               GlslManager::set_input( producer, frame, input );
+               uint8_t *img_copy = make_input_copy( *format, *image, width, height );
+               GlslManager::set_input_pixel_pointer( producer, frame, img_copy );
 
-       if ( !chain || !input ) {
-               GlslManager::get_instance()->unlock_service( frame );
-               return 2;
+               *image = (uint8_t *) -1;
+               mlt_frame_set_image( frame, *image, 0, NULL );
        }
 
-       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.input", input, 0 );
-                                       producer.set( "movit.convert.width", width );
-                                       producer.set( "movit.convert.height", height );
-                                       producer.set( "movit.convert.format", output_format );
-                               }
-                       }
-               }
-               if ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) { 
-                       // TODO: Get the color space if available.
-                       input->useFlatInput( chain, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, width, height );
-                       input->set_pixel_data( *image );
-               }
-               else if ( *format == mlt_image_rgb24 ) {
-                       // TODO: Get the color space if available.
-                       input->useFlatInput( chain, FORMAT_RGB, width, height );
-                       input->set_pixel_data( *image );
-               }
-               else if ( *format == mlt_image_yuv420p ) {
-                       ImageFormat image_format;
-                       YCbCrFormat ycbcr_format;
-                       get_format_from_properties( properties, &image_format, &ycbcr_format );
-                       ycbcr_format.chroma_subsampling_x = ycbcr_format.chroma_subsampling_y = 2;
-                       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;
-                       get_format_from_properties( properties, &image_format, &ycbcr_format );
-                       ycbcr_format.chroma_subsampling_x = 2;
-                       ycbcr_format.chroma_subsampling_y = 1;
-                       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 we're at the _end_ of a series of Movit effects, render the chain.
+       if ( *format == mlt_image_glsl ) {
+               mlt_service leaf_service = (mlt_service) *image;
+
+               // Construct the chain unless we already have a good one.
+               finalize_movit_chain( leaf_service, frame );
+
+               // Set per-frame parameters now that we know which Effect instances to set them on.
+               GlslChain *chain = GlslManager::get_chain( leaf_service );
+               set_movit_parameters( chain, leaf_service, frame );
+
+               error = movit_render( chain->effect_chain, frame, format, output_format, width, height, image );
+
+               dispose_pixel_pointers( leaf_service, frame );
        }
 
-       if ( output_format != mlt_image_glsl ) {
+       // If we've been asked to render some frame directly to a texture (without any
+       // effects in-between), we create a new mini-chain to do so.
+       if ( *format != mlt_image_glsl && 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 );
+               } 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 ) ) );
+                       EffectChain *chain = (EffectChain*) producer.get_data( "movit.convert.chain" );
+                       MltInput *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 || !input || width != w || height != h || *format != f ) {
+                               chain = new EffectChain( width, height );
+                               input = create_input( properties, *format, width, height, width, height );
+                               chain->add_input( input );
+                               chain->add_effect( new Mlt::VerticalFlip() );
+                               ImageFormat movit_output_format;
+                               movit_output_format.color_space = COLORSPACE_sRGB;
+                               movit_output_format.gamma_curve = GAMMA_sRGB;
+                               chain->add_output(movit_output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED);
+                               chain->set_dither_bits(8);
+                               chain->finalize();
+                               producer.set( "movit.convert.chain", chain, 0, (mlt_destructor) delete_chain );
+                               producer.set( "movit.convert.input", input, 0, NULL );
+                               producer.set( "movit.convert.width", width );
+                               producer.set( "movit.convert.height", height );
+                               producer.set( "movit.convert.format", *format );
+                       }
 
-               if ( output_format == mlt_image_glsl_texture ) {
-                       error = glsl->render_frame_texture( service, frame, width, height, image );
-               }
-               else {
-                       error = glsl->render_frame_rgba( service, frame, width, height, image );
-                       if ( !error && output_format != mlt_image_rgb24a ) {
-                               *format = mlt_image_rgb24a;
-                               error = convert_on_cpu( frame, image, format, output_format );
+                       if ( *format == mlt_image_yuv422 ) {
+                               // We need to convert to planar, which make_input_copy() will do for us.
+                               uint8_t *planar = make_input_copy( *format, *image, width, height );
+                               input->set_pixel_data( planar );
+                               error = movit_render( chain, frame, format, output_format, width, height, image );
+                               mlt_pool_release( planar );
+                       } else {
+                               input->set_pixel_data( *image );
+                               error = movit_render( chain, frame, format, output_format, width, height, image );
                        }
                }
-               mlt_properties_set_int( properties, "format", output_format );
-               *format = output_format;
-       }
-       else {
-               mlt_properties_set_int( properties, "format", output_format );
-               *format = output_format;
        }
+
        GlslManager::get_instance()->unlock_service( frame );
 
+       mlt_properties_set_int( properties, "format", output_format );
+       *format = output_format;
+
        return error;
 }
 
index f35fc7f2f60ed84529f1092f17e8601688cabd8e..533673503316ef415f243fb70677f7e406b63ca7 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "filter_glsl_manager.h"
 #include <movit/padding_effect.h>
+#include "optional_effect.h"
 
 static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
@@ -76,32 +77,31 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
 
                mlt_log_debug( MLT_FILTER_SERVICE(filter), "%dx%d -> %dx%d\n", *width, *height, owidth, oheight);
 
+               mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
                GlslManager::get_instance()->lock_service( frame );
-               Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( 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;
-               }
+               mlt_properties_set_int( properties, "movit.parms.int.width", owidth );
+               mlt_properties_set_int( properties, "movit.parms.int.height", oheight );
+               mlt_properties_set_double( properties, "movit.parms.float.left", -left );
+               mlt_properties_set_double( properties, "movit.parms.float.top", -top );
+
+               bool disable = ( *width == owidth && *height == oheight );
+               mlt_properties_set_int( properties, "movit.disable", disable );
+
                GlslManager::get_instance()->unlock_service( frame );
        }
 
+        GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       Effect* effect = GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new OptionalEffect<PaddingEffect> );
+       assert(effect);
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       RGBATuple border_color( 0.0f, 0.0f, 0.0f, 1.0f );
+       bool ok = effect->set_vec4( "border_color", (float*) &border_color );
+       assert(ok);
        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( MLT_FILTER_SERVICE( 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;
index 8a33f4947508ef8183fcd35e1a2d2144d5751a00..bedb313331d6fb4dfa3790c32c7581b7a6db4597 100644 (file)
@@ -29,33 +29,29 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_int( "matrix_size",
-                       mlt_properties_anim_get_int( properties, "matrix_size", position, length ) );
-               ok |= effect->set_float( "cirlce_radius",
-                       mlt_properties_anim_get_double( properties, "circle_radius", position, length ) );
-               ok |= effect->set_float( "gaussian_radius",
-                       mlt_properties_anim_get_double( properties, "gaussian_radius", position, length ) );
-               ok |= effect->set_float( "correlation",
-                       mlt_properties_anim_get_double( properties, "correlation", position, length ) );
-               ok |= effect->set_float( "noise",
-                       mlt_properties_anim_get_double( properties, "noise", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       mlt_properties_set_int( properties, "movit.parms.int.matrix_size",
+               mlt_properties_anim_get_int( properties, "matrix_size", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.circle_radius",
+               mlt_properties_anim_get_double( properties, "circle_radius", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.gaussian_radius",
+               mlt_properties_anim_get_double( properties, "gaussian_radius", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.correlation",
+               mlt_properties_anim_get_double( properties, "correlation", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.noise",
+               mlt_properties_anim_get_double( properties, "noise", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new DeconvolutionSharpenEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new DeconvolutionSharpenEffect() );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index e6341f34bf6b23579e71c4c3378204b9e9629319..c04c2ce4d98f1d1ed1efc06164e983e72596bf04 100644 (file)
@@ -29,27 +29,23 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_float( "radius",
-                       mlt_properties_anim_get_double( properties, "radius", position, length ) );
-               ok |= effect->set_float( "blurred_mix_amount",
-                       mlt_properties_anim_get_double( properties, "mix", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       mlt_properties_set_double( properties, "movit.parms.float.radius",
+               mlt_properties_anim_get_double( properties, "radius", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.blurred_mix_amount",
+               mlt_properties_anim_get_double( properties, "mix", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new DiffusionEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new DiffusionEffect() );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 1d849c1b73d2b3bbe1bd1062d5bcb337c7c24a9f..ab9ea0c5e7372ac53a92ec2741367b4086569a5e 100644 (file)
@@ -28,30 +28,26 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
 {
        mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
        mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
        GlslManager::get_instance()->lock_service( frame );
-       Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_float( "radius",
-                       mlt_properties_anim_get_double( properties, "radius", position, length ) );
-               ok |= effect->set_float( "blurred_mix_amount",
-                       mlt_properties_anim_get_double( properties, "blur_mix", position, length ) );
-               ok |= effect->set_float( "highlight_cutoff",
-                       mlt_properties_anim_get_double( properties, "highlight_cutoff", position, length ) );
-               assert(ok);
-       }
+       mlt_properties_set_double( properties, "movit.parms.float.radius",
+               mlt_properties_anim_get_double( properties, "radius", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.blurred_mix_amount",
+               mlt_properties_anim_get_double( properties, "blur_mix", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.highlight_cutoff",
+               mlt_properties_anim_get_double( properties, "highlight_cutoff", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new GlowEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new GlowEffect() );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 015ab672bae941611b361bc48ce1ec09d0ef6c8e..de934d035aabde99c33b289e26299729255ee48d 100644 (file)
@@ -29,37 +29,37 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               RGBTriplet triplet(
-                       mlt_properties_anim_get_double( properties, "lift_r", position, length ),
-                       mlt_properties_anim_get_double( properties, "lift_g", position, length ),
-                       mlt_properties_anim_get_double( properties, "lift_b", position, length )
-               );
-               bool ok = effect->set_vec3( "lift", (float*) &triplet );
-               triplet.r = mlt_properties_anim_get_double( properties, "gamma_r", position, length );
-               triplet.g = mlt_properties_anim_get_double( properties, "gamma_g", position, length );
-               triplet.b = mlt_properties_anim_get_double( properties, "gamma_b", position, length );
-               ok |= effect->set_vec3( "gamma", (float*) &triplet );
-               triplet.r = mlt_properties_anim_get_double( properties, "gain_r", position, length );
-               triplet.g = mlt_properties_anim_get_double( properties, "gain_g", position, length );
-               triplet.b = mlt_properties_anim_get_double( properties, "gain_b", position, length );
-               ok |= effect->set_vec3( "gain", (float*) &triplet );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       mlt_properties_set_double( properties, "movit.parms.vec3.lift[0]",
+               mlt_properties_anim_get_double( properties, "lift_r", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.lift[1]",
+               mlt_properties_anim_get_double( properties, "lift_g", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.lift[2]",
+               mlt_properties_anim_get_double( properties, "lift_b", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gamma[0]",
+               mlt_properties_anim_get_double( properties, "gamma_r", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gamma[1]",
+               mlt_properties_anim_get_double( properties, "gamma_g", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gamma[2]",
+               mlt_properties_anim_get_double( properties, "gamma_b", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gain[0]",
+               mlt_properties_anim_get_double( properties, "gain_r", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gain[1]",
+               mlt_properties_anim_get_double( properties, "gain_g", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.vec3.gain[2]",
+               mlt_properties_anim_get_double( properties, "gain_b", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new LiftGammaGainEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new LiftGammaGainEffect );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 55fa637667f1badec97b5beac1881ede69d38b14..12d8d271bb58610e6922d46bdc2e97245db3b87b 100644 (file)
 #include "filter_glsl_manager.h"
 #include <movit/mirror_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 );
+       *format = mlt_image_glsl;
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new MirrorEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
+}
+
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame );
-               if ( !effect )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new MirrorEffect() );
-       }
+       mlt_frame_push_service( frame, filter );
+       mlt_frame_push_get_image( frame, get_image );
        return frame;
 }
 
index be80239d76f344182a71ba3aa3ec5215d3ff2361..5916c34e6f595d4ced4af8b5ee5c011f5bacfec8 100644 (file)
 #include <assert.h>
 
 #include "filter_glsl_manager.h"
-#include <movit/mix_effect.h>
+#include <movit/multiply_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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_float( "strength_first",
-                       mlt_properties_anim_get_double( properties, "opacity", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       double opacity = mlt_properties_anim_get_double( properties, "opacity", position, length );
+       mlt_properties_set_double( properties, "movit.parms.vec4.factor[0]", opacity );
+       mlt_properties_set_double( properties, "movit.parms.vec4.factor[1]", opacity );
+       mlt_properties_set_double( properties, "movit.parms.vec4.factor[2]", opacity );
+       mlt_properties_set_double( properties, "movit.parms.vec4.factor[3]", opacity );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new MultiplyEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame );
-               if ( !effect ) {
-                       effect = GlslManager::add_effect( MLT_FILTER_SERVICE( 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;
index 93e7b6ce19d07f92a0fd2fdfdc1cc038de4916a5..1b76339e1dcf076fdb329921f5c62878aed390fd 100644 (file)
 
 #include "filter_glsl_manager.h"
 #include <movit/resample_effect.h>
+#include "optional_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 );
@@ -60,30 +60,34 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        if ( iheight != oheight )
                mlt_properties_set_int( properties, "consumer_deinterlace", 1 );
 
+       GlslManager::get_instance()->lock_service( frame );
+       mlt_properties_set_int( filter_properties, "movit.parms.int.width", owidth );
+       mlt_properties_set_int( filter_properties, "movit.parms.int.height", oheight );
+
+       bool disable = ( iwidth == owidth && iheight == oheight );
+       mlt_properties_set_int( filter_properties, "movit.disable", disable );
+
+       *width = owidth;
+       *height = oheight;
+
+       GlslManager::get_instance()->unlock_service( frame );
+
        // 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( MLT_FILTER_SERVICE( 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;
+       int error = mlt_frame_get_image( frame, image, format, &iwidth, &iheight, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       Effect *effect = GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new OptionalEffect<ResampleEffect> );
+       // This needs to be something else than 0x0 at chain finalization time.
+       bool ok = effect->set_int("width", owidth);
+       ok |= effect->set_int("height", oheight);
+       assert( ok );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+        return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-               GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new ResampleEffect );
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index ef87c7e9c7a6f87b4396d36ef74c053d46298860..04953d9ced500c7071bd8f0c58c829d6d7521421 100644 (file)
@@ -26,6 +26,7 @@
 #include "filter_glsl_manager.h"
 #include <movit/init.h>
 #include <movit/padding_effect.h>
+#include "optional_effect.h"
 
 static float alignment_parse( char* align )
 {
@@ -156,16 +157,22 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        }
 
        if ( !error ) {
+               mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
                GlslManager::get_instance()->lock_service( frame );
-               Effect* effect = GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame );
-               if ( effect ) {
-                       bool ok = effect->set_int( "width", *width );
-                       ok |= effect->set_int( "height", *height );
-                       ok |= effect->set_float( "left", rect.x );
-                       ok |= effect->set_float( "top", rect.y );
-                       assert(ok);
-               }
+               mlt_properties_set_int( filter_properties, "movit.parms.int.width", *width );
+               mlt_properties_set_int( filter_properties, "movit.parms.int.height", *height );
+               mlt_properties_set_double( filter_properties, "movit.parms.float.left", rect.x );
+               mlt_properties_set_double( filter_properties, "movit.parms.float.top", rect.y );
+
+               bool disable = ( *width == owidth && *height == oheight );
+               mlt_properties_set_int( filter_properties, "movit.disable", disable );
+
                GlslManager::get_instance()->unlock_service( frame );
+
+               GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+               GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new OptionalEffect<PaddingEffect> );
+               *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+               return error;
        }
 
        return error;
@@ -173,8 +180,6 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-               GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new PaddingEffect );
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 04d1d0a05095df1e935201a65a3a79976140e988..d23a0503063b7908616901e43e9e47ddaed230dd 100644 (file)
@@ -29,25 +29,21 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_float( "saturation",
-                       mlt_properties_anim_get_double( properties, "saturation", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       mlt_properties_set_double( properties, "movit.parms.float.saturation",
+               mlt_properties_anim_get_double( properties, "saturation", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new SaturationEffect() );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new SaturationEffect() );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index 589931b60a319258902dc2dbd6c9c6a0f3c38573..bdcb8a28b7d8b811b592f8febf2c46246e2ee906 100644 (file)
@@ -29,27 +29,23 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               bool ok = effect->set_float( "radius",
-                       mlt_properties_anim_get_double( properties, "radius", position, length ) );
-               ok |= effect->set_float( "inner_radius",
-                       mlt_properties_anim_get_double( properties, "inner_radius", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       mlt_properties_set_double( properties, "movit.parms.float.radius",
+               mlt_properties_anim_get_double( properties, "radius", position, length ) );
+       mlt_properties_set_double( properties, "movit.parms.float.inner_radius",
+               mlt_properties_anim_get_double( properties, "inner_radius", position, length ) );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new VignetteEffect() );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+        return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new VignetteEffect() );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index fa04776148ee53f80a2791d0172489626c237fd7..71a325d51cb94f38968b4d80ad2d7d793fc818c0 100644 (file)
@@ -40,32 +40,32 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        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( MLT_FILTER_SERVICE( filter ), frame );
-       if ( effect ) {
-               mlt_position position = mlt_filter_get_position( filter, frame );
-               mlt_position length = mlt_filter_get_length2( filter, frame );
-               int color_int = mlt_properties_anim_get_int( properties, "neutral_color", position, length );
-               RGBTriplet color(
-                       srgb8_to_linear((color_int >> 24) & 0xff),
-                       srgb8_to_linear((color_int >> 16) & 0xff),
-                       srgb8_to_linear((color_int >> 8) & 0xff)
-               );
-               bool ok = effect->set_vec3( "neutral_color", (float*) &color );
-               ok |= effect->set_float( "output_color_temperature",
-                       mlt_properties_anim_get_double( properties, "color_temperature", position, length ) );
-               assert(ok);
-       }
+       mlt_position position = mlt_filter_get_position( filter, frame );
+       mlt_position length = mlt_filter_get_length2( filter, frame );
+       int color_int = mlt_properties_anim_get_int( properties, "neutral_color", position, length );
+       RGBTriplet color(
+               srgb8_to_linear((color_int >> 24) & 0xff),
+               srgb8_to_linear((color_int >> 16) & 0xff),
+               srgb8_to_linear((color_int >> 8) & 0xff)
+       );
+       mlt_properties_set_double( properties, "movit.parms.vec3.neutral_color[0]", color.r );
+       mlt_properties_set_double( properties, "movit.parms.vec3.neutral_color[1]", color.g );
+       mlt_properties_set_double( properties, "movit.parms.vec3.neutral_color[2]", color.b );
+       double output_color_temperature =
+               mlt_properties_anim_get_double( properties, "color_temperature", position, length );
+       mlt_properties_set_double( properties, "movit.parms.float.output_color_temperature",
+                output_color_temperature );
        GlslManager::get_instance()->unlock_service( frame );
        *format = mlt_image_glsl;
-       return mlt_frame_get_image( frame, image, format, width, height, writable );
+       int error = mlt_frame_get_image( frame, image, format, width, height, writable );
+       GlslManager::set_effect_input( MLT_FILTER_SERVICE( filter ), frame, (mlt_service) *image );
+       GlslManager::set_effect( MLT_FILTER_SERVICE( filter ), frame, new WhiteBalanceEffect );
+       *image = (uint8_t *) MLT_FILTER_SERVICE( filter );
+       return error;
 }
 
 static mlt_frame process( mlt_filter filter, mlt_frame frame )
 {
-       if ( !mlt_frame_is_test_card( frame ) ) {
-               if ( !GlslManager::get_effect( MLT_FILTER_SERVICE( filter ), frame ) )
-                       GlslManager::add_effect( MLT_FILTER_SERVICE( filter ), frame, new WhiteBalanceEffect );
-       }
        mlt_frame_push_service( frame, filter );
        mlt_frame_push_get_image( frame, get_image );
        return frame;
index f4b29022eb894f2508c24fff72ca99571458634c..d2755741c05168bfc2be77bab186920d504eb23c 100644 (file)
@@ -83,7 +83,7 @@ GammaCurve MltInput::get_gamma_curve() const
        return input->get_gamma_curve();
 }
 
-void MltInput::useFlatInput(EffectChain* chain, MovitPixelFormat pix_fmt, unsigned width, unsigned height)
+void MltInput::useFlatInput(MovitPixelFormat pix_fmt, unsigned width, unsigned height)
 {
        if (!input) {
                m_width = width;
@@ -92,28 +92,21 @@ void MltInput::useFlatInput(EffectChain* chain, MovitPixelFormat pix_fmt, unsign
                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)
+void MltInput::useYCbCrInput(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)
+void MltInput::useFBOInput(GLuint texture)
 {
        if (!input) {
                FBOInput* fboInput = new FBOInput(m_width, m_height);
index 2f5de231d85938b843ceb92c9d27cfde6c5c3810..ce9f61aede1b0017531583e6929786234e553923 100644 (file)
@@ -45,9 +45,9 @@ public:
        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 useFlatInput(MovitPixelFormat pix_fmt, unsigned width, unsigned height);
+       void useYCbCrInput(const ImageFormat& image_format, const YCbCrFormat& ycbcr_format, unsigned width, unsigned height);
+       void useFBOInput(GLuint texture);
        void set_pixel_data(const unsigned char* data);
 
 private:
diff --git a/src/modules/opengl/optional_effect.h b/src/modules/opengl/optional_effect.h
new file mode 100644 (file)
index 0000000..ec6ea27
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef OPTIONAL_EFFECT_H
+#define OPTIONAL_EFFECT_H
+
+#include <movit/effect.h>
+#include <movit/effect_chain.h>
+#include <assert.h>
+
+// A wrapper effect that, at rewrite time, can remove itself entirely from the loop.
+// It does so if "disable" is set to a nonzero value at finalization time.
+template<class T>
+class OptionalEffect : public T {
+public:
+       OptionalEffect() : disable(0) { this->register_int("disable", &disable); }
+       virtual std::string effect_type_id() const { return "OptionalEffect[" + T::effect_type_id() + "]"; }
+       virtual void rewrite_graph(EffectChain *graph, Node *self) {
+               if (disable) {
+                       assert(self->incoming_links.size() == 1);
+                       graph->replace_sender(self, self->incoming_links[0]);
+                       self->disabled = true;
+               } else {
+                       T::rewrite_graph(graph, self);
+               }
+       }
+
+private:
+       int disable;
+};
+
+#endif
index 1697d12e7f47e8d75024efe5a13b5b2f3576f1c5..4adc810e9dc7f83cc14ec9b09e138699d16a66f6 100644 (file)
 
 static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
 {
-       int error = 0;
+       int error;
 
        // 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 );
+       mlt_service service = MLT_TRANSITION_SERVICE( transition );
+       mlt_service_lock( service );
 
        // 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
        mlt_position position = mlt_transition_get_position( transition, a_frame );
        mlt_position length = mlt_transition_get_length( transition );
@@ -69,71 +54,30 @@ static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *form
                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();
-       if ( output_format == mlt_image_glsl_texture ) {
-               error = glsl->render_frame_texture( service, a_frame, *width, *height, image );
-               *format = output_format;
-       }
-       else {
-               error = glsl->render_frame_rgba( service, a_frame, *width, *height, image );
-               *format = mlt_image_rgb24a;
-       }
-       mlt_service_unlock( service );
+       // Set the Movit parameters.
+        mlt_properties_set_double( properties, "movit.parms.float.strength_first", reverse ? mix : inverse );
+        mlt_properties_set_double( properties, "movit.parms.float.strength_second", reverse ? inverse : mix );
+
+       uint8_t *a_image, *b_image;
+
+       // Get the two images.
+       *format = mlt_image_glsl;
+       error = mlt_frame_get_image( a_frame, &a_image, format, width, height, writable );
+       error = mlt_frame_get_image( b_frame, &b_image, format, width, height, writable );
 
+       GlslManager::set_effect_input( service, a_frame, (mlt_service) a_image );
+       GlslManager::set_effect_secondary_input( service, a_frame, (mlt_service) b_image, b_frame );
+       GlslManager::set_effect( service, a_frame, new MixEffect() );
+       *image = (uint8_t *) service;
+
+       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;
index 4492ce6b035a759ba6303ab0f344264c2768952a..2b77c9c617f71ccf362c6caa8b84b68cb4e6fce7 100644 (file)
 #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;
+       int error;
 
        // 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;
-       }
+       uint8_t *a_image, *b_image;
 
-       // 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] );
+       // Get the two images.
+       *format = mlt_image_glsl;
+       error = mlt_frame_get_image( a_frame, &a_image, format, width, height, writable );
+       error = mlt_frame_get_image( b_frame, &b_image, format, width, height, writable );
 
-       // Set resolution to that of the a_frame
-       *width = mlt_properties_get_int( a_props, "width" );
-       *height = mlt_properties_get_int( a_props, "height" );
+       GlslManager::set_effect_input( service, a_frame, (mlt_service) a_image );
+       GlslManager::set_effect_secondary_input( service, a_frame, (mlt_service) b_image, b_frame );
+       GlslManager::set_effect( service, a_frame, new OverlayEffect );
+       *image = (uint8_t *) service;
 
-       // Setup rendering to an FBO
-       GlslManager* glsl = GlslManager::get_instance();
-       if ( output_format == mlt_image_glsl_texture ) {
-               error = glsl->render_frame_texture( service, a_frame, *width, *height, image );
-               *format = output_format;
-       }
-       else {
-               error = glsl->render_frame_rgba( service, a_frame, *width, *height, image );
-               *format = mlt_image_rgb24a;
-       }
        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 );
-
-               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;