/WX enabled for MSVC in CMake too.
[blender.git] / source / blender / blenkernel / intern / sequencer.c
index 341d0a5..5950a46 100644 (file)
 #include "MEM_guardedalloc.h"
 #include "MEM_CacheLimiterC-Api.h"
 
-#include "DNA_listBase.h"
 #include "DNA_sequence_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_anim_types.h"
 #include "DNA_object_types.h"
+#include "DNA_sound_types.h"
 
+#include "BKE_animsys.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "BKE_sequencer.h"
 #include "BKE_fcurve.h"
-#include "BKE_utildefines.h"
 #include "BKE_scene.h"
 #include "RNA_access.h"
 #include "RE_pipeline.h"
 
+#include "BLI_math.h"
 #include "BLI_fileops.h"
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
@@ -61,8 +62,6 @@
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
-
-
 #include "BKE_context.h"
 #include "BKE_sound.h"
 #include "AUD_C-API.h"
@@ -72,8 +71,6 @@
 #endif
 
 /* **** XXX ******** */
-static int seqrectx= 0;        /* bad bad global! */
-static int seqrecty= 0;
 //static void waitcursor(int val) {}
 //static int blender_test_break() {return 0;}
 
@@ -91,71 +88,38 @@ void printf_strip(Sequence *seq)
        fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0));
 }
 
-void seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg)
+int seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg)
 {
        Sequence *iseq;
        for(iseq= seqbase->first; iseq; iseq= iseq->next) {
-               seq_recursive_apply(iseq, apply_func, arg);
+               if(seq_recursive_apply(iseq, apply_func, arg) == -1)
+                       return -1; /* bail out */
        }
+       return 1;
 }
 
-void seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg)
+int seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg)
 {
-       if(apply_func(seq, arg) && seq->seqbase.first)
-               seqbase_recursive_apply(&seq->seqbase, apply_func, arg);
+       int ret= apply_func(seq, arg);
+
+       if(ret == -1)
+               return -1;  /* bail out */
+
+       if(ret && seq->seqbase.first)
+               ret = seqbase_recursive_apply(&seq->seqbase, apply_func, arg);
+
+       return ret;
 }
 
 /* **********************************************************************
    alloc / free functions
    ********************************************************************** */
 
-static void free_tstripdata(int len, TStripElem *se)
-{
-       TStripElem *seo;
-       int a;
-
-       seo= se;
-       if (!se)
-               return;
-
-       for(a=0; a<len; a++, se++) {
-               if(se->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = 0;
-               }
-               if(se->ibuf_comp) {
-                       IMB_freeImBuf(se->ibuf_comp);
-                       se->ibuf_comp = 0;
-               }
-       }
-
-       MEM_freeN(seo);
-}
 
 
 void new_tstripdata(Sequence *seq)
 {
        if(seq->strip) {
-               free_tstripdata(seq->strip->len, seq->strip->tstripdata);
-               free_tstripdata(seq->strip->endstill, 
-                               seq->strip->tstripdata_endstill);
-               free_tstripdata(seq->strip->startstill, 
-                               seq->strip->tstripdata_startstill);
-
-               seq->strip->tstripdata= 0;
-               seq->strip->tstripdata_endstill= 0;
-               seq->strip->tstripdata_startstill= 0;
-
-               if(seq->strip->ibuf_startstill) {
-                       IMB_freeImBuf(seq->strip->ibuf_startstill);
-                       seq->strip->ibuf_startstill = 0;
-               }
-
-               if(seq->strip->ibuf_endstill) {
-                       IMB_freeImBuf(seq->strip->ibuf_endstill);
-                       seq->strip->ibuf_endstill = 0;
-               }
-
                seq->strip->len= seq->len;
        }
 }
@@ -201,23 +165,11 @@ void seq_free_strip(Strip *strip)
                MEM_freeN(strip->color_balance);
        }
 
-       free_tstripdata(strip->len, strip->tstripdata);
-       free_tstripdata(strip->endstill, strip->tstripdata_endstill);
-       free_tstripdata(strip->startstill, strip->tstripdata_startstill);
-
-       if(strip->ibuf_startstill) {
-               IMB_freeImBuf(strip->ibuf_startstill);
-               strip->ibuf_startstill = 0;
-       }
-
-       if(strip->ibuf_endstill) {
-               IMB_freeImBuf(strip->ibuf_endstill);
-               strip->ibuf_endstill = 0;
-       }
-
        MEM_freeN(strip);
 }
 
+static void seq_free_animdata(Scene *scene, Sequence *seq);
+
 void seq_free_sequence(Scene *scene, Sequence *seq)
 {
        if(seq->strip) seq_free_strip(seq->strip);
@@ -239,6 +191,8 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
 
                if(seq->scene_sound)
                        sound_remove_scene_sound(scene, seq->scene_sound);
+
+               seq_free_animdata(scene, seq);
        }
 
        MEM_freeN(seq);
@@ -429,7 +383,7 @@ void build_seqar(ListBase *seqbase, Sequence  ***seqar, int *totseq)
 }
 
 static void do_seq_count_cb(ListBase *seqbase, int *totseq,
-                           int (*test_func)(Sequence * seq))
+                               int (*test_func)(Sequence * seq))
 {
        Sequence *seq;
 
@@ -447,7 +401,7 @@ static void do_seq_count_cb(ListBase *seqbase, int *totseq,
 }
 
 static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
-                             int (*test_func)(Sequence * seq))
+                                 int (*test_func)(Sequence * seq))
 {
        Sequence *seq;
 
@@ -469,7 +423,7 @@ static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
 }
 
 void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
-                   int (*test_func)(Sequence * seq))
+                       int (*test_func)(Sequence * seq))
 {
        Sequence **tseqar;
 
@@ -507,6 +461,31 @@ void calc_sequence_disp(Scene *scene, Sequence *seq)
        seq_update_sound(scene, seq);
 }
 
+static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
+{
+       Sequence *seq;
+
+       /* for sound we go over full meta tree to update bounds of the sound strips,
+          since sound is played outside of evaluating the imbufs, */
+       for(seq=metaseq->seqbase.first; seq; seq=seq->next) {
+               if(seq->type == SEQ_META) {
+                       seq_update_sound_bounds_recursive(scene, seq);
+               }
+               else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
+                       if(seq->scene_sound) {
+                               int startofs = seq->startofs;
+                               int endofs = seq->endofs;
+                               if(seq->startofs + seq->start < metaseq->start + metaseq->startofs)
+                                       startofs = metaseq->start + metaseq->startofs - seq->start;
+
+                               if(seq->start + seq->len - seq->endofs > metaseq->start + metaseq->len - metaseq->endofs)
+                                       endofs = seq->start + seq->len - metaseq->start - metaseq->len + metaseq->endofs;
+                               sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, seq->start+seq->len - endofs, startofs);
+                       }
+               }
+       }
+}
+
 void calc_sequence(Scene *scene, Sequence *seq)
 {
        Sequence *seqm;
@@ -550,8 +529,8 @@ void calc_sequence(Scene *scene, Sequence *seq)
                if(seq->type==SEQ_META) {
                        seqm= seq->seqbase.first;
                        if(seqm) {
-                               min= 1000000;
-                               max= -1000000;
+                               min=  MAXFRAME * 2;
+                               max= -MAXFRAME * 2;
                                while(seqm) {
                                        if(seqm->startdisp < min) min= seqm->startdisp;
                                        if(seqm->enddisp > max) max= seqm->enddisp;
@@ -566,14 +545,18 @@ void calc_sequence(Scene *scene, Sequence *seq)
                                        new_tstripdata(seq);
                                }
                        }
+                       seq_update_sound_bounds_recursive(scene, seq);
                }
                calc_sequence_disp(scene, seq);
        }
 }
 
-void reload_sequence_new_file(Scene *scene, Sequence * seq)
+/* note: caller should run calc_sequence(scene, seq) after */
+void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
 {
        char str[FILE_MAXDIR+FILE_MAXFILE];
+       int prev_startdisp, prev_enddisp;
+       /* note: dont rename the strip, will break animation curves */
 
        if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
                  seq->type == SEQ_SOUND ||
@@ -581,17 +564,26 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
                return;
        }
 
+       if(lock_range) {
+               /* keep so we dont have to move the actual start and end points (only the data) */
+               calc_sequence_disp(scene, seq);
+               prev_startdisp= seq->startdisp;
+               prev_enddisp= seq->enddisp;
+       }
+
+
        new_tstripdata(seq);
 
        if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
-           seq->type != SEQ_IMAGE) {
+               seq->type != SEQ_IMAGE) {
                BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
-               BLI_path_abs(str, G.sce);
+               BLI_path_abs(str, G.main->name);
        }
 
        if (seq->type == SEQ_IMAGE) {
                /* Hack? */
-               int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
+               size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
+
                seq->len = olen;
                seq->len -= seq->anim_startofs;
                seq->len -= seq->anim_endofs;
@@ -626,6 +618,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
                }
                seq->strip->len = seq->len;
        } else if (seq->type == SEQ_SCENE) {
+               /* 'seq->scenenr' should be replaced with something more reliable */
                Scene * sce = G.main->scene.first;
                int nr = 1;
                
@@ -642,9 +635,6 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
                } else {
                        sce = seq->scene;
                }
-
-               BLI_strncpy(seq->name+2, sce->id.name + 2, SEQ_NAME_MAXSTR-2);
-               seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
                
                seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
                seq->len -= seq->anim_startofs;
@@ -657,6 +647,12 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
 
        free_proxy_seq(seq);
 
+       if(lock_range) {
+               seq_tx_set_final_left(seq, prev_startdisp);
+               seq_tx_set_final_right(seq, prev_enddisp);
+               seq_single_fix(seq);
+       }
+       
        calc_sequence(scene, seq);
 }
 
@@ -712,12 +708,12 @@ static int clear_scene_in_allseqs_cb(Sequence *seq, void *arg_pt)
        return 1;
 }
 
-void clear_scene_in_allseqs(Scene *scene)
+void clear_scene_in_allseqs(Main *bmain, Scene *scene)
 {
        Scene *scene_iter;
 
        /* when a scene is deleted: test all seqs */
-       for(scene_iter= G.main->scene.first; scene_iter; scene_iter= scene_iter->id.next) {
+       for(scene_iter= bmain->scene.first; scene_iter; scene_iter= scene_iter->id.next) {
                if(scene_iter != scene && scene_iter->ed) {
                        seqbase_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene);
                }
@@ -743,7 +739,7 @@ static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui)
        Sequence *seq;
        for(seq=seqbasep->first; seq; seq= seq->next) {
                if (sui->seq != seq && strcmp(sui->name_dest, seq->name+2)==0) {
-                       sprintf(sui->name_dest, "%.18s.%03d",  sui->name_src, sui->count++);
+                       sprintf(sui->name_dest, "%.17s.%03d",  sui->name_src, sui->count++); /*24 - 2 for prefix, -1 for \0 */
                        sui->match= 1; /* be sure to re-scan */
                }
        }
@@ -764,12 +760,17 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq)
        strcpy(sui.name_src, seq->name+2);
        strcpy(sui.name_dest, seq->name+2);
 
+       sui.count= 1;
+       sui.match= 1; /* assume the worst to start the loop */
+
        /* Strip off the suffix */
-       if ((dot=strrchr(sui.name_src, '.')))
+       if ((dot=strrchr(sui.name_src, '.'))) {
                *dot= '\0';
+               dot++;
 
-       sui.count= 1;
-       sui.match= 1; /* assume the worst to start the loop */
+               if(*dot)
+                       sui.count= atoi(dot) + 1;
+       }
 
        while(sui.match) {
                sui.match= 0;
@@ -800,6 +801,7 @@ static char *give_seqname_by_type(int type)
        case SEQ_GLOW:       return "Glow";
        case SEQ_TRANSFORM:  return "Transform";
        case SEQ_COLOR:      return "Color";
+       case SEQ_MULTICAM:   return "Multicam";
        case SEQ_SPEED:      return "Speed";
        default:
                return 0;
@@ -891,143 +893,16 @@ static void multibuf(ImBuf *ibuf, float fmul)
        }
 }
 
