== Sequencer ==
authorPeter Schlaile <peter@schlaile.de>
Sat, 11 Nov 2006 22:35:40 +0000 (22:35 +0000)
committerPeter Schlaile <peter@schlaile.de>
Sat, 11 Nov 2006 22:35:40 +0000 (22:35 +0000)
Major sequencer rewrite to add Speed Control effect.
Changes:
- Cleaned up large parts of sequence.c removing a lot of unnecessary code.
  (We first built old seqar array to decide, what is visible, then build
   dependencies with new code, then used old code to iterate through the
   strips and deciding using new code what is used and so forth and so on...)
  Should be much faster now.
- Now we build the strips recursively thereby elemenating the need of a
  seperate dependency calculation.
- Added a Speed-Control effect to change strip speed afterwards.
  (Offers global speed as well as IPO-controlled speed.
   There are several modes to play with:
   - Control by velocity (IPO = velocity where 1.0 is normal speed)
   - Control by frame number (IPO = target frame)
   - IPO-Value can be rescaled to frame-value, to make frame exact matching
     possible. (Matching video tracks to audio tracks with IPOs ;-)

Demo-Blend file is here http://peter.schlaile.de/blender/sequencer/speedcontroltest.blend

Since this was also a Plumiferos request I hope to be mentioned in the
credits ;-)

Enjoy! And please test the new sequencer thoroughly. It is really more like
a rewrite this time.

source/blender/blenloader/intern/writefile.c
source/blender/include/BSE_seqeffects.h
source/blender/include/BSE_sequence.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/src/drawseq.c
source/blender/src/editseq.c
source/blender/src/seqeffects.c
source/blender/src/sequence.c

index 5577c7aa8a6d7204416902134f703392b76f673f..2ee553824ef3669fa85e58ef056d190ffa81358f 100644 (file)
@@ -1262,6 +1262,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                                                case SEQ_COLOR:
                                                        writestruct(wd, DATA, "SolidColorVars", 1, seq->effectdata);
                                                        break;
+                                               case SEQ_SPEED:
+                                                       writestruct(wd, DATA, "SpeedControlVars", 1, seq->effectdata);
+                                                       break;
                                                case SEQ_WIPE:
                                                        writestruct(wd, DATA, "WipeVars", 1, seq->effectdata);
                                                        break;
index 0c3eab82e0bf2cc12fb75c64749dbfd01d33b6cc..d4d40654adaa81d36314e1964b54faa2be9fbcbd 100644 (file)
@@ -86,6 +86,7 @@ struct SeqEffectHandle {
 
 struct SeqEffectHandle get_sequence_effect(struct Sequence * seq);
 int get_sequence_effect_num_inputs(int seq_type);
+void sequence_effect_speed_rebuild_map(struct Sequence * seq, int force);
 
 #endif
 
index 66fa22a5918ce87347dc782b39077d0bbec4f2fa..c975e8de8ff13178676f826b1fd8bb3c296e8adf 100644 (file)
@@ -48,18 +48,12 @@ void free_stripdata(int len, struct StripElem *se);
 void free_strip(struct Strip *strip);
 void new_stripdata(struct Sequence *seq);
 void free_sequence(struct Sequence *seq);
-void do_seq_count(struct ListBase *seqbase, int *totseq);
-void do_build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int depth);
 void build_seqar(struct ListBase *seqbase, struct Sequence  ***seqar, int *totseq);
 void free_editing(struct Editing *ed);
 void calc_sequence(struct Sequence *seq);
 void sort_seq(void);
 void clear_scene_in_allseqs(struct Scene *sce);
-struct Sequence *get_shown_seq_from_metastrip(struct Sequence *seqm, int cfra);
 
-void make_black_ibuf(struct ImBuf *ibuf);
-void multibuf(struct ImBuf *ibuf, float fmul);
-void do_effect(int cfra, struct Sequence *seq, struct StripElem *se);
 int evaluate_seq_frame(int cfra);
 struct StripElem *give_stripelem(struct Sequence *seq, int cfra);
 void set_meta_stripdata(struct Sequence *seqm);
index 71908ded6af57663b6906accf6315c615a37a5b0..5bb9f61f71e82439de629d78eefc3b447426e50d 100644 (file)
@@ -49,8 +49,7 @@ typedef struct StripElem {
        struct ImBuf *ibuf;
        struct StripElem *se1, *se2, *se3;
        short ok;
-       unsigned char isneeded;
-       unsigned char pad;
+       short pad;
        int nr;
 } StripElem;
 
@@ -178,6 +177,18 @@ typedef struct SolidColorVars {
        float pad;
 } SolidColorVars;
 
+typedef struct SpeedControlVars {
+       float * frameMap;
+       float globalSpeed;
+       int flags;
+       int length;
+       int pad;
+} SpeedControlVars;
+
+/* SpeedControlVars->flags */
+#define SEQ_SPEED_INTEGRATE      1
+#define SEQ_SPEED_BLEND          2
+#define SEQ_SPEED_COMPRESS_IPO_Y 4
 
 /* ***************** SEQUENCE ****************** */
 
@@ -216,6 +227,7 @@ typedef struct SolidColorVars {
 #define SEQ_GLOW               26
 #define SEQ_TRANSFORM          27
 #define SEQ_COLOR               28
+#define SEQ_SPEED               29
 
 
 #endif
index 36c58bd8d5c9f336db008c89a6bd6d3f4bf6dc75..24c5f3d45fea3c6e7b09a3ea9cab70b63aec3526 100644 (file)
@@ -118,6 +118,7 @@ static char *give_seqname(Sequence *seq)
        else if(seq->type==SEQ_GLOW) return "Glow";
        else if(seq->type==SEQ_TRANSFORM) return "Transform";
        else if(seq->type==SEQ_COLOR) return "Color";
+       else if(seq->type==SEQ_SPEED) return "Speed";
        else if(seq->type==SEQ_PLUGIN) {
                if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) &&
                   seq->plugin && seq->plugin->doit) return seq->plugin->pname;
@@ -182,6 +183,7 @@ static void get_seq_color3ubv(Sequence *seq, char *col)
                
        /* effects */
        case SEQ_TRANSFORM:
+       case SEQ_SPEED:
        case SEQ_ADD:
        case SEQ_SUB:
        case SEQ_MUL:
