[Bf-committers] External effects for VSE and or compositor nodes

Gaspar Fernández blakeyed at totaki.com
Wed Mar 15 02:21:48 CET 2017

Hi Piotr,

I'll try to be brief (but I'll paste you the patch). My effect is named 
SEQ_TYPE_CUSTOMEFFECT. The effect is really silly, I just wanted to know 
if I could put a new effect into Blender. I also could send you a patch 
trying to insert a filter with Python (but it's really slow). It's only 
for VSE, I want to look at the compositor code too, but I will do it 
another weekend.

In source/blender/makesdna/DNA_sequence_types.h
   * Add the effect (SEQ_TYPE_CUSTOMEFFECT) to the enum and inc 
   * Add properties struct:
typedef struct CustomEffectVars {
float property;
} CustomEffectVars;

In source/blender/editors/space_sequencer/sequencer_edit.c:
   * Add the effect to sequencer_prop_effect_types[]:
{SEQ_TYPE_CUSTOMEFFECT, "CUSTOMEFFECT", 0, "Custom Effect", "Create a 
strip with customized effect" },

In source/blender/makesrna/intern/rna_sequencer_api.c:
   * Add the effect into RNA_api_sequences() / struct EnumPropertyItem 
seq_effect_items[] :
{SEQ_TYPE_CUSTOMEFFECT, "CUSTOM_EFFECT", 0, "Custom Effect", "" },
   * Add the effect into rna_def_sequence() / EnumPropertyItem 
seq_type_items[] :
{SEQ_TYPE_CUSTOMEFFECT, "CUSTOM_EFFECT", 0, "Custom Effect", "" },

   * Add the effect into EffectInfo def_effects[]:
{"CustomEffectSequence", "Custom Effect Sequence", "Sequence strip 
creating custom effects",
      rna_def_custom_effect, 1},
   * Add function: rna_def_custom_effect():

static void rna_def_custom_effect(StructRNA *srna)
     PropertyRNA *prop;

     RNA_def_struct_sdna_from(srna, "CustomEffectVars", "effectdata");
     prop = RNA_def_property(srna, "property", PROP_FLOAT, PROP_UNSIGNED);
     RNA_def_property_ui_text(prop, "One property", "One float prop for 
     RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
     RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, 

    * Add effect to rna_Sequence_refine() / switch:
return &RNA_CustomEffectSequence;

In source/blender/makesrna/RNA_access.h:
    * Add
         extern StructRNA RNA_CustomEffectSequence;

In release/scripts/startup/bl_ui/space_sequencer.py
   * Add the effect strip add into class SEQUENCER_MT_add_effect():
         layout.operator("sequencer.effect_strip_add", text="Custom 
Effect").type = 'CUSTOM_EFFECT'
   * Add our effect properties in CLASS_PT_EFFECT (fragment):
          col = layout.column(align=True)
if strip.type == 'SPEED':
             col.prop(strip, "multiply_speed")
elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 
             col.prop(strip, "use_default_fade", "Default fade")
if not strip.use_default_fade:
                 col.prop(strip, "effect_fader", text="Effect fader")
elif strip.type == 'GAUSSIAN_BLUR':
             col.prop(strip, "size_x")
             col.prop(strip, "size_y")
elif strip.type == 'CUSTOM_EFFECT':
             col.prop(strip, 'property')

In source/blender/editors/space_sequencer/sequencer_draw.c:
    * Add the effect to the switch: (fragment here)
             UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);

/* slightly offset hue to distinguish different effects */
if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04);
else if (seq->type == SEQ_TYPE_CUSTOMEFFECT) 
  rgb_byte_set_hue_float_offset(col, 0.52);


In source/blender/blenloader/intern/writefile.c:
    * Add effect write properties to file (fragment, find the line where 
effects are written to the file):
                             case SEQ_TYPE_TRANSFORM:
                                 writestruct(wd, DATA, TransformVars, 1, 
                                 writestruct(wd, DATA, GaussianBlurVars, 
1, seq->effectdata);
                                 writestruct(wd, DATA, CustomEffectVars, 
1, seq->effectdata);
                                 writestruct(wd, DATA, TextVars, 1, 

In source/blender/blenkernel/intern/seqeffects.c:
    * Define effect callbacks in get_sequence_effect_impl():
             rval.init = init_custom_effect_effect;
             rval.num_inputs = num_inputs_custom_effect;
<http://www.opengroup.org/onlinepubs/009695399/functions/free.html> = 
             rval.copy = copy_custom_effect_effect;
             rval.early_out = early_out_custom_effect;
             rval.execute = do_custom_effect_effect;

    * Add effect code:
/*********************** Custom Effect *************************/
static void init_custom_effect_effect(Sequence *seq)
if (seq->effectdata)

     seq->effectdata = MEM_callocN(sizeof(CustomEffectVars), 

static int num_inputs_custom_effect(void)
return 1;

static void free_custom_effect_effect(Sequence *seq)
if (seq->effectdata)

     seq->effectdata = NULL;

static void copy_custom_effect_effect(Sequence *dst, Sequence *src)
     dst->effectdata = MEM_dupallocN(src->effectdata);

static int early_out_custom_effect(Sequence *seq, float UNUSED(facf0), 
float UNUSED(facf1))

/* source/blender/blenkernel/BKE_sequencer.h */
/* #define EARLY_NO_INPUT      -1 */
/* #define EARLY_DO_EFFECT     0 */
/* #define EARLY_USE_INPUT_1   1 */
/* #define EARLY_USE_INPUT_2   2 */

     CustomEffectVars *UNUSED(data) = seq->effectdata;
/* I will always do my effect */
/* if (data->property == 0) { */
/*  return EARLY_USE_INPUT_1; */
/* } */

// NUESTRO EFECTO !!!!!!!!!!!!!
static ImBuf *do_custom_effect_effect(const SeqRenderData *context, 
Sequence *seq, float UNUSED(cfra), float UNUSED(facf0), float UNUSED(facf1),
                                      ImBuf *ibuf1, ImBuf *ibuf2, ImBuf 
     ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);

     CustomEffectVars *cv = (CustomEffectVars *)seq->effectdata;

unsigned char *rect, *orig;
int x= context->rectx;
int y= context->recty;

if (out->rect) {
         orig = (unsigned char *)ibuf1->rect;
         rect = (unsigned char *)out->rect;
float prop = cv->property;
while (y--) {
             x = context->rectx;
while (x--) {
                 rect[0] = (orig[0]+ prop*orig[1])/(1+prop);
                 rect[1] = (orig[1]+ prop*orig[2])/(1+prop);
                 rect[2] = (orig[2]+ prop*orig[1])/(1+prop);
                 rect[3] = 220;
                 rect += 4;
                 orig += 4;
else if (out->rect_float) {
         orig = (unsigned char *)ibuf1->rect_float;
         rect = (unsigned char *)out->rect_float;
while (y--) {
             x = context->rectx;
while (x--) {
                 rect[0] = (orig[0]+ prop*orig[1])/(1+prop);
                 rect[1] = (orig[1]+ prop*orig[2])/(1+prop);
                 rect[2] = (orig[2]+ prop*orig[1])/(1+prop);
                 rect[3] = 0.5;
                 rect += 4;
                 orig += 4;

return out;

You can do lots of improvements, that was just a test to change image 
channels (play with the property). I didn't make it multithreaded, it 
would be interesting and easy, Blender API makes it so easy with 
rva.multithreaded and rva.execute_slice callback. I also give you the 
git patch for your experiments:

The patch is here: 
(the message was too big)

Best Regards,

Gaspar Fernández

El 13/03/17 a las 12:58, Piotr Arlukowicz escribió:
> Hi Gaspar,
> can you possibly share some knowledge how you did your patches or how were
> you able to create even the simplest effect? I'm looking for an entry point
> to VSE logic code but I'm still walking in the fog...
> cheers
> pio
> ​Piotr
> ​ Arlukowicz, BFCT​
> ​*YT: /user/piotao?feature=guide*
>   *FB:* */polskikursblendera* *TW:*
> */piotao*
> *Blender Network:* *https://www.blendernetwork.org/piotr-arlukowicz
> <https://www.blendernetwork.org/piotr-arlukowicz>*
> *Polski Kurs Blendera:* http://polskikursblendera.pl
> 2017-03-13 5:00 GMT+01:00 Gaspar Fernández <blakeyed at totaki.com>:
>> Hi all!
>> There are only a few effects in Blender for VSE or compositor. I've been
>> thinking about that for years. Even I found, in the past Blender used a
>> C api to allow external effect plugins
>> (https://wiki.blender.org/index.php/Doc:2.4/Manual/
>> Sequencer/Effects/Plugins).
>> And don't know why this feature isn't supported now.
>> Looking for a solution I tried to make my Blender build run image
>> filters via Python API but it's very slow (2 frames/sec for a very very
>> easy effect, inverting red and blue channels and alpha to 50%), also I
>> did not tested using a Python lib so Python will be just calling my C
>> lib which does the effect. But I think it may be better making them
>> directly in C or C++, I've tested doing the same simple effect in C and
>> it's realtime.
>> I also thought about using a pluggable library for doing this (just
>> effects on images or videos), like MLT, where we can add a lot of
>> effects and image generators (another very very interesting feature for
>> me). It's really difficult to render a strip, apply one effect with
>> another program and import the new footage with effect, and sometimes
>> animating effect properties or doing little changes is awful repeating
>> the whole process again.
>> What do you think about that?
>> I've been playing with MLT source, if you think this is interesting I
>> think I could make a POC integrating one effect into VSE to see how it
>> behaves.
>> Best regards,
>> ------------------------------------------------------------------------
>> Gaspar Fernández
>> Facebook de Gaspar Fernández <https://www.facebook.com/gaspy>   Twitter
>> de Gaspar Fernández <https://twitter.com/gaspar_fm>     LinkedIn de Gaspar
>> Fernández <https://www.linkedin.com/profile/view?id=49150267>   Youtube
>> de Gaspar Fernández <https://www.youtube.com/user/yutubero184/feed>
>> Google+ de Gaspar Fernández
>> <https://plus.google.com/u/0/+GasparFern%C3%A1ndez/posts>
>> _______________________________________________
>> Bf-committers mailing list
>> Bf-committers at blender.org
>> https://lists.blender.org/mailman/listinfo/bf-committers
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> https://lists.blender.org/mailman/listinfo/bf-committers

More information about the Bf-committers mailing list