-static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se)
-{
-       TStripElem *se1, *se2, *se3;
-       float fac, facf;
-       int x, y;
-       int early_out;
-       struct SeqEffectHandle sh = get_sequence_effect(seq);
-       FCurve *fcu= NULL;
-
-       if (!sh.execute) { /* effect not supported in this version... */
-               make_black_ibuf(se->ibuf);
-               return;
-       }
-
-       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
-               sh.get_default_fac(seq, cfra, &fac, &facf);
-               if( scene->r.mode & R_FIELDS ); else facf= fac;
-       } else {
-               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
-                                         "effect_fader", 0);
-               if (fcu) {
-                       fac = facf = evaluate_fcurve(fcu, cfra);
-                       if( scene->r.mode & R_FIELDS ) {
-                               facf = evaluate_fcurve(fcu, cfra + 0.5);
-                       }
-               } else {
-                       fac = facf = seq->effect_fader;
-               }
-       }
-
-       early_out = sh.early_out(seq, fac, facf);
-
-       if (early_out == -1) { /* no input needed */
-               sh.execute(scene, seq, cfra, fac, facf, 
-                          se->ibuf->x, se->ibuf->y, 
-                          0, 0, 0, se->ibuf);
-               return;
-       }
-
-       switch (early_out) {
-       case 0:
-               if (se->se1==0 || se->se2==0 || se->se3==0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se1= se->se1;
-               se2= se->se2;
-               se3= se->se3;
-
-               if (   (se1==0 || se2==0 || se3==0)
-                   || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               break;
-       case 1:
-               if (se->se1 == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se1= se->se1;
-
-               if (se1 == 0 || se1->ibuf == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               if (se->ibuf != se1->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = se1->ibuf;
-                       IMB_refImBuf(se->ibuf);
-               }
-               return;
-       case 2:
-               if (se->se2 == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se2= se->se2;
-
-               if (se2 == 0 || se2->ibuf == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-               if (se->ibuf != se2->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = se2->ibuf;
-                       IMB_refImBuf(se->ibuf);
-               }
-               return;
-       default:
-               make_black_ibuf(se->ibuf);
-               return;
-       }
-
-       x= se2->ibuf->x;
-       y= se2->ibuf->y;
-
-       if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect(se1->ibuf);
-       }
-       if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect(se2->ibuf);
-       }
-       if (!se3->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect(se3->ibuf);
-       }
-       
-       if (!se1->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se1->ibuf);
-       }
-       if (!se2->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se2->ibuf);
-       }
-       if (!se3->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se3->ibuf);
-       }
-
-       sh.execute(scene, seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
-                  se->ibuf);
-}
-
-static int give_stripelem_index(Sequence *seq, int cfra)
+static float give_stripelem_index(Sequence *seq, float cfra)
 {
-       int nr;
+       float nr;
 
-       if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1;
        if(seq->len == 0) return -1;
        if(seq->flag&SEQ_REVERSE_FRAMES) {      
                /*reverse frame in this sequence */
                if(cfra <= seq->start) nr= seq->len-1;
                else if(cfra >= seq->start+seq->len-1) nr= 0;
-               else nr= (seq->start + seq->len) - cfra;
+               else nr= (seq->start + seq->len - 1) - cfra;
        } else {
                if(cfra <= seq->start) nr= 0;
                else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
@@ -1035,93 +910,12 @@ static int give_stripelem_index(Sequence *seq, int cfra)
        }
        if (seq->strobe < 1.0) seq->strobe = 1.0;
        if (seq->strobe > 1.0) {
-               nr -= (int)fmod((double)nr, (double)seq->strobe);
+               nr -= fmod((double)nr, (double)seq->strobe);
        }
 
        return nr;
 }
 
-static TStripElem* alloc_tstripdata(int len, const char * name)
-{
-       int i;
-       TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name);
-       for (i = 0; i < len; i++) {
-               se[i].ok = STRIPELEM_OK;
-       }
-       return se;
-}
-
-static TStripElem *give_tstripelem(Sequence *seq, int cfra)
-{
-       TStripElem *se;
-       int nr;
-
-       se = seq->strip->tstripdata;
-       if (se == 0 && seq->len > 0) {
-               se = seq->strip->tstripdata = alloc_tstripdata(seq->len,
-                                                              "tstripelems");
-       }
-       nr = give_stripelem_index(seq, cfra);
-
-       if (nr == -1) return 0;
-       if (se == 0) return 0;
-
-       se += nr; 
-
-       /* if there are IPOs with blend modes active, one has to watch out
-          for startstill + endstill area: we can't use the same tstripelem
-          here for all ibufs, since then, blending with IPOs won't work!
-          
-          Rather common case, if you use a single image and try to fade
-          it in and out... or want to use your strip as a watermark in
-          alpha over mode...
-       */
-       if (seq->blend_mode != SEQ_BLEND_REPLACE ||
-           (/*seq->ipo && seq->ipo->curve.first &&*/ 
-                  (!(seq->type & SEQ_EFFECT) || !seq->seq1))) {
-               Strip * s = seq->strip;
-               if (cfra < seq->start) {
-                       se = s->tstripdata_startstill;
-                       if (seq->startstill > s->startstill) {
-                               free_tstripdata(s->startstill, 
-                                               s->tstripdata_startstill);
-                               se = 0;
-                       }
-
-                       if (se == 0) {
-                               s->startstill = seq->startstill;
-                               se = seq->strip->tstripdata_startstill
-                                       = alloc_tstripdata(
-                                               s->startstill,
-                                               "tstripelems_startstill");
-                       }
-                       se += seq->start - cfra - 1;
-
-               } else if (cfra > seq->start + seq->len-1) {
-                       se = s->tstripdata_endstill;
-                       if (seq->endstill > s->endstill) {
-                               free_tstripdata(s->endstill, 
-                                               s->tstripdata_endstill);
-                               se = 0;
-                       }
-
-                       if (se == 0) {
-                               s->endstill = seq->endstill;
-                               se = seq->strip->tstripdata_endstill
-                                       = alloc_tstripdata(
-                                               s->endstill,
-                                               "tstripelems_endstill");
-                       }
-                       se += cfra - (seq->start + seq->len-1) - 1;
-               }
-       }
-
-       
-       se->nr= nr;
-
-       return se;
-}
-
 StripElem *give_stripelem(Sequence *seq, int cfra)
 {
        StripElem *se= seq->strip->stripdata;
@@ -1130,7 +924,7 @@ StripElem *give_stripelem(Sequence *seq, int cfra)
                /* use the first */
        }
        else {
-               int nr = give_stripelem_index(seq, cfra);
+               int nr = (int) give_stripelem_index(seq, cfra);
 
                if (nr == -1) return 0;
                if (se == 0) return 0;
@@ -1209,7 +1003,7 @@ static int get_shown_sequences(   ListBase * seqbasep, int cfra, int chanshown, Se
                }
        }
 
-       for (;b <= chanshown; b++) {
+       for (;b <= chanshown && b >= 0; b++) {
                if (video_seq_is_rendered(seq_arr[b])) {
                        seq_arr_out[cnt++] = seq_arr[b];
                }
@@ -1225,7 +1019,7 @@ static int get_shown_sequences(   ListBase * seqbasep, int cfra, int chanshown, Se
 
 #define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 
-static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size)
+static int seq_proxy_get_fname(Scene *UNUSED(scene), Sequence * seq, int cfra, char * name, int render_size)
 {
        int frameno;
        char dir[FILE_MAXDIR];
@@ -1234,7 +1028,8 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
                return FALSE;
        }
 
-       if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
+       if ((seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)
+           || (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)) {
                strcpy(dir, seq->strip->proxy->dir);
        } else {
                if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
@@ -1247,7 +1042,7 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
                BLI_join_dirfile(name, dir, seq->strip->proxy->file);
-               BLI_path_abs(name, G.sce);
+               BLI_path_abs(name, G.main->name);
 
                return TRUE;
        }
@@ -1260,23 +1055,21 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
                         dir, render_size, se->name);
                frameno = 1;
        } else if (seq->type == SEQ_MOVIE) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-
-               frameno = tse->nr + seq->anim_startofs;
+               frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
 
                snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
                         seq->strip->stripdata->name,
                         render_size);
        } else {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-
-               frameno = tse->nr + seq->anim_startofs;
+               frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
 
                snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
                         render_size);
        }
 
-       BLI_path_abs(name, G.sce);
+       BLI_path_abs(name, G.main->name);
        BLI_path_frame(name, frameno, 0);
 
 
@@ -1299,10 +1092,11 @@ static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, in
        }
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-               int frameno = tse->nr + seq->anim_startofs;
+               int frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
                if (!seq->strip->proxy->anim) {
-                       if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
+                       if (!seq_proxy_get_fname(
+                                   scene, seq, cfra, name, render_size)) {
                                return 0;
                        }
  
@@ -1328,9 +1122,9 @@ static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, in
 
 #if 0
 static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
-                             int build_proxy_run, int render_size);
+                                 int build_proxy_run, int render_size);
 
-static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size)
+static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
 {
        char name[PROXY_MAXFILE];
        int quality;
@@ -1351,7 +1145,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
        /* that's why it is called custom... */
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
                return;
-    }
+       }
 
        if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
                return;
@@ -1367,7 +1161,8 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
                se->ibuf = 0;
        }
        
-       do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size);
+       do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size,
+                         seqrectx, seqrecty);
 
        if (!se->ibuf) {
                return;
@@ -1401,7 +1196,8 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re
        se->ibuf = 0;
 }
 
-static void seq_proxy_rebuild(Scene *scene, Sequence * seq)
+static void seq_proxy_rebuild(Scene *scene, Sequence * seq, int seqrectx,
+                             int seqrecty)
 {
        int cfra;
        float rsize = seq->strip->proxy->size;
@@ -1428,12 +1224,13 @@ static void seq_proxy_rebuild(Scene *scene, Sequence * seq)
           sequential order */
        if (seq->flag & SEQ_REVERSE_FRAMES) {
                for (cfra = seq->enddisp-seq->endstill-1; 
-                    cfra >= seq->startdisp + seq->startstill; cfra--) {
+                        cfra >= seq->startdisp + seq->startstill; cfra--) {
                        TStripElem * tse = give_tstripelem(seq, cfra);
 
                        if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
 //XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize);
+                               seq_proxy_build_frame(scene, seq, cfra, rsize,
+                                                     seqrectx, seqrecty);
                                tse->flag |= STRIPELEM_PREVIEW_DONE;
                        }
                        if (blender_test_break()) {
@@ -1442,12 +1239,13 @@ static void seq_proxy_rebuild(Scene *scene, Sequence * seq)
                }
        } else {
                for (cfra = seq->startdisp + seq->startstill; 
-                    cfra < seq->enddisp - seq->endstill; cfra++) {
+                        cfra < seq->enddisp - seq->endstill; cfra++) {
                        TStripElem * tse = give_tstripelem(seq, cfra);
 
                        if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
 //XXX                          set_timecursor(cfra);
-                               seq_proxy_build_frame(scene, seq, cfra, rsize);
+                               seq_proxy_build_frame(scene, seq, cfra, rsize,
+                                                     seqrectx, seqrecty);
                                tse->flag |= STRIPELEM_PREVIEW_DONE;
                        }
                        if (blender_test_break()) {
@@ -1469,15 +1267,21 @@ static StripColorBalance calc_cb(StripColorBalance * cb_)
        StripColorBalance cb = *cb_;
        int c;
 
-       if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
-               for (c = 0; c < 3; c++) {
-                       cb.lift[c] = 1.0 - cb.lift[c];
-               }
-       } else {
+       for (c = 0; c < 3; c++) {
+               cb.lift[c] = 2.0f - cb.lift[c];
+       }
+
+       if(cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
                for (c = 0; c < 3; c++) {
-                       cb.lift[c] = -(1.0 - cb.lift[c]);
+                       /* tweak to give more subtle results
+                        * values above 1.0 are scaled */
+                       if(cb.lift[c] > 1.0f)
+                               cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0f) + 1.0f;
+
+                       cb.lift[c] = 2.0f - cb.lift[c];
                }
        }
+
        if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
                for (c = 0; c < 3; c++) {
                        if (cb.gain[c] != 0.0) {
@@ -1501,25 +1305,27 @@ static StripColorBalance calc_cb(StripColorBalance * cb_)
        return cb;
 }
 
+/* note: lift is actually 2-lift */
+MINLINE float color_balance_fl(float in, const float lift, const float gain, const float gamma, const float mul)
+{
+       float x= (((in - 1.0f) * lift) + 1.0f) * gain;
+
+       /* prevent NaN */
+       if (x < 0.f) x = 0.f;
+
+       return powf(x, gamma) * mul;
+}
+
 static void make_cb_table_byte(float lift, float gain, float gamma,
-                              unsigned char * table, float mul)
+                                  unsigned char * table, float mul)
 {
        int y;
 
        for (y = 0; y < 256; y++) {
-               float v = 1.0 * y / 255;
-               v *= gain;
-               v += lift; 
-               v = pow(v, gamma);
-               v *= mul;
-               if ( v > 1.0) {
-                       v = 1.0;
-               } else if (v < 0.0) {
-                       v = 0.0;
-               }
+               float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul);
+               CLAMP(v, 0.0f, 1.0f);
                table[y] = v * 255;
        }
-
 }
 
 static void make_cb_table_float(float lift, float gain, float gamma,
@@ -1528,21 +1334,17 @@ static void make_cb_table_float(float lift, float gain, float gamma,
        int y;
 
        for (y = 0; y < 256; y++) {
-               float v = (float) y * 1.0 / 255.0;
-               v *= gain;
-               v += lift;
-               v = pow(v, gamma);
-               v *= mul;
+               float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul);
                table[y] = v;
        }
 }
 
-static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_byte_byte(Sequence * seq, ImBuf* ibuf, float mul)
 {
        unsigned char cb_tab[3][256];
        int c;
-       unsigned char * p = (unsigned char*) se->ibuf->rect;
-       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+       unsigned char * p = (unsigned char*) ibuf->rect;
+       unsigned char * e = p + ibuf->x * 4 * ibuf->y;
 
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
@@ -1560,18 +1362,18 @@ static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
        }
 }
 