@@ -1189,7 +1191,37 @@ static void seq_panel_properties(short cntrl)    // SEQ_HANDLER_PROPERTIES
                } else if(last_seq->type==SEQ_COLOR) {
                        SolidColorVars *colvars = (SolidColorVars *)last_seq->effectdata;
                        uiDefButF(block, COL, SEQ_BUT_RELOAD, "",10,90,150,19, colvars->col, 0, 0, 0, 0, "");
+               } else if(last_seq->type==SEQ_SPEED){
+                       SpeedControlVars *sp = 
+                               (SpeedControlVars *)last_seq->effectdata;
+
+                       uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Global Speed:",  10,70,150,19, &sp->globalSpeed, 0.0, 100.0, 0, 0, "Global Speed");
+
+                       uiDefButBitI(block, TOG, SEQ_SPEED_INTEGRATE,
+                                    SEQ_BUT_EFFECT, 
+                                    "IPO is velocity",
+                                    10,50,150,19, &sp->flags, 
+                                    0.0, 1.0, 0, 0, 
+                                    "Interpret the IPO value as a "
+                                    "velocity instead of a frame number");
+
+                       uiDefButBitI(block, TOG, SEQ_SPEED_BLEND,
+                                    SEQ_BUT_EFFECT, 
+                                    "Enable frame blending",
+                                    10,30,150,19, &sp->flags, 
+                                    0.0, 1.0, 0, 0, 
+                                    "Blend two frames into the "
+                                    "target for a smoother result");
+
+                       uiDefButBitI(block, TOG, SEQ_SPEED_COMPRESS_IPO_Y,
+                                    SEQ_BUT_EFFECT, 
+                                    "IPO value runs from [0..1]",
+                                    10,10,150,19, &sp->flags, 
+                                    0.0, 1.0, 0, 0, 
+                                    "Scale IPO value to get the "
+                                    "target frame number.");
                }
+
                uiBlockEndAlign(block);
        }
 }
index f5f8228697fb279234f3671d0b5c64fe04846dfa..ec7d14c980bdb104d01fd1f3fbd30a0ffe975a93 100644 (file)
@@ -1046,6 +1046,7 @@ static int event_to_efftype(int event)
        if(event==14) return SEQ_GLOW;
        if(event==15) return SEQ_TRANSFORM;
        if(event==16) return SEQ_COLOR;
+       if(event==17) return SEQ_SPEED;
        return 0;
 }
 
@@ -1345,6 +1346,9 @@ void add_sequence(int type)
                case SEQ_COLOR:
                        event = 16;
                        break;
+               case SEQ_SPEED:
+                       event = 17;
+                       break;
                default:
                        event = 0;
                        break;
@@ -1374,7 +1378,8 @@ void add_sequence(int type)
                               "|Wipe%x13"
                               "|Glow%x14"
                               "|Transforms%x15"
-                              "|Color Generator%x16");
+                              "|Color Generator%x16"
+                              "|Speed Control%x17");
        }
 
        if(event<1) return;
@@ -1454,6 +1459,7 @@ void add_sequence(int type)
        case 14:
        case 15:
        case 16:
+       case 17:
                if(get_last_seq()==0 && 
                   get_sequence_effect_num_inputs( event_to_efftype(event))> 0)
                        error("Need at least one active sequence strip");
@@ -1499,7 +1505,8 @@ void change_sequence(void)
                                "|Wipe%x13"
                                "|Glow%x14"
                                "|Transform%x15"
-                               "|Color Generator%x16");
+                               "|Color Generator%x16"
+                               "|Speed Control%x17");
                if(event > 0) {
                        if(event==1) {
                                SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
index 9196f02c28bc61defe4c602c7baea5dc58e69b11..3a0adfdaa39653ca425c8b301ae525c72f5810ae 100644 (file)
@@ -743,6 +743,8 @@ void do_cross_effect_float(float facf0, float facf1, int x, int y,
        }
 }
 
+/* carefull: also used by speed effect! */
+
 static void do_cross_effect(Sequence * seq,int cfra,
                            float facf0, float facf1, int x, int y, 
                            struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
@@ -2785,6 +2787,154 @@ static void do_solid_color(Sequence * seq,int cfra,
        }
 }
 
+/* **********************************************************************
+   SPEED
+   ********************************************************************** */
+static void init_speed_effect(Sequence *seq)
+{
+       SpeedControlVars * v;
+
+       if(seq->effectdata) MEM_freeN(seq->effectdata);
+       seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), 
+                                     "speedcontrolvars");
+
+       v = (SpeedControlVars *)seq->effectdata;
+       v->globalSpeed = 1.0;
+       v->frameMap = 0;
+       v->flags = SEQ_SPEED_COMPRESS_IPO_Y;
+       v->length = 0;
+}
+
+static void load_speed_effect(Sequence * seq)
+{
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+
+       v->frameMap = 0;
+       v->length = 0;
+}
+
+static int num_inputs_speed()
+{
+       return 1;
+}
+
+static void free_speed_effect(Sequence *seq)
+{
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+       if(v->frameMap) MEM_freeN(v->frameMap);
+       if(seq->effectdata) MEM_freeN(seq->effectdata);
+       seq->effectdata = 0;
+}
+
+static void copy_speed_effect(Sequence *dst, Sequence *src)
+{
+       dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_speed(struct Sequence *seq,
+                         float facf0, float facf1)
+{
+       return 1;
+}
+
+void sequence_effect_speed_rebuild_map(struct Sequence * seq, int force)
+{
+       float facf0 = seq->facf0;
+       float ctime, div;
+       int cfra;
+       SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
+
+       /* if not already done, load / initialize data */
+       get_sequence_effect(seq);
+
+       if (!(force || seq->len != v->length || !v->frameMap)) {
+               return;
+       }
+
+       if (!v->frameMap || v->length != seq->len) {
+               if (v->frameMap) MEM_freeN(v->frameMap);
+
+               v->length = seq->len;
+
+               v->frameMap = MEM_callocN(sizeof(float) * v->length, 
+                                         "speedcontrol frameMap");
+       }
+       if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
+               float cursor = 0;
+
+               for (cfra = 0; cfra < v->length; cfra++) {
+                       if(seq->ipo) {
+                               if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+                                       ctime = frame_to_float(seq->startdisp
+                                                              + cfra);
+                                       div = 1.0;
+                               } else {
+                                       ctime= frame_to_float(cfra);
+                                       div= v->length / 100.0f;
+                                       if(div==0.0) return;
+                               }
+               
+                               calc_ipo(seq->ipo, ctime/div);
+                               execute_ipo((ID *)seq, seq->ipo);
+                       } else {
+                               seq->facf0 = 1.0;
+                       }
+                       seq->facf0 *= v->globalSpeed;
+
+                       cursor += seq->facf0;
+
+                       if (cursor >= v->length) {
+                               v->frameMap[cfra] = v->length - 1;
+                       } else {
+                               v->frameMap[cfra] = cursor;
+                       }
+               }
+       } else {
+               for (cfra = 0; cfra < v->length; cfra++) {
+                       if(seq->ipo) {
+                               if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
+                                       ctime = frame_to_float(seq->startdisp
+                                                              + cfra);
+                                       div = 1.0;
+                               } else {
+                                       ctime= frame_to_float(cfra);
+                                       div= v->length / 100.0f;
+                                       if(div==0.0) return;
+                               }
+               
+                               calc_ipo(seq->ipo, ctime/div);
+                               execute_ipo((ID *)seq, seq->ipo);
+                       }
+                       
+                       if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
+                               seq->facf0 *= v->length;
+                       }
+                       if (!seq->ipo) {
+                               seq->facf0 = cfra;
+                       }
+                       seq->facf0 *= v->globalSpeed;
+                       if (seq->facf0 >= v->length) {
+                               seq->facf0 = v->length - 1;
+                       }
+                       v->frameMap[cfra] = seq->facf0;
+               }
+       }
+       seq->facf0 = facf0;
+}
+
+/*
+  simply reuse do_cross_effect for blending...
+
+static void do_speed_effect(Sequence * seq,int cfra,
+                          float facf0, float facf1, int x, int y, 
+                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
+                          struct ImBuf *ibuf3, struct ImBuf *out)
+{
+
+}
+*/
+
+
 /* **********************************************************************
    sequence effect factory
    ********************************************************************** */
