Sequencer: support for masked color balance
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 11 Aug 2012 14:37:58 +0000 (14:37 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 11 Aug 2012 14:37:58 +0000 (14:37 +0000)
This implements option which could be used to color balance only
specified area. Currently done by adding Mask input to Adjustment
effect. Affects on color balance and multiply settings.

Supporting masked saturation control is in the list, not supported
in this commit.

Also show value slider in the right of color wheel.

release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesrna/intern/rna_sequencer.c

index 77789496a15426ccc74749e7190ae64d2c4c5a63..7b0715f4b411798117f6d66e2fa7e0c235ccd21e 100644 (file)
@@ -423,18 +423,24 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
         return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
-                              'MULTICAM'}
+                              'MULTICAM', 'ADJUSTMENT'}
 
     def draw(self, context):
         layout = self.layout
 
+        sequencer = context.scene.sequence_editor
         strip = act_strip(context)
+
         if strip.input_count > 0:
             col = layout.column()
             col.prop(strip, "input_1")
             if strip.input_count > 1:
                 col.prop(strip, "input_2")
 
+        if strip.is_supports_mask:
+            col = layout.column()
+            col.prop_search(strip, "input_mask", sequencer, "sequences")
+
         if strip.type == 'COLOR':
             layout.prop(strip, "color")
 
@@ -765,21 +771,21 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
         if strip.use_color_balance and strip.color_balance:  # TODO - need to add this somehow
             col = layout.column()
             col.label(text="Lift:")
-            col.template_color_wheel(strip.color_balance, "lift", value_slider=False, cubic=True)
+            col.template_color_wheel(strip.color_balance, "lift", value_slider=True, cubic=True)
             row = col.row()
             row.prop(strip.color_balance, "lift", text="")
             row.prop(strip.color_balance, "invert_lift", text="Inverse")
 
             col = layout.column()
             col.label(text="Gamma:")