-static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul)
 {
        float cb_tab[4][256];
        int c,i;
-       unsigned char * p = (unsigned char*) se->ibuf->rect;
-       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+       unsigned char * p = (unsigned char*) ibuf->rect;
+       unsigned char * e = p + ibuf->x * 4 * ibuf->y;
        float * o;
        StripColorBalance cb;
 
-       imb_addrectfloatImBuf(se->ibuf);
+       imb_addrectfloatImBuf(ibuf);
 
-       o = se->ibuf->rect_float;
+       o = ibuf->rect_float;
 
        cb = calc_cb(seq->strip->color_balance);
 
@@ -1594,30 +1396,29 @@ static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
        }
 }
 
-static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_float_float(Sequence * seq, ImBuf* ibuf, float mul)
 {
-       float * p = se->ibuf->rect_float;
-       float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y;
+       float * p = ibuf->rect_float;
+       float * e = ibuf->rect_float + ibuf->x * 4* ibuf->y;
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
        while (p < e) {
                int c;
                for (c = 0; c < 3; c++) {
-                       p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], 
-                                  cb.gamma[c]) * mul;
+                       p[c]= color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
                }
                p += 4;
        }
 }
 
-static void color_balance(Sequence * seq, TStripElem* se, float mul)
+static void color_balance(Sequence * seq, ImBuf* ibuf, float mul)
 {
-       if (se->ibuf->rect_float) {
-               color_balance_float_float(seq, se, mul);
+       if (ibuf->rect_float) {
+               color_balance_float_float(seq, ibuf, mul);
        } else if(seq->flag & SEQ_MAKE_FLOAT) {
-               color_balance_byte_float(seq, se, mul);
+               color_balance_byte_float(seq, ibuf, mul);
        } else {
-               color_balance_byte_byte(seq, se, mul);
+               color_balance_byte_byte(seq, ibuf, mul);
        }
 }
 
@@ -1634,13 +1435,14 @@ static void color_balance(Sequence * seq, TStripElem* se, float mul)
   - Flip X + Flip Y (could be done afterwards, backward compatibility)
   - Promote image to float data (affects pipeline operations afterwards)
   - Color balance (is most efficient in the byte -> float 
-    (future: half -> float should also work fine!)
-    case, if done on load, since we can use lookup tables)
+       (future: half -> float should also work fine!)
+       case, if done on load, since we can use lookup tables)
   - Premultiply
 
 */
 
-static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra)
+int input_have_to_preprocess(
+       Scene *UNUSED(scene), Sequence * seq, float UNUSED(cfra), int UNUSED(seqrectx), int UNUSED(seqrecty))
 {
        float mul;
 
@@ -1650,34 +1452,38 @@ static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se
            (seq->flag & SEQ_FLIPX) ||
            (seq->flag & SEQ_FLIPY) ||
            (seq->flag & SEQ_USE_COLOR_BALANCE) ||
-           (seq->flag & SEQ_MAKE_PREMUL) ||
-           (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) {
+           (seq->flag & SEQ_MAKE_PREMUL)) {
                return TRUE;
        }
 
        mul = seq->mul;
 
-       if(seq->blend_mode == SEQ_BLEND_REPLACE &&
-          !(seq->type & SEQ_EFFECT)) {
+       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
                mul *= seq->blend_opacity / 100.0;
        }
 
        if (mul != 1.0) {
                return TRUE;
        }
+
+       if (seq->sat != 1.0) {
+               return TRUE;
+       }
                
        return FALSE;
 }
 
-static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
+static ImBuf * input_preprocess(
+       Scene *scene, Sequence *seq, float UNUSED(cfra), int seqrectx, int seqrecty,
+       ImBuf * ibuf)
 {
        float mul;
 
-       seq->strip->orx= se->ibuf->x;
-       seq->strip->ory= se->ibuf->y;
+       seq->strip->orx= ibuf->x;
+       seq->strip->ory= ibuf->y;
 
        if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
-               IMB_filtery(se->ibuf);
+               IMB_filtery(ibuf);
        }
 
        if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
@@ -1695,8 +1501,8 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
                        t = *seq->strip->transform;
                }
 
-               sx = se->ibuf->x - c.left - c.right;
-               sy = se->ibuf->y - c.top - c.bottom;
+               sx = ibuf->x - c.left - c.right;
+               sy = ibuf->y - c.top - c.bottom;
                dx = sx;
                dy = sy;
 
@@ -1705,39 +1511,62 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
                        dy = scene->r.ysch;
                }
 
-               if (c.top + c.bottom >= se->ibuf->y ||
-                   c.left + c.right >= se->ibuf->x ||
-                   t.xofs >= dx || t.yofs >= dy) {
-                       make_black_ibuf(se->ibuf);
+               if (c.top + c.bottom >= ibuf->y ||
+                       c.left + c.right >= ibuf->x ||
+                       t.xofs >= dx || t.yofs >= dy) {
+                       make_black_ibuf(ibuf);
                } else {
                        ImBuf * i;
 
-                       if (se->ibuf->rect_float) {
-                               i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
+                       if (ibuf->rect_float) {
+                               i = IMB_allocImBuf(dx, dy,32, IB_rectfloat);
                        } else {
-                               i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
+                               i = IMB_allocImBuf(dx, dy,32, IB_rect);
                        }
 
-                       IMB_rectcpy(i, se->ibuf, 
+                       IMB_rectcpy(i, ibuf, 
                                    t.xofs, t.yofs, 
                                    c.left, c.bottom, 
                                    sx, sy);
+                       
+                       IMB_freeImBuf(ibuf);
 
-                       IMB_freeImBuf(se->ibuf);
-
-                       se->ibuf = i;
+                       ibuf = i;
                }
        } 
 
        if(seq->flag & SEQ_FLIPX) {
-               IMB_flipx(se->ibuf);
+               IMB_flipx(ibuf);
        }
+       
        if(seq->flag & SEQ_FLIPY) {
-               IMB_flipy(se->ibuf);
+               IMB_flipy(ibuf);
        }
 
-       if(seq->mul == 0.0) {
-               seq->mul = 1.0;
+       if(seq->sat != 1.0f) {
+               /* inline for now, could become an imbuf function */
+               int i;
+               char *rct= (char *)ibuf->rect;
+               float *rctf= ibuf->rect_float;
+               const float sat= seq->sat;
+               float hsv[3];
+
+               if(rct) {
+                       float rgb[3];
+                       for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
+                               rgb_byte_to_float(rct, rgb);
+                               rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
+                               hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2);
+                               rgb_float_to_byte(rgb, rct);
+                       }
+               }
+
+               if(rctf) {
+                       for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
+                               rgb_to_hsv(rctf[0], rctf[1], rctf[2], hsv, hsv+1, hsv+2);
+                               hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf+1, rctf+2);
+                       }
+               }
        }
 
        mul = seq->mul;
@@ -1747,941 +1576,714 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
        }
 
        if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
-               color_balance(seq, se, mul);
+               color_balance(seq, ibuf, mul);
                mul = 1.0;
        }
 
        if(seq->flag & SEQ_MAKE_FLOAT) {
-               if (!se->ibuf->rect_float) {
-                       if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                               IMB_float_from_rect(se->ibuf);
-                       } else {
-                               int profile = IB_PROFILE_NONE;
-                               
-                               /* no color management:
-                                * don't disturb the existing profiles */
-                               SWAP(int, se->ibuf->profile, profile);
-
-                               IMB_float_from_rect(se->ibuf);
-                               
-                               SWAP(int, se->ibuf->profile, profile);
-                       }
-               }
-               if (se->ibuf->rect) {
-                       imb_freerectImBuf(se->ibuf);
+               if (!ibuf->rect_float)
+                       IMB_float_from_rect_simple(ibuf);
+
+               if (ibuf->rect) {
+                       imb_freerectImBuf(ibuf);
                }
        }
 
        if(mul != 1.0) {
-               multibuf(se->ibuf, mul);
+               multibuf(ibuf, mul);
        }
 
        if(seq->flag & SEQ_MAKE_PREMUL) {
-               if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
-                       converttopremul(se->ibuf);
+               if(ibuf->depth == 32 && ibuf->zbuf == 0) {
+                       IMB_premultiply_alpha(ibuf);
                }
        }
 
 
-       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+       if(ibuf->x != seqrectx || ibuf->y != seqrecty ) {
                if(scene->r.mode & R_OSA) {
-                       IMB_scaleImBuf(se->ibuf, 
+                       IMB_scaleImBuf(ibuf, 
                                       (short)seqrectx, (short)seqrecty);
                } else {
-                       IMB_scalefastImBuf(se->ibuf, 
+                       IMB_scalefastImBuf(ibuf, 
                                           (short)seqrectx, (short)seqrecty);
                }
        }
+       return ibuf;
 }
 
-/* test if image too small or discarded from cache: reload */
-
-static void test_and_auto_discard_ibuf(TStripElem * se)
+static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
+                                   int seqrectx, int seqrecty)
 {
-       if (se->ibuf) {
-               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
-                  || !(se->ibuf->rect || se->ibuf->rect_float)) {
-                       IMB_freeImBuf(se->ibuf);
+       ImBuf * rval = 0;
+       ImBuf * ibuf = 0;
 
-                       se->ibuf= 0;
-                       se->ok= STRIPELEM_OK;
-               }
+       if (nr == 0) {
+               ibuf = seq_stripelem_cache_get(
+                       seq, seqrectx, seqrecty, seq->start, 
+                       SEQ_STRIPELEM_IBUF_STARTSTILL);
+       }
+       if (nr == seq->len - 1) {
+               ibuf = seq_stripelem_cache_get(
+                       seq, seqrectx, seqrecty, seq->start, 
+                       SEQ_STRIPELEM_IBUF_ENDSTILL);
        }
-       if (se->ibuf_comp) {
-               if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty 
-                  || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) {
-                       IMB_freeImBuf(se->ibuf_comp);
 
-                       se->ibuf_comp = 0;
-               }
+       if (ibuf) {
+               rval = IMB_dupImBuf(ibuf);
+               IMB_freeImBuf(ibuf);
        }
+
+       return rval;
 }
 