@@ -2944,6 +3094,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
                rval.copy = copy_transform_effect;
                rval.execute = do_transform_effect;
                break;
+       case SEQ_SPEED:
+               rval.init = init_speed_effect;
+               rval.num_inputs = num_inputs_speed;
+               rval.load = load_speed_effect;
+               rval.free = free_speed_effect;
+               rval.copy = copy_speed_effect;
+               rval.execute = do_cross_effect;
+               rval.early_out = early_out_speed;
+               break;
        case SEQ_COLOR:
                rval.init = init_solid_color;
                rval.num_inputs = num_inputs_color;
@@ -2952,7 +3111,6 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
                rval.copy = copy_solid_color;
                rval.execute = do_solid_color;
                break;
-
        case SEQ_PLUGIN:
                rval.init_plugin = init_plugin;
                rval.num_inputs = num_inputs_plugin;
@@ -2973,7 +3131,7 @@ struct SeqEffectHandle get_sequence_effect(Sequence * seq)
 {
        struct SeqEffectHandle rval = get_sequence_effect_impl(seq->type);
 
-       if (seq->flag & SEQ_EFFECT_NOT_LOADED) {
+       if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
                rval.load(seq);
                seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
        }
index f34484fea14a0d8129451dde0789ffc16bebfe08..090d821a342cb98f6abe91776f636c050458b054 100644 (file)
@@ -72,8 +72,6 @@
 
 int seqrectx, seqrecty;
 
-/* ***************** END PLUGIN ************************ */
-
 void free_stripdata(int len, StripElem *se)
 {
        StripElem *seo;
@@ -137,7 +135,16 @@ void free_sequence(Sequence *seq)
        MEM_freeN(seq);
 }
 
-void do_seq_count(ListBase *seqbase, int *totseq)
+/*
+  **********************************************************************
+  * build_seqar
+  **********************************************************************
+  * Build a complete array of _all_ sequencies (including those
+  * in metastrips!)
+  **********************************************************************
+*/
+
+static void do_seq_count(ListBase *seqbase, int *totseq)
 {
        Sequence *seq;
 
@@ -149,7 +156,7 @@ void do_seq_count(ListBase *seqbase, int *totseq)
        }
 }
 
-void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
+static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
 {
        Sequence *seq;
 
@@ -363,7 +370,7 @@ void clear_scene_in_allseqs(Scene *sce)
 
 /* ***************** DO THE SEQUENCE ***************** */
 
-void make_black_ibuf(ImBuf *ibuf)
+static void make_black_ibuf(ImBuf *ibuf)
 {
        unsigned int *rect;
        float *rect_float;
@@ -385,7 +392,7 @@ void make_black_ibuf(ImBuf *ibuf)
        }
 }
 
-void multibuf(ImBuf *ibuf, float fmul)
+static void multibuf(ImBuf *ibuf, float fmul)
 {
        char *rt;
        float *rt_float;
@@ -425,7 +432,7 @@ void multibuf(ImBuf *ibuf, float fmul)
        }
 }
 
-void do_effect(int cfra, Sequence *seq, StripElem *se)
+static void do_effect(int cfra, Sequence *seq, StripElem *se)
 {
        StripElem *se1, *se2, *se3;
        float fac, facf;
@@ -555,10 +562,10 @@ StripElem *give_stripelem(Sequence *seq, int cfra)
        if (seq->strobe > 1.0) {
                nr -= (int)fmod((double)nr, (double)seq->strobe);
        }
-
+       
        se+= nr; /* don't get confused by the increment, this is the same as strip->stripdata[nr], which works on some compilers...*/
        se->nr= nr;
-
+       
        return se;
 }
 
@@ -594,7 +601,7 @@ int evaluate_seq_frame(int cfra)
 
 }
 