-            col.template_color_wheel(strip.color_balance, "gamma", value_slider=False, lock_luminosity=True, cubic=True)
+            col.template_color_wheel(strip.color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
             row = col.row()
             row.prop(strip.color_balance, "gamma", text="")
             row.prop(strip.color_balance, "invert_gamma", text="Inverse")
 
             col = layout.column()
             col.label(text="Gain:")
-            col.template_color_wheel(strip.color_balance, "gain", value_slider=False, lock_luminosity=True, cubic=True)
+            col.template_color_wheel(strip.color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
             row = col.row()
             row.prop(strip.color_balance, "gain", text="")
             row.prop(strip.color_balance, "invert_gain", text="Inverse")
index 78e65fe3ea65e43e76781b526593399be678a266..fee1db99c5ca99b2d60aadffd05ad2a2ed5f84ce 100644 (file)
@@ -110,7 +110,8 @@ enum {
 };
 
 struct SeqEffectHandle {
-       int multithreaded;
+       short multithreaded;
+       short supports_mask;
 
        /* constructors & destructor */
        /* init is _only_ called on first creation */
@@ -150,11 +151,12 @@ struct SeqEffectHandle {
        struct ImBuf * (*execute)(SeqRenderData context, struct Sequence *seq, float cfra, float facf0, float facf1,
                                  struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3);
 
-       struct ImBuf * (*init_execution)(SeqRenderData context, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3);
+       struct ImBuf * (*init_execution)(SeqRenderData context, struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+                                        struct ImBuf *ibuf3);
 
        void (*execute_slice)(SeqRenderData context, struct Sequence *seq, float cfra, float facf0, float facf1,
                              struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3,
-                              int start_line, int total_lines, struct ImBuf *out);
+                             int start_line, int total_lines, struct ImBuf *out);
 };
 
 /* ********************* prototypes *************** */
@@ -253,6 +255,7 @@ void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence
 /* extern */
 struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq);
 int BKE_sequence_effect_get_num_inputs(int seq_type);
+int BKE_sequence_effect_get_supports_mask(int seq_type);
 
 /* **********************************************************************
  * Sequencer editing functions
@@ -284,6 +287,7 @@ void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, in
 struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag);
 int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
 
+int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
 void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq);
 
 void BKE_sequencer_update_sound_bounds_all(struct Scene *scene);
index 911b6b00b98f928c9f9a61d11af6d0361db0c096..2380596c6adfd41e51fc1c64c3d4c4921976476c 100644 (file)
@@ -2840,6 +2840,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
        int sequence_type = seq_type;
 
        rval.multithreaded = FALSE;
+       rval.supports_mask = FALSE;
        rval.init = init_noop;
        rval.num_inputs = num_inputs_default;
        rval.load = load_noop;
@@ -2945,6 +2946,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
                        rval.execute = do_multicam;
                        break;
                case SEQ_TYPE_ADJUSTMENT:
+                       rval.supports_mask = TRUE;
                        rval.num_inputs = num_inputs_adjustment;
                        rval.early_out = early_out_adjustment;
                        rval.execute = do_adjustment;
@@ -2956,7 +2958,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
 
 struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
 {
-       struct SeqEffectHandle rval = {FALSE, NULL};
+       struct SeqEffectHandle rval = {FALSE, FALSE, NULL};
 
        if (seq->type & SEQ_TYPE_EFFECT) {
                rval = get_sequence_effect_impl(seq->type);
@@ -2971,7 +2973,7 @@ struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
 
 struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq)
 {
-       struct SeqEffectHandle rval = {FALSE, NULL};
+       struct SeqEffectHandle rval = {FALSE, FALSE, NULL};
 
        if (seq->blend_mode != 0) {
                rval = get_sequence_effect_impl(seq->blend_mode);
@@ -2994,3 +2996,10 @@ int BKE_sequence_effect_get_num_inputs(int seq_type)
        }
        return 0;
 }
+
+int BKE_sequence_effect_get_supports_mask(int seq_type)
+{
+       struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
+
+       return rval.supports_mask;
+}
index 4f1b324bc28bfba852b8799665686f3f5de42ad4..920588d9f47607498595b7bc14f45d78a29f53c9 100644 (file)
@@ -1426,12 +1426,13 @@ static void make_cb_table_float(float lift, float gain, float gamma,
        }
 }
 
-static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, int width, int height, float mul)
+static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
 {
        unsigned char cb_tab[3][256];
        int c;
        unsigned char *p = rect;
        unsigned char *e = p + width * 4 * height;
+       unsigned char *m = mask_rect;
 
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
@@ -1440,20 +1441,32 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, int widt
        }
 
        while (p < e) {
-               p[0] = cb_tab[0][p[0]];
-               p[1] = cb_tab[1][p[1]];
-               p[2] = cb_tab[2][p[2]];
+               if (m) {
+                       float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
+
+                       p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
+                       p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
+                       p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
+
+                       m += 4;
+               }
+               else {
+                       p[0] = cb_tab[0][p[0]];
+                       p[1] = cb_tab[1][p[1]];
+                       p[2] = cb_tab[2][p[2]];
+               }
                
                p += 4;
        }
 }
 
-static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *rect_float, int width, int height, float mul)
+static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
 {
        float cb_tab[4][256];
        int c, i;
        unsigned char *p = rect;
        unsigned char *e = p + width * 4 * height;
+       unsigned char *m = mask_rect;
        float *o;
        StripColorBalance cb;
 
@@ -1470,27 +1483,48 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *
        }
 
        while (p < e) {
-               o[0] = cb_tab[0][p[0]];
-               o[1] = cb_tab[1][p[1]];
-               o[2] = cb_tab[2][p[2]];
+               if (m) {
+                       float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
+
+                       p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
+                       p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
+                       p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
+
+                       m += 4;
+               }
+               else {
+                       o[0] = cb_tab[0][p[0]];
+                       o[1] = cb_tab[1][p[1]];
+                       o[2] = cb_tab[2][p[2]];
+               }
+
                o[3] = cb_tab[3][p[3]];
 
                p += 4; o += 4;
        }
 }
 
-static void color_balance_float_float(Sequence *seq, float *rect_float, int width, int height, float mul)
+static void color_balance_float_float(Sequence *seq, float *rect_float, float *mask_rect_float, int width, int height, float mul)
 {
        float *p = rect_float;
        float *e = rect_float + width * 4 * height;
+       float *m = mask_rect_float;
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
        while (p < e) {
                int c;
                for (c = 0; c < 3; c++) {
-                       p[c] = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+                       float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+
+                       if (m)
+                               p[c] = p[c] * (1.0f - m[c]) + t * m[c];
+                       else
+                               p[c] = t;
                }
+
                p += 4;
+               if (m)
+                       m += 4;
        }
 }
 
@@ -1498,6 +1532,7 @@ typedef struct ColorBalanceInitData {
        Sequence *seq;
        ImBuf *ibuf;
        float mul;
+       ImBuf *mask;
 } ColorBalanceInitData;
 
 typedef struct ColorBalanceThread {
@@ -1506,8 +1541,8 @@ typedef struct ColorBalanceThread {
 
        int width, height;
 
-       unsigned char *rect;
-       float *rect_float;
+       unsigned char *rect, *mask_rect;
+       float *rect_float, *mask_rect_float;
 } ColorBalanceThread;
 
 static void color_balance_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -1515,6 +1550,7 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
        ColorBalanceThread *handle = (ColorBalanceThread *) handle_v;
        ColorBalanceInitData *init_data = (ColorBalanceInitData *) init_data_v;
        ImBuf *ibuf = init_data->ibuf;
+       ImBuf *mask = init_data->mask;
 
        int offset = 4 * start_line * ibuf->x;
 
@@ -1530,6 +1566,18 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
 
        if (ibuf->rect_float)
                handle->rect_float = ibuf->rect_float + offset;
+
+       if (mask) {
+               if (mask->rect)
+                       handle->mask_rect = (unsigned char *) mask->rect + offset;
+
+               if (mask->rect_float)
+                       handle->mask_rect_float = mask->rect_float + offset;
+       }
+       else {
+               handle->mask_rect = NULL;
+               handle->mask_rect_float = NULL;
+       }
 }
 
 static void *color_balance_do_thread(void *thread_data_v)
@@ -1538,53 +1586,60 @@ static void *color_balance_do_thread(void *thread_data_v)
        Sequence *seq = thread_data->seq;
        int width = thread_data->width, height = thread_data->height;
        unsigned char *rect = thread_data->rect;
+       unsigned char *mask_rect = thread_data->mask_rect;
        float *rect_float = thread_data->rect_float;
+       float *mask_rect_float = thread_data->mask_rect_float;
        float mul = thread_data->mul;
 
        if (rect_float) {
-               color_balance_float_float(seq, rect_float, width, height, mul);
+               color_balance_float_float(seq, rect_float, mask_rect_float, width, height, mul);
        }
        else if (seq->flag & SEQ_MAKE_FLOAT) {
-               color_balance_byte_float(seq, rect, rect_float, width, height, mul);
+               color_balance_byte_float(seq, rect, rect_float, mask_rect, width, height, mul);
        }
        else {
-               color_balance_byte_byte(seq, rect, width, height, mul);
+               color_balance_byte_byte(seq, rect, mask_rect, width, height, mul);
        }
 
        return NULL;
 }
 
-static void color_balance(Sequence *seq, ImBuf *ibuf, float mul)
+static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra)
 {
+       ColorBalanceInitData init_data;
+
        if (!ibuf->rect_float && seq->flag & SEQ_MAKE_FLOAT)
                imb_addrectfloatImBuf(ibuf);
 
-       if (BLI_thread_is_main()) {
-               /* color balance could have been called from prefetching job which
-                * is already multithreaded, so doing threading here makes no sense
-                */
-               ColorBalanceInitData init_data;
-
-               init_data.seq = seq;
-               init_data.ibuf = ibuf;
-               init_data.mul = mul;
-
-               IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
-                                        color_balance_init_handle, color_balance_do_thread);
+       init_data.seq = seq;
+       init_data.ibuf = ibuf;
+       init_data.mul = mul;
+       init_data.mask = NULL;
+
+       if (seq->mask_sequence) {
+               if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) {
+                       ImBuf *mask = seq_render_strip(context, seq->mask_sequence, cfra);
+
+                       if (mask) {
+                               if (ibuf->rect_float) {
+                                       if (!mask->rect_float)
+                                               IMB_float_from_rect(mask);
+                               }
+                               else {
+                                       if (!mask->rect)
+                                               IMB_rect_from_float(mask);
+                               }
 
+                               init_data.mask = mask;
+                       }
+               }
        }