-static void test_and_auto_discard_ibuf_stills(Strip * strip)
+static void copy_to_ibuf_still(Sequence * seq, float nr,
+                              ImBuf * ibuf)
 {
-       if (strip->ibuf_startstill) {
-               if (!strip->ibuf_startstill->rect &&
-                   !strip->ibuf_startstill->rect_float) {
-                       IMB_freeImBuf(strip->ibuf_startstill);
-                       strip->ibuf_startstill = 0;
-               }
+       if (nr == 0) {
+               seq_stripelem_cache_put(
+                       seq, 0, 0, seq->start, 
+                       SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
        }
-       if (strip->ibuf_endstill) {
-               if (!strip->ibuf_endstill->rect &&
-                   !strip->ibuf_endstill->rect_float) {
-                       IMB_freeImBuf(strip->ibuf_endstill);
-                       strip->ibuf_endstill = 0;
-               }
+       if (nr == seq->len - 1) {
+               seq_stripelem_cache_put(
+                       seq, 0, 0, seq->start, 
+                       SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
        }
 }
 
-static void copy_from_ibuf_still(Sequence * seq, TStripElem * se)
-{
-       if (!se->ibuf) {
-               if (se->nr == 0 && seq->strip->ibuf_startstill) {
-                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
-
-                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill);
-               }
-               if (se->nr == seq->len - 1 
-                   && (seq->len != 1)
-                   && seq->strip->ibuf_endstill) {
-                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
-
-                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
-               }
-       }
-}
+/* **********************************************************************
+   strip rendering functions
+   ********************************************************************** */
 
-static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
-{
-       if (se->ibuf) {
-               if (se->nr == 0) {
-                       seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
+static ImBuf* seq_render_strip_stack(
+       Main *bmain, Scene *scene,
+       ListBase *seqbasep, float cfra, int chanshown, int render_size,
+       int seqrectx, int seqrecty);
 
-                       IMB_cache_limiter_insert(seq->strip->ibuf_startstill);
-                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
-               }
-               if (se->nr == seq->len - 1 && seq->len != 1) {
-                       seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf);
+static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
+                               int render_size, 
+                               int seqrectx, int seqrecty);
 
-                       IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
-                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
-               }
-       }
-}
 
-static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
+static ImBuf* seq_render_effect_strip_impl(
+       Main *bmain, Scene *scene, float cfra, Sequence *seq, int render_size,
+       int seqrectx, int seqrecty)
 {
-       Sequence* seq_arr[MAXSEQ+1];
+       float fac, facf;
+       int early_out;
        int i;
-       TStripElem* se = 0;
-
-       evaluate_seq_frame_gen(seq_arr, seqbasep, cfra);
+       int must_preprocess = FALSE;
 
-       for (i = 0; i < MAXSEQ; i++) {
-               if (!video_seq_is_rendered(seq_arr[i])) {
-                       continue;
-               }
-               se = give_tstripelem(seq_arr[i], cfra);
-               if (se) {
-                       if (se->ibuf) {
-                               IMB_freeImBuf(se->ibuf);
-
-                               se->ibuf= 0;
-                               se->ok= STRIPELEM_OK;
-                       }
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
+       FCurve *fcu= NULL;
+       ImBuf * ibuf[3];
+       ImBuf * out = 0;
 
-                       if (se->ibuf_comp) {
-                               IMB_freeImBuf(se->ibuf_comp);
+       ibuf[0] = ibuf[1] = ibuf[2] = 0;
 
-                               se->ibuf_comp = 0;
-                       }
-               }
+       if (!sh.execute) { /* effect not supported in this version... */
+               goto finish;
        }
-       
-}
 
-static void check_limiter_refcount(const char * func, TStripElem *se)
-{
-       if (se && se->ibuf) {
-               int refcount = IMB_cache_limiter_get_refcount(se->ibuf);
-               if (refcount != 1) {
-                       /* can happen on complex pipelines */
-                       if (refcount > 1 && (G.f & G_DEBUG) == 0) {
-                               return;
-                       }
-                       fprintf(stderr, 
-                               "sequencer: (ibuf) %s: "
-                               "suspicious memcache "
-                               "limiter refcount: %d\n", func, refcount);
-               }
-       }
-}
-static void check_limiter_refcount_comp(const char * func, TStripElem *se)
-{
-       if (se && se->ibuf_comp) {
-               int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp);
-               if (refcount != 1) {
-                       /* can happen on complex pipelines */
-                       if (refcount > 1 && (G.f & G_DEBUG) == 0) {
-                               return;
+       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+               if( scene->r.mode & R_FIELDS ); else facf= fac;
+       } else {
+               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
+                                         "effect_fader", 0);
+               if (fcu) {
+                       fac = facf = evaluate_fcurve(fcu, cfra);
+                       if( scene->r.mode & R_FIELDS ) {
+                               facf = evaluate_fcurve(fcu, cfra + 0.5);
                        }
-                       fprintf(stderr, 
-                               "sequencer: (ibuf comp) %s: "
-                               "suspicious memcache "
-                               "limiter refcount: %d\n", func, refcount);
+               } else {
+                       fac = facf = seq->effect_fader;
                }
        }
-}
 
-static TStripElem* do_build_seq_array_recursively(Scene *scene,
-                               ListBase *seqbasep, int cfra, int chanshown, int render_size);
+       early_out = sh.early_out(seq, fac, facf);
 
-static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
-                             int build_proxy_run, int render_size)
-{
-       char name[FILE_MAXDIR+FILE_MAXFILE];
-       int use_limiter = TRUE;
-
-       test_and_auto_discard_ibuf(se);
-       test_and_auto_discard_ibuf_stills(seq->strip);
-
-       if(seq->type == SEQ_META) {
-               TStripElem * meta_se = 0;
-               int use_preprocess = FALSE;
-               use_limiter = FALSE;
-
-               if (!build_proxy_run && se->ibuf == 0) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               use_limiter = TRUE;
-                               use_preprocess = TRUE;
-                       }
-               }
-
-               if(!se->ibuf && seq->seqbase.first) {
-                       meta_se = do_build_seq_array_recursively(scene,
-                               &seq->seqbase, seq->start + se->nr, 0,
-                               render_size);
-
-                       check_limiter_refcount("do_build_seq_ibuf: for META", meta_se);
-               }
-
-               se->ok = STRIPELEM_OK;
-
-               if(!se->ibuf && meta_se) {
-                       se->ibuf = meta_se->ibuf_comp;
-                       if(se->ibuf &&
-                          (!input_have_to_preprocess(scene, seq, se, cfra) ||
-                           build_proxy_run)) {
-                               IMB_refImBuf(se->ibuf);
-                               if (build_proxy_run) {
-                                       IMB_cache_limiter_unref(se->ibuf);
-                               }
-                       } else if (se->ibuf) {
-                               struct ImBuf * i = IMB_dupImBuf(se->ibuf);
-
-                               IMB_cache_limiter_unref(se->ibuf);
+       if (early_out == -1) { /* no input needed */
+               out = sh.execute(bmain, scene, seq, cfra, fac, facf, 
+                                seqrectx, seqrecty, render_size,
+                                0, 0, 0);
+               goto finish;
+       }
 
-                               se->ibuf = i;
 
-                               use_limiter = TRUE;
-                               use_preprocess = TRUE;
-                       }
-               } else if (se->ibuf) {
-                       use_limiter = TRUE;
-               }
-               if (meta_se) {
-                       free_metastrip_imbufs(
-                               &seq->seqbase, seq->start + se->nr, 0);
-               }
+       must_preprocess = input_have_to_preprocess(
+               scene, seq, cfra, seqrectx, seqrecty);
 
-               if (use_preprocess) {
-                       input_preprocess(scene, seq, se, cfra);
-               }
-       } else if(seq->type & SEQ_EFFECT) {
-               int use_preprocess = FALSE;
-               /* should the effect be recalculated? */
-               
-               if (!build_proxy_run && se->ibuf == 0) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               use_preprocess = TRUE;
-                       }
+       switch (early_out) {
+       case 0:
+               break;
+       case 1:
+               if (seq->seq1) {
+                       ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
+                                                  render_size, 
+                                                  seqrectx, seqrecty);
                }
-
-               if(se->ibuf == 0) {
-                       /* if any 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->se3 && se->se3->ibuf && se->se3->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(scene, cfra, seq, se);
-                       if (input_have_to_preprocess(scene, seq, se, cfra) &&
-                           !build_proxy_run) {
-                               if ((se->se1 && (se->ibuf == se->se1->ibuf)) ||
-                                   (se->se2 && (se->ibuf == se->se2->ibuf))) {
-                                       struct ImBuf * i
-                                               = IMB_dupImBuf(se->ibuf);
-
-                                       IMB_freeImBuf(se->ibuf);
-
-                                       se->ibuf = i;
-                               }
-                               use_preprocess = TRUE;
+               if (ibuf[0]) {
+                       if (must_preprocess) {
+                               out = IMB_dupImBuf(ibuf[0]);
+                       } else {
+                               out = ibuf[0];
+                               IMB_refImBuf(out);
                        }
                }
-               if (use_preprocess) {
-                       input_preprocess(scene, seq, se, cfra);
-               }
-       } else if(seq->type == SEQ_IMAGE) {
-               if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
-                       StripElem * s_elem = give_stripelem(seq, cfra);
-                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
-                       BLI_path_abs(name, G.sce);
-                       if (!build_proxy_run) {
-                               se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       }
-                       copy_from_ibuf_still(seq, se);
-
-                       if (!se->ibuf) {
-                               se->ibuf= IMB_loadiffname(
-                                       name, IB_rect);
-                               /* we don't need both (speed reasons)! */
-                               if (se->ibuf &&
-                                       se->ibuf->rect_float && se->ibuf->rect) {
-                                       imb_freerectImBuf(se->ibuf);
-                               }
-
-                               copy_to_ibuf_still(seq, se);
-                       }
-                       
-                       if(se->ibuf == 0) {
-                               se->ok = STRIPELEM_FAILED;
-                       } else if (!build_proxy_run) {
-                               input_preprocess(scene, seq, se, cfra);
+               goto finish;
+       case 2:
+               if (seq->seq2) {
+                       ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
+                                                  render_size, 
+                                                  seqrectx, seqrecty);
+               }
+               if (ibuf[1]) {
+                       if (must_preprocess) {
+                               out = IMB_dupImBuf(ibuf[1]);
+                       } else {
+                               out = ibuf[1];
+                               IMB_refImBuf(out);
                        }
                }
-       } else if(seq->type == SEQ_MOVIE) {
-               if(se->ok == STRIPELEM_OK && se->ibuf==0) {
-                       if(!build_proxy_run) {
-                               se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       }
-                       copy_from_ibuf_still(seq, se);
+               goto finish;
+       default:
+               goto finish;
+       }
 
-                       if (se->ibuf == 0) {
-                               if(seq->anim==0) {
-                                       BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name);
-                                       BLI_path_abs(name, G.sce);
-                                       
-                                       seq->anim = openanim(
-                                               name, IB_rect | 
-                                               ((seq->flag & SEQ_FILTERY) 
-                                                ? IB_animdeinterlace : 0));
-                               }
-                               if(seq->anim) {
-                                       IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
-                                       se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
-                                       /* we don't need both (speed reasons)! */
-                                       if (se->ibuf 
-                                           && se->ibuf->rect_float 
-                                           && se->ibuf->rect) {
-                                               imb_freerectImBuf(se->ibuf);
-                                       }
+       if (seq->seq1) {
+               ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       } 
 
-                               }
-                               copy_to_ibuf_still(seq, se);
-                       }
-                       
-                       if(se->ibuf == 0) {
-                               se->ok = STRIPELEM_FAILED;
-                       } else if (!build_proxy_run) {
-                               input_preprocess(scene, seq, se, cfra);
-                       }
-               }
-       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
-               Scene *sce= seq->scene;// *oldsce= scene;
-               int have_seq= FALSE;
-               int sce_valid= FALSE;
+       if (seq->seq2) {
+               ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       }
 
-               if(sce) {
-                       have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first;
-                       sce_valid= (sce->camera || have_seq);
-               }
+       if (seq->seq3) {
+               ibuf[2] = seq_render_strip(bmain, scene, seq->seq3, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       }
 
-               if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               input_preprocess(scene, seq, se, cfra);
-                       }
-               }
+       if (!ibuf[0] || !ibuf[1]) {
+               goto finish;
+       }
 