-Sequence *get_shown_seq_from_metastrip(Sequence * seqm, int cfra)
+Sequence *get_shown_sequence(ListBase * seqbasep, int cfra, int chanshown)
 {
        Sequence *seq, *seqim, *seqeff;
        Sequence *seq_arr[MAXSEQ+1];
@@ -602,7 +609,14 @@ Sequence *get_shown_seq_from_metastrip(Sequence * seqm, int cfra)
 
        seq = 0;
 
-       if(evaluate_seq_frame_gen(seq_arr, &seqm->seqbase, cfra)) {
+       if (chanshown > MAXSEQ) {
+               return 0;
+       }
+
+       if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
+               if (chanshown > 0) {
+                       return seq_arr[chanshown];
+               }
 
                /* we take the upper effect strip or 
                   the lowest imagestrip/metastrip */
@@ -615,8 +629,7 @@ Sequence *get_shown_seq_from_metastrip(Sequence * seqm, int cfra)
                                        if(seqeff==0) seqeff= seq;
                                        else if(seqeff->machine < seq->machine)
                                                seqeff= seq;
-                               }
-                               else {
+                               } else if (seq->type != SEQ_RAM_SOUND && seq->type != SEQ_HD_SOUND) {
                                        if(seqim==0) seqim= seq;
                                        else if(seqim->machine > seq->machine)
                                                seqim= seq;
@@ -631,6 +644,11 @@ Sequence *get_shown_seq_from_metastrip(Sequence * seqm, int cfra)
        return seq;
 }
  
+static Sequence * get_shown_seq_from_metastrip(Sequence * seqm, int cfra)
+{
+       return get_shown_sequence(&seqm->seqbase, cfra, 0);
+}
+
 void set_meta_stripdata(Sequence *seqm)
 {
        Sequence *seq;
@@ -649,94 +667,229 @@ void set_meta_stripdata(Sequence *seqm)
                        se->se1= 0;
                }
        }
-
 }
 
-
-
-/* HELP FUNCTIONS FOR GIVE_IBUF_SEQ */
-
-static void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra)
+static void do_build_seq_ibuf(Sequence * seq, int cfra)
 {
-       Sequence *seq;
+       StripElem *se = seq->curelem;
+       char name[FILE_MAXDIR+FILE_MAXFILE];
 
-       seq= seqbase->first;
-       while(seq) {
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
-                       (*totseq)++;
+       if(seq->type == SEQ_META) {
+               se->ok= 2;
+               if(se->se1==0) set_meta_stripdata(seq);
+               if(se->se1) {
+                       se->ibuf= se->se1->ibuf;
                }
-               seq= seq->next;
-       }
-}
-
-static void do_seq_unref_cfra(ListBase *seqbase, int cfra)
-{
-       Sequence *seq;
-
-       seq= seqbase->first;
-       while(seq) {
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
-
-                       if(seq->seqbase.first) {
-
-                               if(cfra< seq->start) do_seq_unref_cfra(
-                                       &seq->seqbase, seq->start);
-                               else if(cfra> seq->start+seq->len-1) 
-                                       do_seq_unref_cfra(
-                                               &seq->seqbase, 
-                                               seq->start+seq->len-1);
-                               else do_seq_unref_cfra(&seq->seqbase, cfra);
+       } else if(seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
+               se->ok= 2;
+       } else if(seq->type & SEQ_EFFECT) {
+                       
+               /* test if image is too small or discarded from cache: reload */
+               if(se->ibuf) {
+                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                               IMB_freeImBuf(se->ibuf);
+                               se->ibuf= 0;
                        }
-
-                       if (seq->curelem && seq->curelem->ibuf && seq->curelem->isneeded)
-                               IMB_cache_limiter_unref(seq->curelem->ibuf);
                }
-               seq= seq->next;
-       }
-}
-
-static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra)
-{
-       Sequence *seq;
-
-       seq= seqbase->first;
-       while(seq) {
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
-
-                       if(seq->seqbase.first) {
-
-                               if(cfra< seq->start) 
-                                       do_seq_test_unref_cfra(
-                                               &seq->seqbase, seq->start);
-                               else if(cfra> seq->start+seq->len-1) 
-                                       do_seq_test_unref_cfra(
-                                               &seq->seqbase, 
-                                               seq->start+seq->len-1);
-                               else do_seq_test_unref_cfra(
-                                       &seq->seqbase, cfra);
+                       
+               /* should the effect be recalculated? */
+               
+               if(se->ibuf==0 
+                  || (seq->seq1 && se->se1 != seq->seq1->curelem) 
+                  || (seq->seq2 && se->se2 != seq->seq2->curelem) 
+                  || (seq->seq3 && se->se3 != seq->seq3->curelem)) {
+                       if (seq->seq1) se->se1= seq->seq1->curelem;
+                       if (seq->seq2) se->se2= seq->seq2->curelem;
+                       if (seq->seq3) se->se3= seq->seq3->curelem;
+                       
+                       if(se->ibuf==NULL) {
+                               /* if one of two first inputs are rectfloat, output is float too */
+                               if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
+                                  (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float))
+                                       se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                               else
+                                       se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
                        }
-
-                       if (seq->curelem && seq->curelem->ibuf
-                               && seq->curelem->isneeded) {
-                               if (IMB_cache_limiter_get_refcount(
-                                           seq->curelem->ibuf)) {
-                                       fprintf(stderr, 
-                                               "sequence.c: imbuf-refcount "
-                                               "Arggh: %p, %d\n", 
-                                               seq, seq->type);
-                         }
+                       
+                       do_effect(cfra, seq, se);
+               }
+               
+               /* test size */
+               if(se->ibuf) {
+                       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+                               if(G.scene->r.mode & R_OSA) {
+                                       IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                               } else {
+                                       IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                               }
                        }
                }
-               seq= seq->next;
+       } else if(seq->type < SEQ_EFFECT) {
+               if(se->ibuf) {
+                       /* test if image too small 
+                          or discarded from cache: reload */
+                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                               IMB_freeImBuf(se->ibuf);
+                               se->ibuf= 0;
+                               se->ok= 1;
+                       }
+               }
+               
+               if(seq->type==SEQ_IMAGE) {
+                       if(se->ok && se->ibuf==0) {
+                               /* if playanim or render: 
+                                  no waitcursor */
+                               if((G.f & G_PLAYANIM)==0) 
+                                       waitcursor(1);
+                               
+                               strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
+                               strncat(name, se->name, FILE_MAXFILE);
+                               BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+                               se->ibuf= IMB_loadiffname(name, IB_rect);
+                               
+                               if((G.f & G_PLAYANIM)==0) 
+                                       waitcursor(0);
+                               
+                               if(se->ibuf==0) se->ok= 0;
+                               else {
+                                       if(seq->flag & SEQ_MAKE_PREMUL) {
+                                               if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf);
+                                       }
+                                       seq->strip->orx= se->ibuf->x;
+                                       seq->strip->ory= se->ibuf->y;
+                                       if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
+                                       if(seq->mul==0.0) seq->mul= 1.0;
+                                       if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
+                               }
+                       }
+               }
+               else if(seq->type==SEQ_MOVIE) {
+                       if(se->ok && se->ibuf==0) {
+                               if(seq->anim==0) {
+                                       strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
+                                       strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1);
+                                       BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
+                                       
+                                       seq->anim = openanim(name, IB_rect);
+                               }
+                               if(seq->anim) {
+                                       IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
+                                       se->ibuf = IMB_anim_absolute(seq->anim, se->nr);
+                               }
+                               
+                               if(se->ibuf==0) se->ok= 0;
+                               else {
+                                       if(seq->flag & SEQ_MAKE_PREMUL) {
+                                               if(se->ibuf->depth==32) converttopremul(se->ibuf);
+                                       }
+                                       seq->strip->orx= se->ibuf->x;
+                                       seq->strip->ory= se->ibuf->y;
+                                       if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
+                                       if(seq->mul==0.0) seq->mul= 1.0;
+                                       if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
+                               }
+                       }
+               } else if(seq->type==SEQ_SCENE && se->ibuf==NULL && seq->scene) {       // scene can be NULL after deletions
+                       int oldcfra = CFRA;
+                       Scene *sce= seq->scene, *oldsce= G.scene;
+                       Render *re;
+                       RenderResult rres;
+                       int doseq, rendering= G.rendering;
+                       char scenename[64];
+                       
+                       waitcursor(1);
+                       
+                       /* Hack! This function can be called from do_render_seq(), in that case
+                          the seq->scene can already have a Render initialized with same name, 
+                          so we have to use a default name. (compositor uses G.scene name to
+                          find render).
+                          However, when called from within the UI (image preview in sequencer)
+                          we do want to use scene Render, that way the render result is defined
+                          for display in render/imagewindow */
+                       if(rendering) {
+                               BLI_strncpy(scenename, sce->id.name+2, 64);
+                               strcpy(sce->id.name+2, " do_build_seq_ibuf");
+                       }
+                       re= RE_NewRender(sce->id.name);
+                       
+                       /* prevent eternal loop */
+                       doseq= sce->r.scemode & R_DOSEQ;
+                       sce->r.scemode &= ~R_DOSEQ;
+                       
+                       BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
+                       
+                       /* hrms, set_scene still needed? work on that... */
+                       if(sce!=oldsce) set_scene_bg(sce);
+                       RE_BlenderFrame(re, sce, seq->sfra + se->nr);
+                       if(sce!=oldsce) set_scene_bg(oldsce);
+                       
+                       /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
+                       G.rendering= rendering;
+                       if(rendering)
+                               BLI_strncpy(sce->id.name+2, scenename, 64);
+                       
+                       RE_GetResultImage(re, &rres);
+                       
+                       if(rres.rectf) {
+                               se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                               memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
+                               if(rres.rectz) {
+                                       addzbuffloatImBuf(se->ibuf);
+                                       memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
+                               }
+                       }
+                       
+                       BIF_end_render_callbacks();
+                       
+                       /* restore */
+                       sce->r.scemode |= doseq;
+                       
+                       if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */
+                               waitcursor(0);
+                       CFRA = oldcfra;
+               }
+               
+               /* size test */
+               if(se->ibuf) {
+                       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+                               
+                               if (0) { // G.scene->r.mode & R_FIELDS) {
+                                       
+                                       if (seqrecty > 288) 
+                                               IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                                       else {
+                                               IMB_de_interlace(se->ibuf);
+                                               
+                                               if(G.scene->r.mode & R_OSA)
+                                                       IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                                               else
+                                                       IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                                       }
+                               }
+                               else {
+                                       if(G.scene->r.mode & R_OSA)
+                                               IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty);
+                                       else
+                                               IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+                               }
+                       }
+                       
+               }
+       }
+       if (se->ibuf) {
+               IMB_cache_limiter_insert(se->ibuf);
+               IMB_cache_limiter_ref(se->ibuf);
+               IMB_cache_limiter_touch(se->ibuf);
        }
 }
 