-       else {
-               ColorBalanceThread handle;
 
-               handle.seq = seq;
-               handle.mul = mul;
-               handle.width = ibuf->x;
-               handle.height = ibuf->y;
-               handle.rect = (unsigned char *)ibuf->rect;
-               handle.rect_float = ibuf->rect_float;
+       IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
+                                 color_balance_init_handle, color_balance_do_thread);
 
-               color_balance_do_thread(&handle);
-       }
+       if (init_data.mask)
+               IMB_freeImBuf(init_data.mask);
 }
 
 /*
@@ -1632,7 +1687,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
        return FALSE;
 }
 
-static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float UNUSED(cfra), ImBuf *ibuf,
+static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, ImBuf *ibuf,
                                int is_proxy_image, int is_preprocessed)
 {
        float mul;
@@ -1727,7 +1782,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float UNUSE
        }
 
        if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
-               color_balance(seq, ibuf, mul);
+               color_balance(context, seq, ibuf, mul, cfra);
                mul = 1.0;
        }
 
@@ -2784,11 +2839,34 @@ static void free_anim_seq(Sequence *seq)
        }
 }
 
+/* check whether sequence cur depends on seq */
+int BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
+{
+       /* sequences are not intersecting in time, assume no dependency exists between them */
+       if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp)
+               return FALSE;
+
+       /* checking sequence is below reference one, not dependent on it */
+       if (cur->machine < seq->machine)
+               return FALSE;
+
+       /* sequence is not blending with lower machines, no dependency here occurs
+        * check for non-effects only since effect could use lower machines as input
+        */
+       if ((cur->type & SEQ_TYPE_EFFECT) == 0 &&
+                   ((cur->blend_mode == SEQ_BLEND_REPLACE) ||
+                (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f)))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
 {
        Editing *ed = scene->ed;
        Sequence *cur;
-       int left = seq->startdisp, right = seq->enddisp;
 
        /* invalidate cache for current sequence */
        BKE_sequencer_cache_cleanup_sequence(seq);
@@ -2796,27 +2874,11 @@ void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
        /* invalidate cache for all dependent sequences */
        SEQ_BEGIN (ed, cur)
        {
-               int cur_left = cur->startdisp, cur_right = cur->enddisp;
-
                if (cur == seq)
                        continue;
 
-               /* sequence is outside of changed one, shouldn't be invalidated */
-               if (cur_right < left || cur_left > right)
-                       continue;
-
-               /* sequence is below changed one, not dependent on it */
-               if (cur->machine < seq->machine)
-                       continue;
-
-               /* sequence is not blending with lower machines, no need to invalidate */
-               if ((cur->blend_mode == SEQ_BLEND_REPLACE) ||
-                   (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f))
-               {
-                       continue;
-               }
-
-               BKE_sequencer_cache_cleanup_sequence(cur);
+               if (BKE_sequence_check_depend(seq, cur))
+                       BKE_sequencer_cache_cleanup_sequence(cur);
        }
        SEQ_END
 }