-               if (se->ibuf == NULL && sce_valid) {
-                       copy_from_ibuf_still(seq, se);
-                       if (se->ibuf) {
-                               input_preprocess(scene, seq, se, cfra);
-                       }
-               }
-               
-               if (!sce_valid) {
-                       se->ok = STRIPELEM_FAILED;
-               }
-               else if (se->ibuf==NULL && sce_valid) {
-                       int frame= seq->sfra + se->nr + seq->anim_startofs;
-                       int oldcfra = seq->scene->r.cfra;
-                       Object *oldcamera= seq->scene->camera;
-                       ListBase oldmarkers;
-
-                       /* 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 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
-
-                          Hmm, don't see, why we can't do that all the time,
-                          and since G.rendering is uhm, gone... (Peter)
-                       */
-
-                       int rendering = 1;
-                       int doseq;
-
-                       /* prevent eternal loop */
-                       doseq= scene->r.scemode & R_DOSEQ;
-                       scene->r.scemode &= ~R_DOSEQ;
-
-                       seq->scene->r.cfra= frame;
-                       if(seq->scene_camera)   seq->scene->camera= seq->scene_camera;
-                       else                                    scene_camera_switch_update(seq->scene);
+       out = sh.execute(bmain, scene, seq, cfra, fac, facf, seqrectx, seqrecty, 
+                        render_size,
+                        ibuf[0], ibuf[1], ibuf[2]);
 
-#ifdef DURIAN_CAMERA_SWITCH
-                       /* stooping to new low's in hackyness :( */
-                       oldmarkers= seq->scene->markers;
-                       seq->scene->markers.first= seq->scene->markers.last= NULL;
-#endif
+finish:
+       for (i = 0; i < 3; i++) {
+               IMB_freeImBuf(ibuf[i]);
+       }
 
-                       if(sequencer_view3d_cb && (seq->flag & SEQ_USE_SCENE_OPENGL) && (seq->scene == scene || have_seq==0)) {
-                               /* opengl offscreen render */
-                               scene_update_for_newframe(seq->scene, seq->scene->lay);
-                               se->ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty);
-                       }
-                       else {
-                               Render *re;
-                               RenderResult rres;
+       if (!out) {
+               out = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect);
+       }
 
-                               if(rendering)
-                                       re= RE_NewRender(" do_build_seq_ibuf", RE_SLOT_DEFAULT);
-                               else
-                                       re= RE_NewRender(sce->id.name, RE_SLOT_VIEW);
+       return out;
+}
 
-                               RE_BlenderFrame(re, sce, NULL, frame);
 
-                               RE_AcquireResultImage(re, &rres);
+static ImBuf * seq_render_scene_strip_impl(
+       Main *bmain, Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty)
+{
+       ImBuf * ibuf = 0;
+       float frame= seq->sfra + nr + seq->anim_startofs;
+       float oldcfra;
+       Object *oldcamera;
+       ListBase oldmarkers;
+       
+       /* 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 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
+          
+          Hmm, don't see, why we can't do that all the time,
+          and since G.rendering is uhm, gone... (Peter)
+       */
 
-                               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);
-                                       }
-                               } else if (rres.rect32) {
-                                       se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
-                                       memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
-                               }
+       int rendering = G.rendering;
+       int doseq;
+       int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV);
+       int have_seq= FALSE;
+       Scene *sce= seq->scene; /* dont refer to seq->scene above this point!, it can be NULL */
+       int sce_valid= FALSE;
 
-                               RE_ReleaseResultImage(re);
+       if(sce) {
+               have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first;
+               sce_valid= (sce->camera || have_seq);
+       }
 
-                               // BIF_end_render_callbacks();
-                       }
-                       
-                       /* restore */
-                       scene->r.scemode |= doseq;
+       if (!sce_valid)
+               return NULL;
 
-                       seq->scene->r.cfra = oldcfra;
-                       seq->scene->camera= oldcamera;
+       oldcfra= seq->scene->r.cfra;
+       oldcamera= seq->scene->camera;
 
+       /* prevent eternal loop */
+       doseq= scene->r.scemode & R_DOSEQ;
+       scene->r.scemode &= ~R_DOSEQ;
+       
+       seq->scene->r.cfra= frame;
+       if(seq->scene_camera)   
+               seq->scene->camera= seq->scene_camera;
+       else    
+               scene_camera_switch_update(seq->scene);
+       
 #ifdef DURIAN_CAMERA_SWITCH
-                       /* stooping to new low's in hackyness :( */
-                       seq->scene->markers= oldmarkers;
+       /* stooping to new low's in hackyness :( */
+       oldmarkers= seq->scene->markers;
+       seq->scene->markers.first= seq->scene->markers.last= NULL;
 #endif
-
-                       copy_to_ibuf_still(seq, se);
-
-                       if (!build_proxy_run) {
-                               if(se->ibuf == NULL) {
-                                       se->ok = STRIPELEM_FAILED;
-                               } else {
-                                       input_preprocess(scene, seq, se, cfra);
-                               }
+       
+       if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) {
+               /* opengl offscreen render */
+               scene_update_for_newframe(bmain, seq->scene, seq->scene->lay);
+               ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, IB_rect,
+                                         scene->r.seq_prev_type);
+       }
+       else {
+               Render *re;
+               RenderResult rres;
+               
+               if(rendering)
+                       re= RE_NewRender(" do_build_seq_ibuf");
+               /* If the top level scene that does the sequencer rendering is included 
+                * as a strip the default render name for the strip will conflict with
+                * the original render, so override the name in this case.
+                * See bugs #22236 and #24160 for examples.
+                * XXX: Somebody with deeper insight to the rendering pipeline should
+                *      probably check if this is the best way to handle this. -jahka
+                */
+               else if(seq->scene == scene)
+                       re= RE_NewRender("scene_conflict_render");
+               else
+                       re= RE_NewRender(sce->id.name);
+               
+               RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame);
+               
+               RE_AcquireResultImage(re, &rres);
+               
+               if(rres.rectf) {
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
+                       memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
+                       if(rres.rectz) {
+                               addzbuffloatImBuf(ibuf);
+                               memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
                        }
 
+                       /* float buffers in the sequencer are not linear */
+                       ibuf->profile= IB_PROFILE_LINEAR_RGB;
+                       IMB_convert_profile(ibuf, IB_PROFILE_SRGB);                     
                }
-       }
-       if (!build_proxy_run) {
-               if (se->ibuf && use_limiter) {
-                       IMB_cache_limiter_insert(se->ibuf);
-                       IMB_cache_limiter_ref(se->ibuf);
-                       IMB_cache_limiter_touch(se->ibuf);
+               else if (rres.rect32) {
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
+                       memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
                }
+               
+               RE_ReleaseResultImage(re);
+               
+               // BIF_end_render_callbacks();
        }
-}
+       
+       /* restore */
+       scene->r.scemode |= doseq;
+       
+       seq->scene->r.cfra = oldcfra;
+       seq->scene->camera= oldcamera;
+       
+#ifdef DURIAN_CAMERA_SWITCH
+       /* stooping to new low's in hackyness :( */
+       seq->scene->markers= oldmarkers;
+#endif
 
-static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size);
+       return ibuf;
+}
 
-static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size)
+static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra,
+                               int render_size, 
+                               int seqrectx, int seqrecty)
 {
-       float fac, facf;
-       struct SeqEffectHandle sh = get_sequence_effect(seq);
-       int early_out;
-       FCurve *fcu= NULL;
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       int use_preprocess = input_have_to_preprocess(
+               scene, seq, cfra, seqrectx, seqrecty);
+       ImBuf * ibuf = seq_stripelem_cache_get(
+               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF);
+       float nr = give_stripelem_index(seq, cfra);
 
-       se->se1 = 0;
-       se->se2 = 0;
-       se->se3 = 0;
+       /* currently, we cache preprocessed images */
+       if (ibuf) {
+               use_preprocess = FALSE;
+       }
 
-       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
-               sh.get_default_fac(seq, cfra, &fac, &facf);
-               if( scene->r.mode & R_FIELDS ); else facf= fac;
-       } else {
-               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
-                                         "effect_fader", 0);
-               if (fcu) {
-                       fac = facf = evaluate_fcurve(fcu, cfra);
-                       if( scene->r.mode & R_FIELDS ) {
-                               facf = evaluate_fcurve(fcu, cfra + 0.5);
-                       }
-               } else {
-                       fac = facf = seq->effect_fader;
+       if(seq->type == SEQ_META) {
+               ImBuf * meta_ibuf = 0;
+
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
                }
-       }
 
-       early_out = sh.early_out(seq, fac, facf);
-       switch (early_out) {
-       case -1:
-               /* no input needed */
-               break;
-       case 0:
-               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size);
-               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size);
-               if (seq->seq3) {
-                       se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size);
+               if(!ibuf && seq->seqbase.first) {
+                       meta_ibuf = seq_render_strip_stack(
+                               bmain, scene,
+                               &seq->seqbase, seq->start + nr, 0,
+                               render_size, seqrectx, seqrecty);
                }
-               break;
-       case 1:
-               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size);
-               break;
-       case 2:
-               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size);
-               break;
-       }
 
+               if(!ibuf && meta_ibuf) {
+                       ibuf = meta_ibuf;
+                       if(ibuf && use_preprocess) {
+                               struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-       do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size);
+                               IMB_freeImBuf(ibuf);
 
-       /* children are not needed anymore ... */
+                               ibuf = i;
+                       }
+               }
+       } else if(seq->type == SEQ_SPEED) {
+               ImBuf * child_ibuf = 0;
 
-       if (se->se1 && se->se1->ibuf) {
-               IMB_cache_limiter_unref(se->se1->ibuf);
-       }
-       if (se->se2 && se->se2->ibuf) {
-               IMB_cache_limiter_unref(se->se2->ibuf);
-       }
-       if (se->se3 && se->se3->ibuf) {
-               IMB_cache_limiter_unref(se->se3->ibuf);
-       }
-       check_limiter_refcount("do_effect_seq_recursively", se);
-}
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size)
-{
-       TStripElem *se;
+               if (ibuf == 0) {
+                       float f_cfra;
+                       SpeedControlVars * s 
+                               = (SpeedControlVars *)seq->effectdata;
 
-       se = give_tstripelem(seq, cfra);
+                       sequence_effect_speed_rebuild_map(scene, seq, 0);
 
-       if(se) {
-               if (seq->type & SEQ_EFFECT) {
-                       do_effect_seq_recursively(scene, seq, se, cfra, render_size);
-               } else {
-                       do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size);
+                       /* weeek! */
+                       f_cfra = seq->start + s->frameMap[(int) nr];
+
+                       child_ibuf = seq_render_strip(bmain, scene, seq->seq1, f_cfra,
+                                                     render_size, 
+                                                     seqrectx, seqrecty);
                }
-       }
-       return se;
-}
 
-/* 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 (!ibuf && child_ibuf) {
+                       ibuf = child_ibuf;
+                       if(ibuf && use_preprocess) {
+                               struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-*/
+                               IMB_freeImBuf(ibuf);
 
-static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size)
-{
-       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
-       int nr = cfra - seq->start;
-       float f_cfra;
-       int cfra_left;
-       int cfra_right;
-       TStripElem * se = 0;
-       TStripElem * se1 = 0;
-       TStripElem * se2 = 0;
-       
-       sequence_effect_speed_rebuild_map(scene, seq, 0);
-       
-       f_cfra = seq->start + s->frameMap[nr];
-       
-       cfra_left = (int) floor(f_cfra);
-       cfra_right = (int) ceil(f_cfra);
+                               ibuf = i;
+                       }
+               }
+       } else if(seq->type & SEQ_EFFECT) {
+               /* should the effect be recalculated? */
+               
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-       se = give_tstripelem(seq, cfra);
+               if(ibuf == 0) {         
+                       ibuf = seq_render_effect_strip_impl(
+                               bmain, scene, cfra, seq, render_size, 
+                               seqrectx, seqrecty);
+               }
+       } else if(seq->type == SEQ_IMAGE) {
+               StripElem * s_elem = give_stripelem(seq, cfra);
 
-       if (!se) {
-               return se;
-       }
+               if(ibuf == 0 && s_elem) {
+                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
+                       BLI_path_abs(name, G.main->name);
 
-       if (cfra_left == cfra_right || 
-           (s->flags & SEQ_SPEED_BLEND) == 0) {
-               test_and_auto_discard_ibuf(se);
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-               if (se->ibuf == NULL) {
-                       se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size);
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty);
+               }
 
-                       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 (ibuf == 0 && s_elem && 
+                   (ibuf = IMB_loadiffname(name, IB_rect))) {
+                       /* we don't need both (speed reasons)! */
+                       if (ibuf->rect_float && ibuf->rect)
+                               imb_freerectImBuf(ibuf);
 
-                       if (se1 == 0 || se1->ibuf == 0) {
-                               make_black_ibuf(se->ibuf);
-                       } else {
-                               if (se->ibuf != se1->ibuf) {
-                                       if (se->ibuf) {
-                                               IMB_freeImBuf(se->ibuf);
-                                       }
+                       /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+                       if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+                               IMB_convert_profile(ibuf, IB_PROFILE_NONE);
 
-                                       se->ibuf = se1->ibuf;
-                                       IMB_refImBuf(se->ibuf);
-                               }
-                       }
+                       copy_to_ibuf_still(seq, nr, ibuf);
                }
-       } else {
-               struct SeqEffectHandle sh;
-
-               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_MOVIE) {
+               if(ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+                       
+               }
+               
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
                }
 