-static void do_build_seq_depend(Sequence * seq, int cfra);
+static void do_build_seq_recursively(Sequence * seq, int cfra);
 
-static void do_effect_depend(int cfra, Sequence * seq, StripElem *se)
+static void do_effect_seq_recursively(int cfra, Sequence * seq, StripElem *se)
 {
        float fac, facf;
        struct SeqEffectHandle sh = get_sequence_effect(seq);
+       int early_out;
 
        if(seq->ipo && seq->ipo->curve.first) {
                do_seq_ipo(seq);
@@ -748,351 +901,220 @@ static void do_effect_depend(int cfra, Sequence * seq, StripElem *se)
 
        if( G.scene->r.mode & R_FIELDS ); else facf= fac;
        
-       switch (sh.early_out(seq, fac, facf)) {
+       early_out = sh.early_out(seq, fac, facf);
+       switch (early_out) {
        case -1:
                /* no input needed */
                break;
        case 0:
-               do_build_seq_depend(seq->seq1, cfra);
-               do_build_seq_depend(seq->seq2, cfra);
+               do_build_seq_recursively(seq->seq1, cfra);
+               do_build_seq_recursively(seq->seq2, cfra);
                break;
        case 1:
-               do_build_seq_depend(seq->seq1, cfra);
+               do_build_seq_recursively(seq->seq1, cfra);
                break;
        case 2:
-               do_build_seq_depend(seq->seq2, cfra);
+               do_build_seq_recursively(seq->seq2, cfra);
                break;
        }
 
        if (seq->seq3) {
-               do_build_seq_depend(seq->seq3, cfra);
+               do_build_seq_recursively(seq->seq3, cfra);
+       }
+
+       do_build_seq_ibuf(seq, cfra);
+
+       /* children are not needed anymore ... */
+
+       switch (early_out) {
+       case 0:
+               if (seq->seq1->curelem && seq->seq1->curelem->ibuf)
+                       IMB_cache_limiter_unref(seq->seq1->curelem->ibuf);
+               if (seq->seq2->curelem && seq->seq2->curelem->ibuf)
+                       IMB_cache_limiter_unref(seq->seq2->curelem->ibuf);
+               break;
+       case 1:
+               if (seq->seq1->curelem && seq->seq1->curelem->ibuf)
+                       IMB_cache_limiter_unref(seq->seq1->curelem->ibuf);
+               break;
+       case 2:
+               if (seq->seq2->curelem && seq->seq2->curelem->ibuf)
+                       IMB_cache_limiter_unref(seq->seq2->curelem->ibuf);
+               break;
+       }
+       if (seq->seq3) {
+               if (seq->seq3->curelem && seq->seq3->curelem->ibuf)
+                       IMB_cache_limiter_unref(seq->seq3->curelem->ibuf);
        }
 }
 
-static void do_build_seq_depend(Sequence * seq, int cfra)
+static void do_build_seq_recursively_impl(Sequence * seq, int cfra)
 {
-       StripElem *se = seq->curelem;
+       StripElem *se;
+
+       se = seq->curelem = give_stripelem(seq, cfra);
 
-       if(se && !se->isneeded) {
-               se->isneeded = 1;
+       if(se) {
                if(seq->seqbase.first) {
                        Sequence * seqmshown= get_shown_seq_from_metastrip(seq, cfra);
                        if (seqmshown) {
                                if(cfra< seq->start) 
-                                       do_build_seq_depend(seqmshown, seq->start);
+                                       do_build_seq_recursively(seqmshown, seq->start);
                                else if(cfra> seq->start+seq->len-1) 
-                                       do_build_seq_depend(seqmshown, seq->start + seq->len-1);
-                               else do_build_seq_depend(seqmshown, cfra);
+                                       do_build_seq_recursively(seqmshown, seq->start + seq->len-1);
+                               else do_build_seq_recursively(seqmshown, cfra);
                        }
                }
 
                if (seq->type & SEQ_EFFECT) {
-                       do_effect_depend(cfra, seq, se);
+                       do_effect_seq_recursively(cfra, seq, se);
+               } else {
+                       do_build_seq_ibuf(seq, cfra);
                }
        }
 }
 
-static void do_build_seq_ibuf(Sequence * seq, int cfra)
-{
-       StripElem *se = seq->curelem;
-       char name[FILE_MAXDIR+FILE_MAXFILE];
+/* FIXME:
+   
+If cfra was float throughout blender (especially in the render
+pipeline) one could even _render_ with subframe precision
+instead of faking using the blend code below...
 
-       if(se && se->isneeded) {
-               if(seq->type == SEQ_META) {
-                       se->ok= 2;
-                       if(se->se1==0) set_meta_stripdata(seq);
-                       if(se->se1) {
-                               se->ibuf= se->se1->ibuf;
-                       }
-               }
-               else if(seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) {
-                       se->ok= 2;
-               }
-               else if(seq->type & SEQ_EFFECT) {
-                       
-                       /* test if image is too small or discarded from cache: reload */
-                       if(se->ibuf) {
-                               if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty || !(se->ibuf->rect || se->ibuf->rect_float)) {
-                                       IMB_freeImBuf(se->ibuf);
-                                       se->ibuf= 0;
-                               }
-                       }
-                       
-                       /* should the effect be recalculated? */
-                       
-                       if(se->ibuf==0 
-                          || (seq->seq1 && se->se1 != seq->seq1->curelem) 
-                          || (seq->seq2 && se->se2 != seq->seq2->curelem) 
-                          || (seq->seq3 && se->se3 != seq->seq3->curelem)) {
-                               if (seq->seq1) se->se1= seq->seq1->curelem;
-                               if (seq->seq2) se->se2= seq->seq2->curelem;
-                               if (seq->seq3) se->se3= seq->seq3->curelem;
-                               
-                               if(se->ibuf==NULL) {
-                                       /* if one of two first inputs are rectfloat, output is float too */
-                                       if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
-                                          (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float))
-                                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
-                                       else
-                                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
-                               }
+*/
 
-                               do_effect(cfra, seq, se);
-                       }
-                       
-                       /* test size */
-                       if(se->ibuf) {
-                               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
-                                       if(G.scene->r.mode & R_OSA) {
-                                               IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                       } else {
-                                               IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                       }
-                               }
+static void do_handle_speed_effect(Sequence * seq, int cfra)
+{
+       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
+       int nr = cfra - seq->start;
+       float f_cfra;
+       int cfra_left;
+       int cfra_right;
+       StripElem * se = 0;
+       StripElem * se1 = 0;
+       StripElem * se2 = 0;
+       
+       sequence_effect_speed_rebuild_map(seq, 0);
+       
+       f_cfra = seq->start + s->frameMap[nr];
+       
+       cfra_left = (int) floor(f_cfra);
+       cfra_right = (int) ceil(f_cfra);
+
+       se = seq->curelem = give_stripelem(seq, cfra);
+
+       if (cfra_left == cfra_right || 
+           (s->flags & SEQ_SPEED_BLEND) == 0) {
+               if(se->ibuf) {
+                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
+                          || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                               IMB_freeImBuf(se->ibuf);
+                               se->ibuf= 0;
                        }
                }
-               else if(seq->type < SEQ_EFFECT) {
-                       if(se->ibuf) {
-                               /* test if image too small 
-                                  or discarded from cache: reload */
-                               if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty || !(se->ibuf->rect || se->ibuf->rect_float)) {
-                                       IMB_freeImBuf(se->ibuf);
-                                       se->ibuf= 0;
-                                       se->ok= 1;
-                               }
-                       }
-                       
-                       if(seq->type==SEQ_IMAGE) {
-                               if(se->ok && se->ibuf==0) {
-                                       /* if playanim or render: 
-                                          no waitcursor */
-                                       if((G.f & G_PLAYANIM)==0) 
-                                               waitcursor(1);
-                                       
-                                       strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
-                                       strncat(name, se->name, FILE_MAXFILE);
-                                       BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
-                                       se->ibuf= IMB_loadiffname(name, IB_rect);
-                                       
-                                       if((G.f & G_PLAYANIM)==0) 
-                                               waitcursor(0);
-                                       
-                                       if(se->ibuf==0) se->ok= 0;
-                                       else {
-                                               if(seq->flag & SEQ_MAKE_PREMUL) {
-                                                       if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf);
-                                               }
-                                               seq->strip->orx= se->ibuf->x;
-                                               seq->strip->ory= se->ibuf->y;
-                                               if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
-                                               if(seq->mul==0.0) seq->mul= 1.0;
-                                               if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
-                                       }
-                               }
-                       }
-                       else if(seq->type==SEQ_MOVIE) {
-                               if(se->ok && se->ibuf==0) {
-                                       if(seq->anim==0) {
-                                               strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
-                                               strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1);
-                                               BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
-                                               
-                                               seq->anim = openanim(name, IB_rect);
-                                       }
-                                       if(seq->anim) {
-                                               IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
-                                               se->ibuf = IMB_anim_absolute(seq->anim, se->nr);
-                                       }
-                                       
-                                       if(se->ibuf==0) se->ok= 0;
-                                       else {
-                                               if(seq->flag & SEQ_MAKE_PREMUL) {
-                                                       if(se->ibuf->depth==32) converttopremul(se->ibuf);
-                                               }
-                                               seq->strip->orx= se->ibuf->x;
-                                               seq->strip->ory= se->ibuf->y;
-                                               if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
-                                               if(seq->mul==0.0) seq->mul= 1.0;
-                                               if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
-                                       }
-                               }
-                       }
-                       else if(seq->type==SEQ_SCENE && se->ibuf==NULL && seq->scene) { // scene can be NULL after deletions
-                               int oldcfra = CFRA;
-                               Scene *sce= seq->scene, *oldsce= G.scene;
-                               Render *re;
-                               RenderResult rres;
-                               int doseq, rendering= G.rendering;
-                               char scenename[64];
-                               
-                               waitcursor(1);
-                               
-                               /* Hack! This function can be called from do_render_seq(), in that case
-                                  the seq->scene can already have a Render initialized with same name, 
-                                  so we have to use a default name. (compositor uses G.scene name to
-                                  find render).
-                                  However, when called from within the UI (image preview in sequencer)
-                                  we do want to use scene Render, that way the render result is defined
-                                  for display in render/imagewindow */
-                               if(rendering) {
-                                       BLI_strncpy(scenename, sce->id.name+2, 64);
-                                       strcpy(sce->id.name+2, " do_build_seq_ibuf");
-                               }
-                               re= RE_NewRender(sce->id.name);
-                               
-                               /* prevent eternal loop */
-                               doseq= sce->r.scemode & R_DOSEQ;
-                               sce->r.scemode &= ~R_DOSEQ;
-                               
-                               BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
-                               
-                               /* hrms, set_scene still needed? work on that... */
-                               if(sce!=oldsce) set_scene_bg(sce);
-                               RE_BlenderFrame(re, sce, seq->sfra + se->nr);
-                               if(sce!=oldsce) set_scene_bg(oldsce);
-                               
-                               /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
-                               G.rendering= rendering;
-                               if(rendering)
-                                       BLI_strncpy(sce->id.name+2, scenename, 64);
-                               
-                               RE_GetResultImage(re, &rres);
-                               
-                               if(rres.rectf) {
-                                       se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
-                                       memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
-                                       if(rres.rectz) {
-                                               addzbuffloatImBuf(se->ibuf);
-                                               memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
-                                       }
-                               }
-                                          
-                               BIF_end_render_callbacks();
 
-                               /* restore */
-                               sce->r.scemode |= doseq;
-                               
-                               if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */
-                                       waitcursor(0);
-                               CFRA = oldcfra;
-                       }
-                       
-                       /* size test */
-                       if(se->ibuf) {
-                               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
-                                       
-                                       if (0) { // G.scene->r.mode & R_FIELDS) {
-                                               
-                                               if (seqrecty > 288) 
-                                                       IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                               else {
-                                                       IMB_de_interlace(se->ibuf);
-                                                       
-                                                       if(G.scene->r.mode & R_OSA)
-                                                               IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                       else
-                                                               IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                               }
-                                       }
-                                       else {
-                                               if(G.scene->r.mode & R_OSA)
-                                                       IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty);
-                                               else
-                                                       IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
+               if (se->ibuf == NULL) {
+                       do_build_seq_recursively_impl(seq->seq1, cfra_left);
+
+                       se1 = seq->seq1->curelem;
+
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+
+                       if (se1 == 0 || se1->ibuf == 0) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               if (se->ibuf != se1->ibuf) {
+                                       if (se->ibuf) {
+                                               IMB_freeImBuf(se->ibuf);
                                        }
+
+                                       se->ibuf = se1->ibuf;
+                                       IMB_refImBuf(se->ibuf);
                                }
-                               
                        }
                }
-               if (se->ibuf) {
-                       IMB_cache_limiter_insert(se->ibuf);
-                       IMB_cache_limiter_ref(se->ibuf);
-                       IMB_cache_limiter_touch(se->ibuf);
-               }
-       }
-}
-
-static void do_set_seq_curelem(ListBase *seqbase, int cfra)
-{
-       Sequence *seq;
-
-       for(seq=seqbase->first; seq; seq=seq->next) {
-               seq->curelem= give_stripelem(seq, cfra);
-
-               if (seq->curelem) {
-                       seq->curelem->isneeded= 0; /* nobody is needed a priori */
+       } else {
+               struct SeqEffectHandle sh;
 
-                       if (seq->seqbase.first)
-                               do_set_seq_curelem(&seq->seqbase, cfra);
+               if(se->ibuf) {
+                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
+                          || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                               IMB_freeImBuf(se->ibuf);
+                               se->ibuf= 0;
+                       }
                }
-       }
-}
 