index 1f3662e62cdb0e0340f2760f8d4336fc877c6532..c235034bccbe6dd45e48e39ea449f365396c89fd 100644 (file)
@@ -4972,6 +4972,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        seq->seq1= newdataadr(fd, seq->seq1);
                        seq->seq2= newdataadr(fd, seq->seq2);
                        seq->seq3= newdataadr(fd, seq->seq3);
+                       seq->mask_sequence= newdataadr(fd, seq->mask_sequence);
                        /* a patch: after introduction of effects with 3 input strips */
                        if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
                        
index 161c448476d176e25019932676e0438196a25885..9731854d68c376c81864e93bd88a5edf8c0e2d66 100644 (file)
@@ -140,6 +140,9 @@ typedef struct Sequence {
        /* pointers for effects: */
        struct Sequence *seq1, *seq2, *seq3;
 
+       /* maks input for effects */
+       struct Sequence *mask_sequence;
+
        ListBase seqbase;       /* list of strips for metastrips */
 
        struct bSound *sound;   /* the linked "bSound" object */
index 8c0c87e5696a5e4ed94062799a7e7c62b67a9d95..06742f55774b3da802c788cac455b1cdbd1d9378 100644 (file)
@@ -55,6 +55,7 @@ typedef struct EffectInfo {
        const char *ui_desc;
        void (*func)(StructRNA *);
        int inputs;
+       int supports_mask;
 } EffectInfo;
 
 #ifdef RNA_RUNTIME
@@ -590,6 +591,13 @@ static int rna_Sequence_input_count_get(PointerRNA *ptr)
        return BKE_sequence_effect_get_num_inputs(seq->type);
 }
 
+static int rna_Sequence_supports_mask_get(PointerRNA *ptr)
+{
+       Sequence *seq = (Sequence *)(ptr->data);
+
+       return BKE_sequence_effect_get_supports_mask(seq->type);
+}
+
 #if 0
 static void rna_SoundSequence_filename_set(PointerRNA *ptr, const char *value)
 {
@@ -616,6 +624,20 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p
        }
 }
 
+static int rna_Sequence_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
+{
+       Sequence *seq = (Sequence *) ptr->data;
+       Sequence *cur = (Sequence *) value.data;
+
+       if (seq == cur)
+               return FALSE;
+
+       if (BKE_sequence_check_depend(seq, cur))
+               return FALSE;
+
+       return TRUE;
+}
+
 static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
 {
        Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
@@ -1412,7 +1434,7 @@ static void rna_def_input(StructRNA *srna)
        RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 }
 