-               if (se->ibuf == NULL) {
-                       se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size);
-                       se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size);
+               if (ibuf == 0) {
+                       if(seq->anim==0) {
+                               BLI_join_dirfile(name, 
+                                                seq->strip->dir, 
+                                                seq->strip->stripdata->name);
+                               BLI_path_abs(name, G.main->name);
+                                       
+                               seq->anim = openanim(
+                                       name, IB_rect | 
+                                       ((seq->flag & SEQ_FILTERY) 
+                                        ? IB_animdeinterlace : 0));
+                       }
+                       if(seq->anim) {
+                               IMB_anim_set_preseek(seq->anim, 
+                                                    seq->anim_preseek);
+                               ibuf = IMB_anim_absolute(seq->anim, 
+                                                        nr 
+                                                        + seq->anim_startofs);
+                               /* we don't need both (speed reasons)! */
+                               if (ibuf && ibuf->rect_float 
+                                   && ibuf->rect) {
+                                       imb_freerectImBuf(ibuf);
+                               }
 
-                       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);
+                       }
+                       copy_to_ibuf_still(seq, nr, ibuf);
+               }
                        
-                       if (!se1 || !se2) {
-                               make_black_ibuf(se->ibuf);
-                       } else {
-                               sh = get_sequence_effect(seq);
+       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+               }
+               
+               if (ibuf == 0) {
+                       ibuf = seq_render_scene_strip_impl(bmain, scene, seq, nr,
+                                                          seqrectx, seqrecty);
 
-                               sh.execute(scene, 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);
-                       }
+                       copy_to_ibuf_still(seq, nr, ibuf);
                }
+       }
 
+       if (!ibuf) {
+               ibuf = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect);
        }
 
-       /* 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 (ibuf->x != seqrectx || ibuf->y != seqrecty) {
+               use_preprocess = TRUE;
        }
 
-       /* 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);
+       if (use_preprocess) {
+               ibuf = input_preprocess(scene, seq, cfra, seqrectx,
+                                       seqrecty, ibuf);
+       }
 
-       check_limiter_refcount("do_handle_speed_effect", se);
+       seq_stripelem_cache_put(
+               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf);
 
-       return se;
+       return ibuf;
 }
 
-/* 
- * build all ibufs recursively
- * 
- * if successfull, the returned TStripElem contains the (referenced!) imbuf
- * that means: you _must_ call 
- *
- * IMB_cache_limiter_unref(rval);
- * 
- * if rval != 0
- * 
- */
+/* **********************************************************************
+   strip stack rendering functions
+   ********************************************************************** */
 