-static void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra)
-{
-       Sequence *seq;
+               if (se->ibuf == NULL) {
+                       do_build_seq_recursively_impl(seq->seq1, cfra_left);
+                       se1 = seq->seq1->curelem;
+                       do_build_seq_recursively_impl(seq->seq1, cfra_right);
+                       se2 = seq->seq1->curelem;
 
-       if(seqar==NULL) return;
-       
-       seq= seqbase->first;
-       while(seq) {
-               if ((seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) && (seq->ipo)
-                   && (seq->startdisp <= cfra+2) && (seq->enddisp > cfra)) {
-                       do_seq_ipo(seq);
-               }
 
-               if(seq->curelem) {
-                       **seqar= seq;
-                       (*seqar)++;
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       
+                       if (!se1 || !se2) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               sh = get_sequence_effect(seq);
+
+                               sh.execute(seq, cfra, 
+                                          f_cfra - (float) cfra_left, 
+                                          f_cfra - (float) cfra_left, 
+                                          se->ibuf->x, se->ibuf->y, 
+                                          se1->ibuf, se2->ibuf, 0, se->ibuf);
+                       }
                }
 
-               seq= seq->next;
        }
-}
-
-static void do_build_seq_ibufs(ListBase *seqbase, int cfra)
-{
-       Sequence *seq;
 
-       seq= seqbase->first;
-       while(seq) {
-               if ((seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) && (seq->ipo)
-                   && (seq->startdisp <= cfra+2)  && (seq->enddisp > cfra)) {
-                       do_seq_ipo(seq);
-               }
+       /* caller expects this to be referenced, so do it! */
+       if (se->ibuf) {
+               IMB_cache_limiter_insert(se->ibuf);
+               IMB_cache_limiter_ref(se->ibuf);
+               IMB_cache_limiter_touch(se->ibuf);
+       }
 
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
-                       if(seq->seqbase.first) {
-                               if(cfra< seq->start) 
-                                       do_build_seq_ibufs(&seq->seqbase, seq->start);
-                               else if(cfra> seq->start+seq->len-1) 
-                                       do_build_seq_ibufs(&seq->seqbase, seq->start + seq->len-1);
-                               else do_build_seq_ibufs(&seq->seqbase, cfra);
-                       }
+       /* children are no longer needed */
+       if (se1 && se1->ibuf)
+               IMB_cache_limiter_unref(se1->ibuf);
+       if (se2 && se2->ibuf)
+               IMB_cache_limiter_unref(se2->ibuf);
+}
 
-                       do_build_seq_ibuf(seq, cfra);
-               }
+/* 
+ * build all ibufs recursively
+ * 
+ * if successfull, seq->curelem->ibuf contains the (referenced!) imbuf
+ * that means: you _must_ call 
+ *
+ * IMB_cache_limiter_unref(seq->curelem->ibuf);
+ * 
+ * if seq->curelem exists!
+ * 
+ */
 