-static void rna_def_effect_inputs(StructRNA *srna, int count)
+static void rna_def_effect_inputs(StructRNA *srna, int count, int supports_mask)
 {
        PropertyRNA *prop;
 
@@ -1420,6 +1442,10 @@ static void rna_def_effect_inputs(StructRNA *srna, int count)
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_int_funcs(prop, "rna_Sequence_input_count_get", NULL, NULL);
 
+       prop = RNA_def_property(srna, "is_supports_mask", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_int_funcs(prop, "rna_Sequence_supports_mask_get", NULL, NULL);
+
        if (count >= 1) {
                prop = RNA_def_property(srna, "input_1",  PROP_POINTER, PROP_NONE);
                RNA_def_property_pointer_sdna(prop, NULL, "seq1");
@@ -1442,6 +1468,15 @@ static void rna_def_effect_inputs(StructRNA *srna, int count)
                RNA_def_property_ui_text(prop, "Input 3", "Third input for the effect strip");
        }
        */
+
+       if (supports_mask) {
+               prop = RNA_def_property(srna, "input_mask",  PROP_POINTER, PROP_NONE);
+               RNA_def_property_pointer_sdna(prop, NULL, "mask_sequence");
+               RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Sequence_otherSequence_poll");
+               RNA_def_property_flag(prop, PROP_EDITABLE);
+               RNA_def_property_ui_text(prop, "Mask", "Mask input for the effect strip");
+               RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+       }
 }
 
 static void rna_def_image(BlenderRNA *brna)
@@ -1884,50 +1919,50 @@ static void rna_def_speed_control(StructRNA *srna)
 static EffectInfo def_effects[] = {
        {"AddSequence", "Add Sequence",
         "Add Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"AdjustmentSequence", "Adjustment Layer Sequence",
         "Sequence strip to perform filter adjustments to layers below",
-        rna_def_input, 0},
+        rna_def_input, 0, TRUE},
        {"AlphaOverSequence", "Alpha Over Sequence",
         "Alpha Over Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"AlphaUnderSequence", "Alpha Under Sequence",
         "Alpha Under Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"ColorSequence", "Color Sequence",
         "Sequence strip creating an image filled with a single color",
-        rna_def_solid_color, 0},
+        rna_def_solid_color, 0, FALSE},
        {"CrossSequence", "Cross Sequence",
         "Cross Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"GammaCrossSequence", "Gamma Cross Sequence",
         "Gamma Cross Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"GlowSequence", "Glow Sequence",
         "Sequence strip creating a glow effect",
-        rna_def_glow, 1},
+        rna_def_glow, 1, FALSE},
        {"MulticamSequence", "Multicam Select Sequence",
         "Sequence strip to perform multicam editing",
-        rna_def_multicam, 0},
+        rna_def_multicam, 0, FALSE},
        {"MultiplySequence", "Multiply Sequence",
         "Multiply Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"OverDropSequence", "Over Drop Sequence",
         "Over Drop Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"SpeedControlSequence", "SpeedControl Sequence",
         "Sequence strip to control the speed of other strips",
-        rna_def_speed_control, 1},
+        rna_def_speed_control, 1, FALSE},
        {"SubtractSequence", "Subtract Sequence",
         "Subtract Sequence",
-        NULL, 2},
+        NULL, 2, FALSE},
        {"TransformSequence", "Transform Sequence",
         "Sequence strip applying affine transformations to other strips",
-        rna_def_transform, 1},
+        rna_def_transform, 1, FALSE},
        {"WipeSequence", "Wipe Sequence",
         "Sequence strip creating a wipe transition",
-        rna_def_wipe, 1},
-       {"", "", "", NULL, 0}
+        rna_def_wipe, 1, FALSE},
+       {"", "", "", NULL, 0, FALSE}
 };
 
 static void rna_def_effects(BlenderRNA *brna)
@@ -1940,7 +1975,7 @@ static void rna_def_effects(BlenderRNA *brna)
                RNA_def_struct_ui_text(srna, effect->ui_name, effect->ui_desc);
                RNA_def_struct_sdna(srna, "Sequence");
 
-               rna_def_effect_inputs(srna, effect->inputs);
+               rna_def_effect_inputs(srna, effect->inputs, effect->supports_mask);
 
                if (effect->func)
                        effect->func(srna);