-static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size)
+static int seq_must_swap_input_in_blend_mode(Sequence * seq)
 {
-       TStripElem *se;
-       if (seq->type == SEQ_SPEED) {
-               se = do_handle_speed_effect(scene, seq, cfra, render_size);
-       } else {
-               se = do_build_seq_recursively_impl(scene, seq, cfra, render_size);
+       int swap_input = FALSE;
+
+       /* bad hack, to fix crazy input ordering of 
+          those two effects */
+
+       if (seq->blend_mode == SEQ_ALPHAOVER ||
+               seq->blend_mode == SEQ_ALPHAUNDER ||
+               seq->blend_mode == SEQ_OVERDROP) {
+               swap_input = TRUE;
        }
+       
+       return swap_input;
+}
 
-       check_limiter_refcount("do_build_seq_recursively", se);
+static int seq_get_early_out_for_blend_mode(Sequence * seq)
+{
+       struct SeqEffectHandle sh = get_sequence_blend(seq);
+       float facf = seq->blend_opacity / 100.0;
+       int early_out = sh.early_out(seq, facf, facf);
+       
+       if (early_out < 1) {
+               return early_out;
+       }
 
-       return se;
+       if (seq_must_swap_input_in_blend_mode(seq)) {
+               if (early_out == 2) {
+                       return 1;
+               } else if (early_out == 1) {
+                       return 2;
+               }
+       }
+       return early_out;
 }
 
-static TStripElem* do_build_seq_array_recursively(Scene *scene,
-       ListBase *seqbasep, int cfra, int chanshown, int render_size)
+static ImBuf* seq_render_strip_stack(
+       Main *bmain, Scene *scene, ListBase *seqbasep, float cfra, int chanshown, 
+       int render_size, int seqrectx, int seqrecty)
 {
        Sequence* seq_arr[MAXSEQ+1];
        int count;
        int i;
-       TStripElem* se = 0;
+       ImBuf* out = 0;
 
-       count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
+       count = get_shown_sequences(seqbasep, cfra, chanshown, 
+                                   (Sequence **)&seq_arr);
 
        if (!count) {
                return 0;
        }
 
-       se = give_tstripelem(seq_arr[count - 1], cfra);
-
-       if (!se) {
-               return 0;
+#if 0 /* commentind since this breaks keyframing, since it resets the value on draw */
+       if(scene->r.cfra != cfra) {
+               // XXX for prefetch and overlay offset!..., very bad!!!
+               AnimData *adt= BKE_animdata_from_id(&scene->id);
+               BKE_animsys_evaluate_animdata(&scene->id, adt, cfra, ADT_RECALC_ANIM);
        }
+#endif
 
-       test_and_auto_discard_ibuf(se);
+       out = seq_stripelem_cache_get(
+               seq_arr[count - 1], 
+               seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
 
-       if (se->ibuf_comp != 0) {
-               IMB_cache_limiter_insert(se->ibuf_comp);
-               IMB_cache_limiter_ref(se->ibuf_comp);
-               IMB_cache_limiter_touch(se->ibuf_comp);
-               return se;
+       if (out) {
+               return out;
        }
-
        
        if(count == 1) {
-               se = do_build_seq_recursively(scene, seq_arr[0], cfra, render_size);
-               if (se->ibuf) {
-                       se->ibuf_comp = se->ibuf;
-                       IMB_refImBuf(se->ibuf_comp);
-               }
-               return se;
+               out = seq_render_strip(bmain, scene, seq_arr[0],
+                                       cfra, render_size,
+                                       seqrectx, seqrecty);
+               seq_stripelem_cache_put(
+                       seq_arr[0], 
+                       seqrectx, seqrecty, cfra, 
+                       SEQ_STRIPELEM_IBUF_COMP, out);
+
+               return out;
        }
 
 
        for (i = count - 1; i >= 0; i--) {
                int early_out;
                Sequence * seq = seq_arr[i];
-               struct SeqEffectHandle sh;
-               float facf;
 
-               se = give_tstripelem(seq, cfra);
+               out = seq_stripelem_cache_get(
+                       seq, 
+                       seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
 
-               test_and_auto_discard_ibuf(se);
-
-               if (se->ibuf_comp != 0) {
+               if (out) {
                        break;
                }
                if (seq->blend_mode == SEQ_BLEND_REPLACE) {
-                       do_build_seq_recursively(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf);
-                       } else {
-                               se->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
-                       }
+                       out = seq_render_strip(bmain, scene, seq, cfra,
+                                              render_size,
+                                              seqrectx, seqrecty);
                        break;
                }
 
-               sh = get_sequence_blend(seq);
-
-               facf = seq->blend_opacity / 100.0;
-
-               early_out = sh.early_out(seq, facf, facf);
+               early_out = seq_get_early_out_for_blend_mode(seq);
 
                switch (early_out) {
                case -1:
                case 2:
-                       do_build_seq_recursively(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf_comp);
-                       } else {
-                               se->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
-                       }
+                       out = seq_render_strip(bmain, scene, seq, cfra,
+                                              render_size,
+                                              seqrectx, seqrecty);
                        break;
                case 1:
                        if (i == 0) {
-                               se->ibuf_comp = IMB_allocImBuf(
+                               out = IMB_allocImBuf(
                                        (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
+                                       32, IB_rect);
                        }
                        break;
                case 0:
-                       do_build_seq_recursively(scene, seq, cfra, render_size);
-                       if (!se->ibuf) {
-                               se->ibuf = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf);
-                               IMB_cache_limiter_ref(se->ibuf);
-                               IMB_cache_limiter_touch(se->ibuf);
-                       }
                        if (i == 0) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf_comp);
+                               out = seq_render_strip(bmain, scene, seq, cfra,
+                                                      render_size,
+                                                      seqrectx, seqrecty);
                        }
+
                        break;
                }
-       
-               if (se->ibuf_comp) {
+               if (out) {
                        break;
                }
        }
 
+       seq_stripelem_cache_put(
+               seq_arr[i], seqrectx, seqrecty, cfra, 
+               SEQ_STRIPELEM_IBUF_COMP, out);
+
+
        i++;
 
        for (; i < count; i++) {
                Sequence * seq = seq_arr[i];
-               struct SeqEffectHandle sh = get_sequence_blend(seq);
-               TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra);
-               TStripElem* se2 = give_tstripelem(seq_arr[i], cfra);
-
-               float facf = seq->blend_opacity / 100.0;
-
-               int early_out = sh.early_out(seq, facf, facf);
-
-               switch (early_out) {
-               case 0: {
-                       int x= se2->ibuf->x;
-                       int y= se2->ibuf->y;
-                       int swap_input = FALSE;
 
-                       if(se1->ibuf_comp == NULL)
-                               continue;
+               if (seq_get_early_out_for_blend_mode(seq) == 0) {
+                       struct SeqEffectHandle sh = get_sequence_blend(seq);
+                       ImBuf * ibuf1 = out;
+                       ImBuf * ibuf2 = seq_render_strip(bmain, scene, seq, cfra,
+                                                        render_size,
+                                                        seqrectx, seqrecty);
 
-                       if (se1->ibuf_comp->rect_float ||
-                           se2->ibuf->rect_float) {
-                               se2->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rectfloat, 0);
-                       } else {
-                               se2->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                       }
-
-
-                       if (!se1->ibuf_comp->rect_float && 
-                           se2->ibuf_comp->rect_float) {
-                               IMB_float_from_rect(se1->ibuf_comp);
-                       }
-                       if (!se2->ibuf->rect_float && 
-                           se2->ibuf_comp->rect_float) {
-                               IMB_float_from_rect(se2->ibuf);
-                       }
-
-                       if (!se1->ibuf_comp->rect && 
-                           !se2->ibuf_comp->rect_float) {
-                               IMB_rect_from_float(se1->ibuf_comp);
-                       }
-                       if (!se2->ibuf->rect && 
-                           !se2->ibuf_comp->rect_float) {
-                               IMB_rect_from_float(se2->ibuf);
-                       }
-                       
-                       /* bad hack, to fix crazy input ordering of 
-                          those two effects */
+                       float facf = seq->blend_opacity / 100.0;
+                       int swap_input 
+                               = seq_must_swap_input_in_blend_mode(seq);
 
-                       if (seq->blend_mode == SEQ_ALPHAOVER ||
-                           seq->blend_mode == SEQ_ALPHAUNDER ||
-                           seq->blend_mode == SEQ_OVERDROP) {
-                               swap_input = TRUE;
-                       }
+                       int x= seqrectx;
+                       int y= seqrecty;
 
                        if (swap_input) {
-                               sh.execute(scene, seq, cfra, 
-                                          facf, facf, x, y, 
-                                          se2->ibuf, se1->ibuf_comp, 0,
-                                          se2->ibuf_comp);
+                               out = sh.execute(bmain, scene, seq, cfra, 
+                                                facf, facf, x, y, render_size,
+                                                ibuf2, ibuf1, 0);
                        } else {
-                               sh.execute(scene, seq, cfra, 
-                                          facf, facf, x, y, 
-                                          se1->ibuf_comp, se2->ibuf, 0,
-                                          se2->ibuf_comp);
+                               out = sh.execute(bmain, scene, seq, cfra, 
+                                                facf, facf, x, y, render_size,
+                                                ibuf1, ibuf2, 0);
                        }
-                       
-                       IMB_cache_limiter_insert(se2->ibuf_comp);
-                       IMB_cache_limiter_ref(se2->ibuf_comp);
-                       IMB_cache_limiter_touch(se2->ibuf_comp);
-
-                       IMB_cache_limiter_unref(se1->ibuf_comp);
-                       IMB_cache_limiter_unref(se2->ibuf);
-
-                       break;
+               
+                       IMB_freeImBuf(ibuf1);
+                       IMB_freeImBuf(ibuf2);
                }
-               case 1: {
-                       se2->ibuf_comp = se1->ibuf;
-                       if(se2->ibuf_comp)
-                               IMB_refImBuf(se2->ibuf_comp);
 
-                       break;
-               }
-               }
-               se = se2;
+               seq_stripelem_cache_put(
+                       seq_arr[i], seqrectx, seqrecty, cfra, 
+                       SEQ_STRIPELEM_IBUF_COMP, out);
        }
 
-       return se;
+       return out;
 }
 
 /*
  * returned ImBuf is refed!
- * you have to unref after usage!
+ * you have to free after usage!
  */
 
-static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
        int count;
        ListBase *seqbasep;
-       TStripElem *se;
-
        
        if(ed==NULL) return NULL;
 
@@ -2693,50 +2295,19 @@ static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, i
                seqbasep= ed->seqbasep;
        }
 
-       seqrectx= rectx;        /* bad bad global! */
-       seqrecty= recty;
-
-       se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size);
-
-       if(!se) { 
-               return 0;
-       }
-
-       check_limiter_refcount_comp("give_ibuf_seq_impl", se);
-
-       return se->ibuf_comp;
+       return seq_render_strip_stack(
+               bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
 }
 
-ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
+ImBuf *give_ibuf_seqbase(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep)
 {
-       TStripElem* se;
-
-       seqrectx= rectx;        /* bad bad global! */
-       seqrecty= recty;
-
-       se = do_build_seq_recursively(scene, seq, cfra, render_size);
-
-       if(!se) { 
-               return 0;
-       }
-
-       check_limiter_refcount("give_ibuf_seq_direct", se);
-
-       if (se->ibuf) {
-               IMB_cache_limiter_unref(se->ibuf);
-       }
-
-       return se->ibuf;
+       return seq_render_strip_stack(bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
 }
 
-ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
-{
-       ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size);
 
-       if (i) {
-               IMB_cache_limiter_unref(i);
-       }
-       return i;
+ImBuf *give_ibuf_seq_direct(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
+{
+       return seq_render_strip(bmain, scene, seq, cfra, render_size, rectx, recty);
 }
 
 #if 0
@@ -2767,7 +2338,7 @@ static pthread_cond_t  wakeup_cond         = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t frame_done_lock     = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t  frame_done_cond     = PTHREAD_COND_INITIALIZER;
 
-static volatile int seq_thread_shutdown = FALSE;
+static volatile int seq_thread_shutdown = TRUE; 
 static volatile int seq_last_given_monoton_cfra = 0;
 static int monoton_cfra = 0;
 
@@ -2918,8 +2489,8 @@ static void seq_stop_threads()
 
        seq_thread_shutdown = TRUE;
 
-        pthread_cond_broadcast(&wakeup_cond);
-        pthread_mutex_unlock(&wakeup_lock);
+               pthread_cond_broadcast(&wakeup_cond);
+               pthread_mutex_unlock(&wakeup_lock);
 
        for(tslot = running_threads.first; tslot; tslot= tslot->next) {
                pthread_join(tslot->pthread, NULL);
@@ -3002,13 +2573,13 @@ static void seq_wait_for_prefetch_ready()
 }
 #endif
 
-ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 {
        PrefetchQueueElem *e = NULL;
        int found_something = FALSE;
 
        if (seq_thread_shutdown) {
-               return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size);
+               return give_ibuf_seq(bmain, scene, rectx, recty, cfra, chanshown, render_size);
        }
 
        while (!e) {
@@ -3017,10 +2588,10 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int
 
                for (e = prefetch_done.first; e; e = e->next) {
                        if (cfra == e->cfra &&
-                           chanshown == e->chanshown &&
-                           rectx == e->rectx && 
-                           recty == e->recty &&
-                           render_size == e->render_size) {
+                               chanshown == e->chanshown &&
+                               rectx == e->rectx && 
+                               recty == e->recty &&
+                               render_size == e->render_size) {
                                success = TRUE;
                                found_something = TRUE;
                                break;
@@ -3030,10 +2601,10 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int
                if (!e) {
                        for (e = prefetch_wait.first; e; e = e->next) {
                                if (cfra == e->cfra &&
-                                   chanshown == e->chanshown &&
-                                   rectx == e->rectx && 
-                                   recty == e->recty &&
-                                   render_size == e->render_size) {
+                                       chanshown == e->chanshown &&
+                                       rectx == e->rectx && 
+                                       recty == e->recty &&
+                                       render_size == e->render_size) {
                                        found_something = TRUE;
                                        break;
                                }
@@ -3044,13 +2615,13 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int
                        PrefetchThread *tslot;
 
                        for(tslot = running_threads.first; 
-                           tslot; tslot= tslot->next) {
+                               tslot; tslot= tslot->next) {
                                if (tslot->current &&
-                                   cfra == tslot->current->cfra &&
-                                   chanshown == tslot->current->chanshown &&
-                                   rectx == tslot->current->rectx && 
-                                   recty == tslot->current->recty &&
-                                   render_size== tslot->current->render_size){
+                                       cfra == tslot->current->cfra &&
+                                       chanshown == tslot->current->chanshown &&
+                                       rectx == tslot->current->rectx && 
+                                       recty == tslot->current->recty &&
+                                       render_size== tslot->current->render_size){
                                        found_something = TRUE;
                                        break;
                                }
@@ -3085,20 +2656,6 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int
 
 /* Functions to free imbuf and anim data on changes */
 
-static void free_imbuf_strip_elem(TStripElem *se)
-{
-       if(se->ibuf) {
-               IMB_freeImBuf(se->ibuf);
-       }
-       if(se->ibuf_comp) {
-               IMB_freeImBuf(se->ibuf_comp);
-       }
-       se->ibuf_comp = 0;
-       se->ibuf= 0;
-       se->ok= STRIPELEM_OK;
-       se->se1= se->se2= se->se3= 0;
-}
-
 static void free_anim_seq(Sequence *seq)
 {
        if(seq->anim) {
@@ -3107,63 +2664,10 @@ static void free_anim_seq(Sequence *seq)
        }
 }
 
-#if 0
-static void free_imbuf_seq_except(Scene *scene, int cfra)
+void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
+                   int keep_file_handles)
 {
-       Editing *ed= seq_give_editing(scene, FALSE);
        Sequence *seq;
-       TStripElem *se;
-       int a;
-
-       if(ed==NULL) return;
-
-       SEQ_BEGIN(ed, seq) {
-               if(seq->strip) {
-                       TStripElem * curelem = give_tstripelem(seq, cfra);
-
-                       for(a = 0, se = seq->strip->tstripdata; 
-                           a < seq->strip->len && se; a++, se++) {
-                               if(se != curelem) {
-                                       free_imbuf_strip_elem(se);
-                               }
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_startstill;
-                           a < seq->strip->startstill && se; a++, se++) {
-                               if(se != curelem) {
-                                       free_imbuf_strip_elem(se);
-                               }
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_endstill;
-                           a < seq->strip->endstill && se; a++, se++) {
-                               if(se != curelem) {
-                                       free_imbuf_strip_elem(se);
-                               }
-                       }
-                       if(seq->strip->ibuf_startstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_startstill);
-                               seq->strip->ibuf_startstill = 0;
-                       }
-
-                       if(seq->strip->ibuf_endstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_endstill);
-                               seq->strip->ibuf_endstill = 0;
-                       }
-
-                       if(seq->type==SEQ_MOVIE)
-                               if(seq->startdisp > cfra || seq->enddisp < cfra)
-                                       free_anim_seq(seq);
-                       free_proxy_seq(seq);
-               }
-       }
-       SEQ_END
-}
-#endif
-
-void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage)
-{
-       Sequence *seq;
-       TStripElem *se;
-       int a;
 
        if (check_mem_usage) {
                /* Let the cache limitor take care of this (schlaile) */
@@ -3189,39 +2693,19 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage)
                }
        }
 
+       seq_stripelem_cache_cleanup();
        
        for(seq= seqbase->first; seq; seq= seq->next) {
                if(seq->strip) {
-                       for(a = 0, se = seq->strip->tstripdata; 
-                           a < seq->strip->len && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_startstill; 
-                           a < seq->strip->startstill && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_endstill; 
-                           a < seq->strip->endstill && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       if(seq->strip->ibuf_startstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_startstill);
-                               seq->strip->ibuf_startstill = 0;
-                       }
-
-                       if(seq->strip->ibuf_endstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_endstill);
-                               seq->strip->ibuf_endstill = 0;
-                       }
-
-                       if(seq->type==SEQ_MOVIE)
+                       if(seq->type==SEQ_MOVIE && !keep_file_handles)
                                free_anim_seq(seq);
                        if(seq->type==SEQ_SPEED) {
                                sequence_effect_speed_rebuild_map(scene, seq, 1);
                        }
                }
                if(seq->type==SEQ_META) {
-                       free_imbuf_seq(scene, &seq->seqbase, FALSE);
+                       free_imbuf_seq(scene, &seq->seqbase, FALSE,
+                                      keep_file_handles);
                }
                if(seq->type==SEQ_SCENE) {
                        /* FIXME: recurs downwards, 
@@ -3234,8 +2718,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage)
 static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
 {
        Sequence *subseq;
-       int a, free_imbuf = 0;
-       TStripElem *se;
+       int free_imbuf = 0;
        
        /* recurs downwards to see if this seq depends on the changed seq */
        
@@ -3261,12 +2744,6 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan
        
        if(free_imbuf) {
                if(ibuf_change) {
-                       se= seq->strip->tstripdata;
-                       if (se) {
-                               for(a=0; a<seq->len; a++, se++)
-                                       free_imbuf_strip_elem(se);
-                       }
-                       
                        if(seq->type == SEQ_MOVIE)
                                free_anim_seq(seq);
                        if(seq->type == SEQ_SPEED) {
@@ -3292,39 +2769,6 @@ void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_ch
                update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
 }
 
-#if 0 // XXX from 2.4x, needs updating
-void free_imbuf_seq()
-{
-       Scene * sce = G.main->scene.first;
-       while(sce) {
-               free_imbuf_seq_editing(sce->ed);
-               sce= sce->id.next;
-       }
-}
-#endif 
-
-#if 0 // XXX old animation system
-static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
-{
-       /* force update of all sequences with this ipo, on ipo changes */
-       Editing *ed= seq_give_editing(scene, FALSE);
-       Sequence *seq;
-
-       if(ed==NULL) return;
-
-       SEQ_BEGIN(ed, seq) {
-               if(seq->ipo == ipo) {
-                       update_changed_seq_and_deps(scene, seq, 0, 1);
-                       if(seq->type == SEQ_SPEED) {
-                               sequence_effect_speed_rebuild_map(seq, 1);
-                       }
-                       free_proxy_seq(seq);
-               }
-       }
-       SEQ_END
-}
-#endif
-
 /* seq funcs's for transforming internally
  notice the difference between start/end and left/right.
 
@@ -3385,7 +2829,8 @@ void seq_tx_set_final_right(Sequence *seq, int val)
    since they work a bit differently to normal image seq's (during transform) */
 int seq_single_check(Sequence *seq)
 {
-       if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR))
+       if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR
+                            || seq->type == SEQ_MULTICAM))
                return 1;
        else
                return 0;
@@ -3669,7 +3114,7 @@ static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequen
 
                        seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute);
                }
-               else if(seq->type == SEQ_SOUND) {
+               else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) {
                        if(seq->scene_sound) {
                                sound_mute_scene_sound(scene, seq->scene_sound, seqmute);
                        }
@@ -3708,6 +3153,57 @@ ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq)
        return NULL;
 }
 
+int seq_swap(Sequence *seq_a, Sequence *seq_b)
+{
+       char name[sizeof(seq_a->name)];
+
+       if(seq_a->len != seq_b->len)
+               return 0;
+
+       /* type checking, could be more advanced but disalow sound vs non-sound copy */
+       if(seq_a->type != seq_b->type) {
+               if(seq_a->type == SEQ_SOUND || seq_b->type == SEQ_SOUND) {
+                       return 0;
+               }
+
+               /* disallow effects to swap with non-effects strips */
+               if((seq_a->type & SEQ_EFFECT) != (seq_b->type & SEQ_EFFECT)) {
+                       return 0;
+               }
+
+               if((seq_a->type & SEQ_EFFECT) && (seq_b->type & SEQ_EFFECT)) {
+                       if(get_sequence_effect_num_inputs(seq_a->type) != get_sequence_effect_num_inputs(seq_b->type)) {
+                               return 0;
+                       }
+               }
+       }
+
+       SWAP(Sequence, *seq_a, *seq_b);
+
+       /* swap back names so animation fcurves dont get swapped */
+       strcpy(name, seq_a->name+2);
+       strcpy(seq_a->name+2, seq_b->name+2);
+       strcpy(seq_b->name+2, name);
+
+       /* swap back opacity, and overlay mode */
+       SWAP(int, seq_a->blend_mode, seq_b->blend_mode);
+       SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity);
+
+
+       SWAP(void *, seq_a->prev, seq_b->prev);
+       SWAP(void *, seq_a->next, seq_b->next);
+       SWAP(int, seq_a->start, seq_b->start);
+       SWAP(int, seq_a->startofs, seq_b->startofs);
+       SWAP(int, seq_a->endofs, seq_b->endofs);
+       SWAP(int, seq_a->startstill, seq_b->startstill);
+       SWAP(int, seq_a->endstill, seq_b->endstill);
+       SWAP(int, seq_a->machine, seq_b->machine);
+       SWAP(int, seq_a->startdisp, seq_b->startdisp);
+       SWAP(int, seq_a->enddisp, seq_b->enddisp);
+
+       return 1;
+}
+
 /* XXX - hackish function needed for transforming strips! TODO - have some better solution */
 void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
 {
@@ -3721,7 +3217,7 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
 
        for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) {
                if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
-                       int i;
+                       unsigned int i;
                        for (i = 0; i < fcu->totvert; i++) {
                                BezTriple *bezt= &fcu->bezt[i];
                                bezt->vec[0][0] += ofs;
@@ -3732,6 +3228,62 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
        }
 }
 