-               seq= seq->next;
+static void do_build_seq_recursively(Sequence * seq, int cfra)
+{
+       if (seq->type == SEQ_SPEED) {
+               do_handle_speed_effect(seq, cfra);
+       } else {
+               do_build_seq_recursively_impl(seq, cfra);
        }
 }
 
 ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown)
 {
-       Sequence **tseqar, **seqar;
-       Sequence *seq, *seqfirst=0;/*  , *effirst=0; */
+       Sequence *seqfirst=0;
        Editing *ed;
-       StripElem *se;
-       int seqnr, totseq, count;
+       int count;
        ListBase *seqbasep;
 
-       /* we make recursively a 'stack' of sequences, these are
-        * sorted nicely as well.
-        * this method has been developed especially for 
-        * stills before or after metas
-        */
-
-       totseq= 0;
        ed= G.scene->ed;
        if(ed==0) return 0;
 
@@ -1100,77 +1122,27 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown)
        if((chanshown < 0) && (count > 0)) {
                count = MAX2(count + chanshown, 0);
                seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep;
-       }
-       else
+       } else {
                seqbasep= ed->seqbasep;
-
-       do_seq_count_cfra(seqbasep, &totseq, cfra);
-
-       if(totseq==0) return 0;
+       }
 
        seqrectx= rectx;        /* bad bad global! */
        seqrecty= recty;
 