+void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to)
+{
+       char str_from[32];
+       FCurve *fcu;
+       FCurve *fcu_last;
+       FCurve *fcu_cpy;
+       ListBase lb= {NULL, NULL};
+
+       if(scene->adt==NULL || scene->adt->action==NULL)
+               return;
+
+       sprintf(str_from, "[\"%s\"]", name_from);
+
+       fcu_last= scene->adt->action->curves.last;
+
+       for (fcu= scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu= fcu->next) {
+               if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str_from)) {
+                       fcu_cpy= copy_fcurve(fcu);
+                       BLI_addtail(&lb, fcu_cpy);
+               }
+       }
+
+       /* notice validate is 0, keep this because the seq may not be added to the scene yet */
+       BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0);
+
+       /* add the original fcurves back */
+       addlisttolist(&scene->adt->action->curves, &lb);
+}
+
+/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */
+static void seq_free_animdata(Scene *scene, Sequence *seq)
+{
+       char str[32];
+       FCurve *fcu;
+
+       if(scene->adt==NULL || scene->adt->action==NULL)
+               return;
+
+       sprintf(str, "[\"%s\"]", seq->name+2);
+
+       fcu= scene->adt->action->curves.first; 
+
+       while (fcu) {
+               if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
+                       FCurve *next_fcu = fcu->next;
+                       
+                       BLI_remlink(&scene->adt->action->curves, fcu);
+                       free_fcurve(fcu);
+
+                       fcu = next_fcu;
+               } else {
+                       fcu = fcu->next;
+               }
+       }
+}
+
 
 Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive)
 {
@@ -3750,14 +3302,14 @@ Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive)
 }
 
 
-Sequence *active_seq_get(Scene *scene)
+Sequence *seq_active_get(Scene *scene)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
        if(ed==NULL) return NULL;
        return ed->act_seq;
 }
 
-void active_seq_set(Scene *scene, Sequence *seq)
+void seq_active_set(Scene *scene, Sequence *seq)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
        if(ed==NULL) return;
@@ -3765,12 +3317,41 @@ void active_seq_set(Scene *scene, Sequence *seq)
        ed->act_seq= seq;
 }
 
+int seq_active_pair_get(Scene *scene, Sequence **seq_act, Sequence **seq_other)
+{
+       Editing *ed= seq_give_editing(scene, FALSE);
+
+       *seq_act= seq_active_get(scene);
+
+       if(*seq_act == NULL) {
+               return 0;
+       }
+       else {
+               Sequence *seq;
+
+               *seq_other= NULL;
+
+               for(seq= ed->seqbasep->first; seq; seq= seq->next) {
+                       if(seq->flag & SELECT && (seq != (*seq_act))) {
+                               if(*seq_other) {
+                                       return 0;
+                               }
+                               else {
+                                       *seq_other= seq;
+                               }
+                       }
+               }
+
+               return (*seq_other != NULL);
+       }
+}
+
 /* api like funcs for adding */
 
 void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
 {
        if(seq) {
-               strcpy(seq->name, seq_load->name);
+               BLI_strncpy(seq->name+2, seq_load->name, sizeof(seq->name)-2);
                seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
 
                if(seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) {
@@ -3779,7 +3360,7 @@ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
 
                if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) {
                        seq_load->flag |= SELECT;
-                       active_seq_set(scene, seq);
+                       seq_active_set(scene, seq);
                }
 
                if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
@@ -3807,6 +3388,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
        seq->flag= SELECT;
        seq->start= cfra;
        seq->machine= machine;
+       seq->sat= 1.0;
        seq->mul= 1.0;
        seq->blend_opacity = 100.0;
        seq->volume = 1.0f;
@@ -3824,8 +3406,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
        seq->type= SEQ_IMAGE;
-       BLI_strncpy(seq->name+2, "Image", SEQ_NAME_MAXSTR-2);
-       seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
+       seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
        
        /* basic defaults */
        seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
@@ -3833,8 +3414,8 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        strip->len = seq->len = seq_load->len ? seq_load->len : 1;
        strip->us= 1;
        strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-       BLI_split_dirfile(seq_load->path, strip->dir, se->name);
-       
+       BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
+
        seq_load_apply(scene, seq, seq_load);
 
        return seq;
@@ -3852,7 +3433,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        AUD_SoundInfo info;
 
-       sound = sound_new_file(CTX_data_main(C), seq_load->path);
+       sound = sound_new_file(CTX_data_main(C), seq_load->path); /* handles relative paths */
 
        if (sound==NULL || sound->playback_handle == NULL) {
                //if(op)
@@ -3900,6 +3481,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
        Scene *scene= CTX_data_scene(C); /* only for sound */
+       char path[sizeof(seq_load->path)];
 
        Sequence *seq, *soundseq;       /* generic strip vars */
        Strip *strip;
@@ -3907,14 +3489,18 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        struct anim *an;
 
-       an = openanim(seq_load->path, IB_rect);
+       BLI_strncpy(path, seq_load->path, sizeof(path));
+       BLI_path_abs(path, G.main->name);
+
+       an = openanim(path, IB_rect);
 
        if(an==NULL)
                return NULL;
 
        seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
-
        seq->type= SEQ_MOVIE;
+       seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
+
        seq->anim= an;
        seq->anim_preseek = IMB_anim_get_preseek(an);
        BLI_strncpy(seq->name+2, "Movie", SEQ_NAME_MAXSTR-2);
@@ -3942,8 +3528,137 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
                seq_load->channel--;
        }
 
+       if(seq_load->name[0] == '\0')
+               BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name));
+
        /* can be NULL */
        seq_load_apply(scene, seq, seq_load);
 
        return seq;
 }
+
+
+static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag)
+{
+       Scene *sce_audio= scene_to ? scene_to : scene;
+       Sequence *seqn = MEM_dupallocN(seq);
+
+       seq->tmp = seqn;
+       seqn->strip= MEM_dupallocN(seq->strip);
+
+       // XXX: add F-Curve duplication stuff?
+
+       if (seq->strip->crop) {
+               seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
+       }
+
+       if (seq->strip->transform) {
+               seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
+       }
+
+       if (seq->strip->proxy) {
+               seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
+       }
+
+       if (seq->strip->color_balance) {
+               seqn->strip->color_balance
+                       = MEM_dupallocN(seq->strip->color_balance);
+       }
+
+       if(seq->type==SEQ_META) {
+               seqn->strip->stripdata = 0;
+
+               seqn->seqbase.first= seqn->seqbase.last= 0;
+               /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
+               /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
+       } else if(seq->type == SEQ_SCENE) {
+               seqn->strip->stripdata = 0;
+               if(seq->scene_sound)
+                       seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+       } else if(seq->type == SEQ_MOVIE) {
+               seqn->strip->stripdata =
+                               MEM_dupallocN(seq->strip->stripdata);
+               seqn->anim= 0;
+       } else if(seq->type == SEQ_SOUND) {
+               seqn->strip->stripdata =
+                               MEM_dupallocN(seq->strip->stripdata);
+               if(seq->scene_sound)
+                       seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
+
+               seqn->sound->id.us++;
+       } else if(seq->type == SEQ_IMAGE) {
+               seqn->strip->stripdata =
+                               MEM_dupallocN(seq->strip->stripdata);
+       } else if(seq->type >= SEQ_EFFECT) {
+               if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
+               if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
+               if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
+
+               if (seq->type & SEQ_EFFECT) {
+                       struct SeqEffectHandle sh;
+                       sh = get_sequence_effect(seq);
+                       if(sh.copy)
+                               sh.copy(seq, seqn);
+               }
+
+               seqn->strip->stripdata = 0;
+
+       } else {
+               fprintf(stderr, "Aiiiiekkk! sequence type not "
+                               "handled in duplicate!\nExpect a crash"
+                                               " now...\n");
+       }
+
+       if(dupe_flag & SEQ_DUPE_UNIQUE_NAME)
+               seqbase_unique_name_recursive(&scene->ed->seqbase, seqn);
+
+       if(dupe_flag & SEQ_DUPE_ANIM)
+               seq_dupe_animdata(scene, seq->name+2, seqn->name+2);
+
+       return seqn;
+}
+
+Sequence * seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence * seq, int dupe_flag)
+{
+       Sequence * seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
+       if (seq->type == SEQ_META) {
+               Sequence *s;
+               for(s= seq->seqbase.first; s; s = s->next) {
+                       Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag);
+                       if (n) {
+                               BLI_addtail(&seqn->seqbase, n);
+                       }
+               }
+       }
+       return seqn;
+}
+
+void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
+{
+       Sequence *seq;
+       Sequence *seqn = 0;
+       Sequence *last_seq = seq_active_get(scene);
+
+       for(seq= seqbase->first; seq; seq= seq->next) {
+               seq->tmp= NULL;
+               if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
+                       seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
+                       if (seqn) { /*should never fail */
+                               if(dupe_flag & SEQ_DUPE_CONTEXT) {
+                                       seq->flag &= ~SEQ_ALLSEL;
+                                       seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
+                               }
+
+                               BLI_addtail(nseqbase, seqn);
+                               if(seq->type==SEQ_META)
+                                       seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag);
+
+                               if(dupe_flag & SEQ_DUPE_CONTEXT) {
+                                       if (seq == last_seq) {
+                                               seq_active_set(scene, seqn);
+                                       }
+                               }
+                       }
+               }
+       }
+}