-       /* tseqar is needed because in do_build_... the pointer changes */
-       seqar= tseqar= MEM_callocN(sizeof(void *)*totseq, "seqar");
-
-       /* set curelem pointers to stripelem */
-       do_set_seq_curelem(seqbasep, cfra);
-
-       /* this call creates the sequence order array */
-       do_build_seqar_cfra(seqbasep, &seqar, cfra);
-
-       seqar= tseqar;
+       seqfirst = get_shown_sequence(seqbasep, cfra, chanshown);
 
-       for(seqnr=0; seqnr<totseq; seqnr++) {
-               seq= seqar[seqnr];
-
-               se= seq->curelem;
-               if((seq->type != SEQ_RAM_SOUND && seq->type != SEQ_HD_SOUND) 
-                       && (se) && (chanshown <= 0 || seq->machine == chanshown)) {
-                       if(seq->type==SEQ_META) {
-
-                               /* bottom strip! */
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine > seq->machine) seqfirst= seq;
-
-                       }
-                       else if(seq->type & SEQ_EFFECT) {
-
-                               /* top strip! */
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine < seq->machine) seqfirst= seq;
-
-
-                       }
-                       else if(seq->type < SEQ_EFFECT) {       /* images */
-
-                               /* bottom strip! a feature that allows you to store junk in locations above */
-
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine > seq->machine) seqfirst= seq;
-
-                       }
-               }
+       if (!seqfirst) {
+               return 0;
        }
 
-       MEM_freeN(seqar);
-
-       /* we know, that we have to build the ibuf of seqfirst, 
-          now build the dependencies and later the ibufs */
+       do_build_seq_recursively(seqfirst, cfra);
 
-       if (seqfirst) {
-               do_build_seq_depend(seqfirst, cfra);
-               do_build_seq_ibufs(seqbasep, cfra);
-               do_seq_unref_cfra(seqbasep, cfra);
-               do_seq_test_unref_cfra(seqbasep, cfra);
+       if(!seqfirst->curelem) { 
+               return 0;
        }
 
-       if(!seqfirst) return 0;
-       if(!seqfirst->curelem) return 0;
+       IMB_cache_limiter_unref(seqfirst->curelem->ibuf);
+
        return seqfirst->curelem->ibuf;
 
 }
@@ -1235,6 +1207,9 @@ void free_imbuf_seq()
 
                        if(seq->type==SEQ_MOVIE)
                                free_anim_seq(seq);
+                       if(seq->type==SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
+                       }
                }
        }
        END_SEQ
@@ -1249,8 +1224,12 @@ void free_imbuf_seq_with_ipo(struct Ipo *ipo)
        if(ed==0) return;
 
        WHILE_SEQ(&ed->seqbase) {
-               if(seq->ipo == ipo)
+               if(seq->ipo == ipo) {
                        update_changed_seq_and_deps(seq, 0, 1);
+                       if(seq->type == SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
+                       }
+               }
        }
        END_SEQ
 }
@@ -1290,6 +1269,9 @@ static int update_changed_seq_recurs(Sequence *seq, Sequence *changed_seq, int l
                
                        if(seq->type==SEQ_MOVIE)
                                free_anim_seq(seq);
+                       if(seq->type == SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
+                       }
                }
 
                if(len_change)