Changed frame numbering to only alter hashes if they are in the filename (not the...
[blender-staging.git] / source / blender / src / sequence.c
index 068d559916b1dd3922a0b3b18e2f0771233a0891..9f3be52af1bd7a7323b1eee2ed7b1d151591b72d 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
+ * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
  *
- * Contributor(s): none yet.
- *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef WIN32
-#include "BLI_winstuff.h"
-#endif
-
 #include "MEM_guardedalloc.h"
-#include "PIL_dynlib.h"
+#include "MEM_CacheLimiterC-Api.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "IMB_imbuf.h"
 
 #include "DNA_ipo_types.h"
+#include "DNA_scene_types.h"
 #include "DNA_sequence_types.h"
 #include "DNA_view3d_types.h"
 
-#include "BKE_utildefines.h"
-#include "BKE_plugin_types.h"
 #include "BKE_global.h"
-#include "BKE_texture.h"
 #include "BKE_image.h"
+#include "BKE_ipo.h"
 #include "BKE_main.h"
 #include "BKE_scene.h"
-#include "BKE_ipo.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
 
+#include "BIF_editsound.h"
+#include "BIF_editseq.h"
 #include "BSE_filesel.h"
-#include "BIF_interface.h"
 #include "BSE_headerbuttons.h"
+#include "BIF_interface.h"
+#include "BIF_renderwin.h"
 #include "BIF_screen.h"
 #include "BIF_space.h"
 #include "BIF_toolbox.h"
 
 #include "BSE_sequence.h"
+#include "BSE_seqeffects.h"
 
-#include "blendef.h"
-#include "render.h"            // talks to entire render API, and igamtab
-
-Sequence *seq_arr[MAXSEQ+1];
-int seqrectx, seqrecty;
-
-/* support for plugin sequences: */
-
-void open_plugin_seq(PluginSeq *pis, char *seqname)
-{
-       int (*version)();
-       char *cp;
-
-       /* to be sure: (is tested for) */
-       pis->doit= 0;
-       pis->pname= 0;
-       pis->varstr= 0;
-       pis->cfra= 0;
-       pis->version= 0;
-
-       /* clear the error list */
-       PIL_dynlib_get_error_as_string(NULL);
-
-       /* if(pis->handle) PIL_dynlib_close(pis->handle); */
-       /* pis->handle= 0; */
-
-       /* open the needed object */
-       pis->handle= PIL_dynlib_open(pis->name);
-       if(test_dlerr(pis->name, pis->name)) return;
-
-       if (pis->handle != 0) {
-               /* find the address of the version function */
-               version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
-               if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
-
-               if (version != 0) {
-                       pis->version= version();
-                       if (pis->version==2 || pis->version==3) {
-                               int (*info_func)(PluginInfo *);
-                               PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");;
-
-                               info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
-
-                               if(info_func == NULL) error("No info func");
-                               else {
-                                       info_func(info);
-
-                                       pis->pname= info->name;
-                                       pis->vars= info->nvars;
-                                       pis->cfra= info->cfra;
-
-                                       pis->varstr= info->varstr;
-
-                                       pis->doit= (void(*)(void))info->seq_doit;
-                                       if (info->init)
-                                               info->init();
-                               }
-                               MEM_freeN(info);
-
-                               cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
-                               if(cp) strcpy(cp, seqname);
-                       } else {
-                               printf ("Plugin returned unrecognized version number\n");
-                               return;
-                       }
-               }
-       }
-}
-
-PluginSeq *add_plugin_seq(char *str, char *seqname)
-{
-       PluginSeq *pis;
-       VarStruct *varstr;
-       int a;
-
-       pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
-
-       strcpy(pis->name, str);
-       open_plugin_seq(pis, seqname);
-
-       if(pis->doit==0) {
-               if(pis->handle==0) error("no plugin: %s", str);
-               else error("in plugin: %s", str);
-               MEM_freeN(pis);
-               return 0;
-       }
-
-       /* default values */
-       varstr= pis->varstr;
-       for(a=0; a<pis->vars; a++, varstr++) {
-               if( (varstr->type & FLO)==FLO)
-                       pis->data[a]= varstr->def;
-               else if( (varstr->type & INT)==INT)
-                       *((int *)(pis->data+a))= (int) varstr->def;
-       }
+#include "RE_pipeline.h"               // talks to entire render API
 
-       return pis;
-}
+#include "blendef.h"
 
-void free_plugin_seq(PluginSeq *pis)
-{
+#include "BLI_threads.h"
+#include <pthread.h>
 
-       if(pis==0) return;
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
 
-       /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
-       MEM_freeN(pis);
-}
+int seqrectx, seqrecty;
 
-/* ***************** END PLUGIN ************************ */
+/* **********************************************************************
+   alloc / free functions
+   ********************************************************************** */
 
-void free_stripdata(int len, StripElem *se)
+void free_tstripdata(int len, TStripElem *se)
 {
-       StripElem *seo;
+       TStripElem *seo;
        int a;
 
        seo= se;
+       if (!se) {
+               return;
+       }
 
        for(a=0; a<len; a++, se++) {
-               if(se->ibuf && se->ok!=2) IMB_freeImBuf(se->ibuf);
+               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);
@@ -207,40 +115,97 @@ void free_strip(Strip *strip)
                return;
        }
 
-       if(strip->stripdata) {
-               free_stripdata(strip->len, strip->stripdata);
+       if (strip->stripdata) {
+               MEM_freeN(strip->stripdata);
+       }
+
+       if (strip->proxy) {
+               MEM_freeN(strip->proxy);
+       }
+       if (strip->crop) {
+               MEM_freeN(strip->crop);
+       }
+       if (strip->transform) {
+               MEM_freeN(strip->transform);
+       }
+       if (strip->color_balance) {
+               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);
 }
 
-void new_stripdata(Sequence *seq)
+void new_tstripdata(Sequence *seq)
 {
-
        if(seq->strip) {
-               if(seq->strip->stripdata) free_stripdata(seq->strip->len, seq->strip->stripdata);
-               seq->strip->stripdata= 0;
+               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;
-               if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelems");
        }
 }
 
 void free_sequence(Sequence *seq)
 {
-       extern Sequence *last_seq;
+       Sequence *last_seq = get_last_seq();
 
        if(seq->strip) free_strip(seq->strip);
-       if(seq->effectdata) MEM_freeN(seq->effectdata);
 
        if(seq->anim) IMB_free_anim(seq->anim);
+       if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
+
+       if (seq->type & SEQ_EFFECT) {
+               struct SeqEffectHandle sh = get_sequence_effect(seq);
 
-       free_plugin_seq(seq->plugin);
+               sh.free(seq);
+       }
 
-       if(seq==last_seq) last_seq= 0;
+       if(seq==last_seq) set_last_seq(NULL);
 
        MEM_freeN(seq);
 }
 
-void do_seq_count(ListBase *seqbase, int *totseq)
+/*
+  **********************************************************************
+  * build_seqar
+  **********************************************************************
+  * Build a complete array of _all_ sequencies (including those
+  * in metastrips!)
+  **********************************************************************
+*/
+
+static void do_seq_count(ListBase *seqbase, int *totseq)
 {
        Sequence *seq;
 
@@ -252,7 +217,7 @@ void do_seq_count(ListBase *seqbase, int *totseq)
        }
 }
 
-void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
+static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
 {
        Sequence *seq;
 
@@ -284,12 +249,73 @@ void build_seqar(ListBase *seqbase, Sequence  ***seqar, int *totseq)
        *seqar= tseqar;
 }
 
+static void do_seq_count_cb(ListBase *seqbase, int *totseq,
+                           int (*test_func)(Sequence * seq))
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               int test = test_func(seq);
+               if (test & BUILD_SEQAR_COUNT_CURRENT) {
+                       (*totseq)++;
+               }
+               if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
+                       do_seq_count_cb(&seq->seqbase, totseq, test_func);
+               }
+               seq= seq->next;
+       }
+}
+
+static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
+                             int (*test_func)(Sequence * seq))
+{
+       Sequence *seq;
+
+       seq= seqbase->first;
+       while(seq) {
+               int test = test_func(seq);
+               seq->depth= depth;
+
+               if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
+                       do_build_seqar_cb(&seq->seqbase, seqar, depth+1, 
+                                         test_func);
+               }
+               if (test & BUILD_SEQAR_COUNT_CURRENT) {
+                       **seqar= seq;
+                       (*seqar)++;
+               }
+               seq= seq->next;
+       }
+}
+
+void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
+                   int (*test_func)(Sequence * seq))
+{
+       Sequence **tseqar;
+
+       *totseq= 0;
+       do_seq_count_cb(seqbase, totseq, test_func);
+
+       if(*totseq==0) {
+               *seqar= 0;
+               return;
+       }
+       *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
+       tseqar= *seqar;
+
+       do_build_seqar_cb(seqbase, seqar, 0, test_func);
+       *seqar= tseqar;
+}
+
+
 void free_editing(Editing *ed)
 {
        MetaStack *ms;
        Sequence *seq;
 
-       if(ed==0) return;
+       if(ed==NULL) return;
+       set_last_seq(NULL);     /* clear_last_seq doesnt work, it screws up free_sequence */
 
        WHILE_SEQ(&ed->seqbase) {
                free_sequence(seq);
@@ -302,6 +328,24 @@ void free_editing(Editing *ed)
        }
 
        MEM_freeN(ed);
+
+}
+
+void calc_sequence_disp(Sequence *seq)
+{
+       if(seq->startofs && seq->startstill) seq->startstill= 0;
+       if(seq->endofs && seq->endstill) seq->endstill= 0;
+       
+       seq->startdisp= seq->start + seq->startofs - seq->startstill;
+       seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
+       
+       seq->handsize= 10.0;    /* 10 frames */
+       if( seq->enddisp-seq->startdisp < 10 ) {
+               seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
+       }
+       else if(seq->enddisp-seq->startdisp > 250) {
+               seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
+       }
 }
 
 void calc_sequence(Sequence *seq)
@@ -330,12 +374,16 @@ void calc_sequence(Sequence *seq)
                // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
                // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
 
-               seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
-               seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
-               seq->len= seq->enddisp - seq->startdisp;
+               if (seq->seq1) {
+                       seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
+                       seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
+                       seq->len= seq->enddisp - seq->startdisp;
+               } else {
+                       calc_sequence_disp(seq);
+               }
 
                if(seq->strip && seq->len!=seq->strip->len) {
-                       new_stripdata(seq);
+                       new_tstripdata(seq);
                }
 
        }
@@ -350,30 +398,125 @@ void calc_sequence(Sequence *seq)
                                        if(seqm->enddisp > max) max= seqm->enddisp;
                                        seqm= seqm->next;
                                }
-                               seq->start= min;
-                               seq->len= max-min;
+                               seq->start= min + seq->anim_startofs;
+                               seq->len = max-min;
+                               seq->len -= seq->anim_startofs;
+                               seq->len -= seq->anim_endofs;
 
                                if(seq->strip && seq->len!=seq->strip->len) {
-                                       new_stripdata(seq);
+                                       new_tstripdata(seq);
                                }
                        }
                }
+               calc_sequence_disp(seq);
+       }
+}
+
+void reload_sequence_new_file(Sequence * seq)
+{
+       char str[FILE_MAXDIR+FILE_MAXFILE];
+
+       if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
+             seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND ||
+             seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
+               return;
+       }
+
+       new_tstripdata(seq);
+
+       if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
+           seq->type != SEQ_IMAGE) {
+               strncpy(str, seq->strip->dir, FILE_MAXDIR-1);
+               strncat(str, seq->strip->stripdata->name, FILE_MAXFILE-1);
 
+               BLI_convertstringcode(str, G.sce);
+               BLI_convertstringframe(str, G.scene->r.cfra); /* TODO - is this needed? */
+               
+       }
+
+       if (seq->type == SEQ_IMAGE) {
+               /* Hack? */
+               int olen = MEM_allocN_len(seq->strip->stripdata) 
+                       / sizeof(struct StripElem);
+               seq->len = olen;
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_MOVIE) {
+               if(seq->anim) IMB_free_anim(seq->anim);
+               seq->anim = openanim(str, IB_rect);
 
-               if(seq->startofs && seq->startstill) seq->startstill= 0;
-               if(seq->endofs && seq->endstill) seq->endstill= 0;
+               if (!seq->anim) {
+                       return;
+               }
+       
+               seq->len = IMB_anim_get_duration(seq->anim);
+               
+               seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
+
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_HD_SOUND) {
+               if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
+               seq->hdaudio = sound_open_hdaudio(str);
 
-               seq->startdisp= seq->start + seq->startofs - seq->startstill;
-               seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
+               if (!seq->hdaudio) {
+                       return;
+               }
 
-               seq->handsize= 10.0;    /* 10 frames */
-               if( seq->enddisp-seq->startdisp < 20 ) {
-                       seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
+               seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS)
+                       - seq->anim_startofs - seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_RAM_SOUND) {
+               seq->len = (int) ( ((float)(seq->sound->streamlen-1)/
+                                   ((float)G.scene->audio.mixrate*4.0 ))
+                                  * FPS);
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
                }
-               else if(seq->enddisp-seq->startdisp > 250) {
-                       seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
+               seq->strip->len = seq->len;
+       } else if (seq->type == SEQ_SCENE) {
+               Scene * sce = G.main->scene.first;
+                int nr = 1;
+                while(sce) {
+                        if(nr == seq->scenenr) {
+                                break;
+                        }
+                        nr++;
+                        sce= sce->id.next;
+                }
+
+               if (sce) {
+                       seq->scene = sce;
+               } else {
+                       sce = seq->scene;
                }
+
+               strncpy(seq->name + 2, sce->id.name + 2, 
+                       sizeof(seq->name) - 2);
+
+               seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
+               seq->len -= seq->anim_startofs;
+               seq->len -= seq->anim_endofs;
+               if (seq->len < 0) {
+                       seq->len = 0;
+               }
+               seq->strip->len = seq->len;
        }
+
+       calc_sequence(seq);
 }
 
 void sort_seq()
@@ -446,1800 +589,2340 @@ void clear_scene_in_allseqs(Scene *sce)
        }
 }
 
-/* ***************** DO THE SEQUENCE ***************** */
-
-void do_alphaover_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+char *give_seqname_by_type(int type)
 {
-       int fac2, mfac, fac, fac4;
-       int xo, tempc;
-       char *rt1, *rt2, *rt;
+       switch(type) {
+       case SEQ_META:       return "Meta";
+       case SEQ_IMAGE:      return "Image";
+       case SEQ_SCENE:      return "Scene";
+       case SEQ_MOVIE:      return "Movie";
+       case SEQ_RAM_SOUND:  return "Audio (RAM)";
+       case SEQ_HD_SOUND:   return "Audio (HD)";
+       case SEQ_CROSS:      return "Cross";
+       case SEQ_GAMCROSS:   return "Gamma Cross";
+       case SEQ_ADD:        return "Add";
+       case SEQ_SUB:        return "Sub";
+       case SEQ_MUL:        return "Mul";
+       case SEQ_ALPHAOVER:  return "Alpha Over";
+       case SEQ_ALPHAUNDER: return "Alpha Under";
+       case SEQ_OVERDROP:   return "Over Drop";
+       case SEQ_WIPE:       return "Wipe";
+       case SEQ_GLOW:       return "Glow";
+       case SEQ_TRANSFORM:  return "Transform";
+       case SEQ_COLOR:      return "Color";
+       case SEQ_SPEED:      return "Speed";
+       default:
+               return 0;
+       }
+}
 
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+char *give_seqname(Sequence *seq)
+{
+       char * name = give_seqname_by_type(seq->type);
+
+       if (!name) {
+               if(seq->type<SEQ_EFFECT) {
+                       return seq->strip->dir;
+               } else if(seq->type==SEQ_PLUGIN) {
+                       if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) &&
+                          seq->plugin && seq->plugin->doit) {
+                               return seq->plugin->pname;
+                       } else {
+                               return "Plugin";
+                       }
+               } else {
+                       return "Effect";
+               }
+       }
+       return name;
+}
 
-       fac2= (int)(256.0*facf0);
-       fac4= (int)(256.0*facf1);
+/* ***************** DO THE SEQUENCE ***************** */
 
-       while(y--) {
+static void make_black_ibuf(ImBuf *ibuf)
+{
+       unsigned int *rect;
+       float *rect_float;
+       int tot;
 
-               x= xo;
-               while(x--) {
+       if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
 
-                       /* rt = rt1 over rt2  (alpha from rt1) */
+       tot= ibuf->x*ibuf->y;
 
-                       fac= fac2;
-                       mfac= 256 - ( (fac2*rt1[3])>>8 );
+       rect= ibuf->rect;
+       rect_float = ibuf->rect_float;
 
-                       if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                       else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                       else {
-                               tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
-                               if(tempc>255) rt[0]= 255; else rt[0]= tempc;
-                               tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
-                               if(tempc>255) rt[1]= 255; else rt[1]= tempc;
-                               tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
-                               if(tempc>255) rt[2]= 255; else rt[2]= tempc;
-                               tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
-                               if(tempc>255) rt[3]= 255; else rt[3]= tempc;
-                       }
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       if (rect) {
+               memset(rect,       0, tot * sizeof(char) * 4);
+       }
 
-               if(y==0) break;
-               y--;
+       if (rect_float) {
+               memset(rect_float, 0, tot * sizeof(float) * 4);
+       }
+}
 
-               x= xo;
-               while(x--) {
+static void multibuf(ImBuf *ibuf, float fmul)
+{
+       char *rt;
+       float *rt_float;
 
-                       fac= fac4;
-                       mfac= 256 - ( (fac4*rt1[3])>>8 );
+       int a, mul, icol;
 
-                       if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                       else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                       else {
-                               tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
-                               if(tempc>255) rt[0]= 255; else rt[0]= tempc;
-                               tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
-                               if(tempc>255) rt[1]= 255; else rt[1]= tempc;
-                               tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
-                               if(tempc>255) rt[2]= 255; else rt[2]= tempc;
-                               tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
-                               if(tempc>255) rt[3]= 255; else rt[3]= tempc;
-                       }
-                       rt1+= 4; rt2+= 4; rt+= 4;
+       mul= (int)(256.0*fmul);
+       rt= (char *)ibuf->rect;
+       rt_float = ibuf->rect_float;
+
+       if (rt) {
+               a= ibuf->x*ibuf->y;
+               while(a--) {
+
+                       icol= (mul*rt[0])>>8;
+                       if(icol>254) rt[0]= 255; else rt[0]= icol;
+                       icol= (mul*rt[1])>>8;
+                       if(icol>254) rt[1]= 255; else rt[1]= icol;
+                       icol= (mul*rt[2])>>8;
+                       if(icol>254) rt[2]= 255; else rt[2]= icol;
+                       icol= (mul*rt[3])>>8;
+                       if(icol>254) rt[3]= 255; else rt[3]= icol;
+                       
+                       rt+= 4;
+               }
+       }
+       if (rt_float) {
+               a= ibuf->x*ibuf->y;
+               while(a--) {
+                       rt_float[0] *= fmul;
+                       rt_float[1] *= fmul;
+                       rt_float[2] *= fmul;
+                       rt_float[3] *= fmul;
+                       
+                       rt_float += 4;
                }
        }
 }
 
-void do_alphaunder_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+static void do_effect(int cfra, Sequence *seq, TStripElem * se)
 {
-       int fac2, mfac, fac, fac4;
-       int xo;
-       char *rt1, *rt2, *rt;
-
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+       TStripElem *se1, *se2, *se3;
+       float fac, facf;
+       int x, y;
+       int early_out;
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
 
-       fac2= (int)(256.0*facf0);
-       fac4= (int)(256.0*facf1);
+       if (!sh.execute) { /* effect not supported in this version... */
+               make_black_ibuf(se->ibuf);
+               return;
+       }
 
-       while(y--) {
+       if(seq->ipo && seq->ipo->curve.first) {
+               do_seq_ipo(seq, cfra);
+               fac= seq->facf0;
+               facf= seq->facf1;
+       } else {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+       }
 
-               x= xo;
-               while(x--) {
+       if( !(G.scene->r.mode & R_FIELDS) ) facf = fac;
 
-                       /* rt = rt1 under rt2  (alpha from rt2) */
+       early_out = sh.early_out(seq, fac, facf);
 
-                       /* this complex optimalisation is because the
-                        * 'skybuf' can be crossed in
-                        */
-                       if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                       else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                       else {
-                               mfac= rt2[3];
-                               fac= (fac2*(256-mfac))>>8;
+       if (early_out == -1) { /* no input needed */
+               sh.execute(seq, cfra, fac, facf, 
+                          se->ibuf->x, se->ibuf->y, 
+                          0, 0, 0, se->ibuf);
+               return;
+       }
 
-                               if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                               else {
-                                       rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
-                                       rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
-                                       rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
-                                       rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
-                               }
-                       }
-                       rt1+= 4; rt2+= 4; rt+= 4;
+       switch (early_out) {
+       case 0:
+               if (se->se1==0 || se->se2==0 || se->se3==0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
                }
 
-               if(y==0) break;
-               y--;
+               se1= se->se1;
+               se2= se->se2;
+               se3= se->se3;
 
-               x= xo;
-               while(x--) {
-
-                       if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                       else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                       else {
-                               mfac= rt2[3];
-                               fac= (fac4*(256-mfac))>>8;
+               if (   (se1==0 || se2==0 || se3==0)
+                   || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
 
-                               if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
-                               else {
-                                       rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
-                                       rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
-                                       rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
-                                       rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
-                               }
-                       }
-                       rt1+= 4; rt2+= 4; rt+= 4;
+               break;
+       case 1:
+               if (se->se1 == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
                }
-       }
-}
 
+               se1= se->se1;
 
-void do_cross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
-       int fac1, fac2, fac3, fac4;
-       int xo;
-       char *rt1, *rt2, *rt;
+               if (se1 == 0 || se1->ibuf == 0) {
+                       make_black_ibuf(se->ibuf);
+                       return;
+               }
 
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+               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;
+               }
 
-       fac2= (int)(256.0*facf0);
-       fac1= 256-fac2;
-       fac4= (int)(256.0*facf1);
-       fac3= 256-fac4;
+               se2= se->se2;
 
-       while(y--) {
+               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= xo;
-               while(x--) {
+       x= se2->ibuf->x;
+       y= se2->ibuf->y;
 
-                       rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
-                       rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
-                       rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
-                       rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
+       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);
+       }
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       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(y==0) break;
-               y--;
+       sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
+                  se->ibuf);
+}
 
-               x= xo;
-               while(x--) {
+static int give_stripelem_index(Sequence *seq, int cfra)
+{
+       int nr;
 
-                       rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
-                       rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
-                       rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
-                       rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
+       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 {
+               if(cfra <= seq->start) nr= 0;
+               else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
+               else nr= cfra-seq->start;
+       }
+       if (seq->strobe < 1.0) seq->strobe = 1.0;
+       if (seq->strobe > 1.0) {
+               nr -= (int)fmod((double)nr, (double)seq->strobe);
+       }
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       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;
 }
 
-void do_gammacross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+TStripElem *give_tstripelem(Sequence *seq, int cfra)
 {
-       int fac1, fac2, col;
-       int xo;
-       char *rt1, *rt2, *rt;
+       TStripElem *se;
+       int nr;
 
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+       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);
 
-       fac2= (int)(256.0*facf0);
-       fac1= 256-fac2;
+       if (nr == -1) return 0;
+       if (se == 0) return 0;
 
-       while(y--) {
+       se += nr; 
 
-               x= xo;
-               while(x--) {
+       /* 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;
+                       }
 
-                       col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
-                       if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
-                       if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
-                       if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
-                       if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+                       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;
+                       }
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
+                       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;
                }
+       }
 
-               if(y==0) break;
-               y--;
+       
+       se->nr= nr;
+
+       return se;
+}
 
-               x= xo;
-               while(x--) {
+StripElem *give_stripelem(Sequence *seq, int cfra)
+{
+       StripElem *se;
+       int nr;
 
-                       col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
-                       if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
-                       if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
-                       if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-                       col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
-                       if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+       se = seq->strip->stripdata;
+       nr = give_stripelem_index(seq, cfra);
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       if (nr == -1) return 0;
+       if (se == 0) return 0;
 
-       }
+       se += nr + seq->anim_startofs; 
+       
+       return se;
 }
 
-void do_add_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+static int evaluate_seq_frame_gen(
+       Sequence ** seq_arr, ListBase *seqbase, int cfra)
 {
-       int col, xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
-
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+       Sequence *seq;
+       int totseq=0;
 
-       fac1= (int)(256.0*facf0);
-       fac3= (int)(256.0*facf1);
+       memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1));
 
-       while(y--) {
+       seq= seqbase->first;
+       while(seq) {
+               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+                       seq_arr[seq->machine]= seq;
+                       totseq++;
+               }
+               seq= seq->next;
+       }
+
+       return totseq;
+}
 
-               x= xo;
-               while(x--) {
+int evaluate_seq_frame(int cfra)
+{
+       Editing *ed;
+       Sequence *seq_arr[MAXSEQ+1];
 
-                       col= rt1[0]+ ((fac1*rt2[0])>>8);
-                       if(col>255) rt[0]= 255; else rt[0]= col;
-                       col= rt1[1]+ ((fac1*rt2[1])>>8);
-                       if(col>255) rt[1]= 255; else rt[1]= col;
-                       col= rt1[2]+ ((fac1*rt2[2])>>8);
-                       if(col>255) rt[2]= 255; else rt[2]= col;
-                       col= rt1[3]+ ((fac1*rt2[3])>>8);
-                       if(col>255) rt[3]= 255; else rt[3]= col;
+       ed= G.scene->ed;
+       if(ed==0) return 0;
+       
+       return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra);
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+}
 
-               if(y==0) break;
-               y--;
+static int video_seq_is_rendered(Sequence * seq)
+{
+       return (seq 
+               && !(seq->flag & SEQ_MUTE) 
+               && seq->type != SEQ_RAM_SOUND 
+               && seq->type != SEQ_HD_SOUND);
+}
 
-               x= xo;
-               while(x--) {
+static int get_shown_sequences(
+       ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
+{
+       Sequence *seq_arr[MAXSEQ+1];
+       int b = chanshown;
+       int cnt = 0;
 
-                       col= rt1[0]+ ((fac3*rt2[0])>>8);
-                       if(col>255) rt[0]= 255; else rt[0]= col;
-                       col= rt1[1]+ ((fac3*rt2[1])>>8);
-                       if(col>255) rt[1]= 255; else rt[1]= col;
-                       col= rt1[2]+ ((fac3*rt2[2])>>8);
-                       if(col>255) rt[2]= 255; else rt[2]= col;
-                       col= rt1[3]+ ((fac3*rt2[3])>>8);
-                       if(col>255) rt[3]= 255; else rt[3]= col;
+       if (b > MAXSEQ) {
+               return 0;
+       }
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
+       if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
+               if (b > 0) {
+                       if (seq_arr[b] == 0) {
+                               return 0;
+                       }
+               } else {
+                       for (b = MAXSEQ; b > 0; b--) {
+                               if (video_seq_is_rendered(seq_arr[b])) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       
+       chanshown = b;
+
+       for (;b > 0; b--) {
+               if (video_seq_is_rendered(seq_arr[b])) {
+                       if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
+                               break;
+                       }
                }
        }
+
+       for (;b <= chanshown; b++) {
+               if (video_seq_is_rendered(seq_arr[b])) {
+                       seq_arr_out[cnt++] = seq_arr[b];
+               }
+       }
+
+       return cnt;
 }
+
+/* **********************************************************************
+   proxy management
+   ********************************************************************** */
+
+#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 
-void do_sub_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+static int seq_proxy_get_fname(Sequence * seq, int cfra, char * name)
 {
-       int col, xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
+       int frameno;
+       char dir[FILE_MAXDIR];
 
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+       if (!seq->strip->proxy) {
+               return FALSE;
+       }
 
-       fac1= (int)(256.0*facf0);
-       fac3= (int)(256.0*facf1);
+       if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
+               strcpy(dir, seq->strip->proxy->dir);
+       } else {
+               if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
+                       snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", 
+                                seq->strip->dir);
+               } else {
+                       return FALSE;
+               }
+       }
 
-       while(y--) {
+       /* generate a seperate proxy directory for each preview size */
 
-               x= xo;
-               while(x--) {
+       if (seq->type == SEQ_IMAGE) {
+               StripElem * se = give_stripelem(seq, cfra);
+               snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy",
+                        dir, G.scene->r.size, se->name);
+               frameno = 1;
+       } else if (seq->type == SEQ_MOVIE) {
+               TStripElem * tse = give_tstripelem(seq, cfra);
 
-                       col= rt1[0]- ((fac1*rt2[0])>>8);
-                       if(col<0) rt[0]= 0; else rt[0]= col;
-                       col= rt1[1]- ((fac1*rt2[1])>>8);
-                       if(col<0) rt[1]= 0; else rt[1]= col;
-                       col= rt1[2]- ((fac1*rt2[2])>>8);
-                       if(col<0) rt[2]= 0; else rt[2]= col;
-                       col= rt1[3]- ((fac1*rt2[3])>>8);
-                       if(col<0) rt[3]= 0; else rt[3]= col;
+               frameno = tse->nr + seq->anim_startofs;
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+               snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
+                        seq->strip->stripdata->name,
+                        G.scene->r.size);
+       } else {
+               TStripElem * tse = give_tstripelem(seq, cfra);
 
-               if(y==0) break;
-               y--;
+               frameno = tse->nr + seq->anim_startofs;
 
-               x= xo;
-               while(x--) {
+               snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
+                        G.scene->r.size);
+       }
 
-                       col= rt1[0]- ((fac3*rt2[0])>>8);
-                       if(col<0) rt[0]= 0; else rt[0]= col;
-                       col= rt1[1]- ((fac3*rt2[1])>>8);
-                       if(col<0) rt[1]= 0; else rt[1]= col;
-                       col= rt1[2]- ((fac3*rt2[2])>>8);
-                       if(col<0) rt[2]= 0; else rt[2]= col;
-                       col= rt1[3]- ((fac3*rt2[3])>>8);
-                       if(col<0) rt[3]= 0; else rt[3]= col;
+       BLI_convertstringcode(name, G.sce);
+       BLI_convertstringframe(name, frameno);
+       
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       strcat(name, ".jpg");
+
+       return TRUE;
+}
+
+static struct ImBuf * seq_proxy_fetch(Sequence * seq, int cfra)
+{
+       char name[PROXY_MAXFILE];
+
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return 0;
+       }
+
+       /* rendering at 100% ? No real sense in proxy-ing, right? */
+       if (G.scene->r.size == 100.0) {
+               return 0;
+       }
+
+       if (!seq_proxy_get_fname(seq, cfra, name)) {
+               return 0;
+       }
+
+       if (BLI_exists(name)) {
+               return IMB_loadiffname(name, IB_rect);
+       } else {
+               return 0;
        }
 }
 
-/* Must be > 0 or add precopy, etc to the function */
-#define XOFF   8
-#define YOFF   8
+static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
+                             int build_proxy_run);
 
-void do_drop_effect(float facf0, float facf1, int x, int y, unsigned int *rect2i, unsigned int *rect1i, unsigned int *outi)
+static void seq_proxy_build_frame(Sequence * seq, int cfra)
 {
-       int height, width, temp, fac, fac1, fac2;
-       char *rt1, *rt2, *out;
-       int field= 1;
+       char name[PROXY_MAXFILE];
+       int quality;
+       TStripElem * se;
+       int ok;
+       int rectx, recty;
+       struct ImBuf * ibuf;
+
+       if (!(seq->flag & SEQ_USE_PROXY)) {
+               return;
+       }
+
+       /* rendering at 100% ? No real sense in proxy-ing, right? */
+       if (G.scene->r.size == 100.0) {
+               return;
+       }
 
-       width= x;
-       height= y;
+       if (!seq_proxy_get_fname(seq, cfra, name)) {
+               return;
+       }
 
-       fac1= (int)(70.0*facf0);
-       fac2= (int)(70.0*facf1);
+       se = give_tstripelem(seq, cfra);
+       if (!se) {
+               return;
+       }
+
+       if(se->ibuf) {
+               IMB_freeImBuf(se->ibuf);
+               se->ibuf = 0;
+       }
+       
+       do_build_seq_ibuf(seq, se, cfra, TRUE);
 
-       rt2= (char*) (rect2i + YOFF*width);
-       rt1= (char*) rect1i;
-       out= (char*) outi;
-       for (y=0; y<height-YOFF; y++) {
-               if(field) fac= fac1;
-               else fac= fac2;
-               field= !field;
+       if (!se->ibuf) {
+               return;
+       }
 
-               memcpy(out, rt1, sizeof(int)*XOFF);
-               rt1+= XOFF*4;
-               out+= XOFF*4;
+       rectx= (G.scene->r.size*G.scene->r.xsch)/100;
+       recty= (G.scene->r.size*G.scene->r.ysch)/100;
 
-               for (x=XOFF; x<width; x++) {
-                       temp= ((fac*rt2[3])>>8);
+       ibuf = se->ibuf;
 
-                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
-                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
-                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
-                       *(out++)= MAX2(0, *rt1 - temp); rt1++;
-                       rt2+=4;
-               }
-               rt2+=XOFF*4;
+       if (ibuf->x != rectx || ibuf->y != recty) {
+               IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
        }
-       memcpy(out, rt1, sizeof(int)*YOFF*width);
-}
 
-                                               /* WATCH:  rect2 and rect1 reversed */
-void do_drop_effect2(float facf0, float facf1, int x, int y, unsigned int *rect2, unsigned int *rect1, unsigned int *out)
-{
-       int col, xo, yo, temp, fac1, fac3;
-       int xofs= -8, yofs= 8;
-       char *rt1, *rt2, *rt;
+       /* quality is fixed, otherwise one has to generate seperate
+          directories for every quality...
 
-       xo= x;
-       yo= y;
+          depth = 32 is intentionally left in, otherwise ALPHA channels
+          won't work... */
+       quality = 90;
+       ibuf->ftype= JPG | quality;
 
-       rt2= (char *)(rect2 + yofs*x + xofs);
+       BLI_make_existing_file(name);
+       
+       ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
+       if (ok == 0) {
+               perror(name);
+       }
 
-       rt1= (char *)rect1;
-       rt= (char *)out;
+       IMB_freeImBuf(ibuf);
+       se->ibuf = 0;
+}
 
-       fac1= (int)(70.0*facf0);
-       fac3= (int)(70.0*facf1);
+void seq_proxy_rebuild(Sequence * seq)
+{
+       int cfra;
 
-       while(y-- > 0) {
+       waitcursor(1);
 
-               temp= y-yofs;
-               if(temp > 0 && temp < yo) {
+       G.afbreek = 0;
 
-                       x= xo;
-                       while(x--) {
+       /* flag management tries to account for strobe and 
+          other "non-linearities", that might come in the future...
+          better way would be to "touch" the files, so that _really_
+          no one is rebuild twice.
+        */
 
-                               temp= x+xofs;
-                               if(temp > 0 && temp < xo) {
+       for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
+               TStripElem * tse = give_tstripelem(seq, cfra);
 
-                                       temp= ((fac1*rt2[3])>>8);
+               tse->flag &= ~STRIPELEM_PREVIEW_DONE;
+       }
 
-                                       col= rt1[0]- temp;
-                                       if(col<0) rt[0]= 0; else rt[0]= col;
-                                       col= rt1[1]- temp;
-                                       if(col<0) rt[1]= 0; else rt[1]= col;
-                                       col= rt1[2]- temp;
-                                       if(col<0) rt[2]= 0; else rt[2]= col;
-                                       col= rt1[3]- temp;
-                                       if(col<0) rt[3]= 0; else rt[3]= col;
-                               }
-                               else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+       /* a _lot_ faster for movie files, if we read frames in
+          sequential order */
+       if (seq->flag & SEQ_REVERSE_FRAMES) {
+               for (cfra = seq->enddisp-seq->endstill-1; 
+                    cfra >= seq->startdisp + seq->startstill; cfra--) {
+                       TStripElem * tse = give_tstripelem(seq, cfra);
 
-                               rt1+= 4; rt2+= 4; rt+= 4;
+                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
+                               seq_proxy_build_frame(seq, cfra);
+                               tse->flag |= STRIPELEM_PREVIEW_DONE;
+                       }
+                       if (blender_test_break()) {
+                               break;
                        }
                }
-               else {
-                       x= xo;
-                       while(x--) {
-                               *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                               rt1+= 4; rt2+= 4; rt+= 4;
+       } else {
+               for (cfra = seq->startdisp + seq->startstill; 
+                    cfra < seq->enddisp - seq->endstill; cfra++) {
+                       TStripElem * tse = give_tstripelem(seq, cfra);
+
+                       if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
+                               seq_proxy_build_frame(seq, cfra);
+                               tse->flag |= STRIPELEM_PREVIEW_DONE;
+                       }
+                       if (blender_test_break()) {
+                               break;
                        }
                }
+       }
+       waitcursor(0);
+}
 
-               if(y==0) break;
-               y--;
-
-               temp= y-yofs;
-               if(temp > 0 && temp < yo) {
-
-                       x= xo;
-                       while(x--) {
-
-                               temp= x+xofs;
-                               if(temp > 0 && temp < xo) {
 
-                                       temp= ((fac3*rt2[3])>>8);
+/* **********************************************************************
+   color balance 
+   ********************************************************************** */
 
-                                       col= rt1[0]- temp;
-                                       if(col<0) rt[0]= 0; else rt[0]= col;
-                                       col= rt1[1]- temp;
-                                       if(col<0) rt[1]= 0; else rt[1]= col;
-                                       col= rt1[2]- temp;
-                                       if(col<0) rt[2]= 0; else rt[2]= col;
-                                       col= rt1[3]- temp;
-                                       if(col<0) rt[3]= 0; else rt[3]= col;
-                               }
-                               else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+static StripColorBalance calc_cb(StripColorBalance * cb_)
+{
+       StripColorBalance cb = *cb_;
+       int c;
 
-                               rt1+= 4; rt2+= 4; rt+= 4;
+       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] = -(1.0 - cb.lift[c]);
+               }
+       }
+       if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
+               for (c = 0; c < 3; c++) {
+                       if (cb.gain[c] != 0.0) {
+                               cb.gain[c] = 1.0/cb.gain[c];
+                       } else {
+                               cb.gain[c] = 1000000; /* should be enough :) */
                        }
                }
-               else {
-                       x= xo;
-                       while(x--) {
-                               *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-                               rt1+= 4; rt2+= 4; rt+= 4;
+       }
+
+       if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
+               for (c = 0; c < 3; c++) {
+                       if (cb.gamma[c] != 0.0) {
+                               cb.gamma[c] = 1.0/cb.gamma[c];
+                       } else {
+                               cb.gamma[c] = 1000000; /* should be enough :) */
                        }
                }
        }
+
+       return cb;
 }
 
+static void make_cb_table_byte(float lift, float gain, float gamma,
+                              unsigned char * table, float mul)
+{
+       int y;
+
+       for (y = 0; y < 256; y++) {
+               float v = 1.0 * y / 255;
+               v += lift; 
+               v *= gain;
+               v = pow(v, gamma);
+               v *= mul;
+               if ( v > 1.0) {
+                       v = 1.0;
+               } else if (v < 0.0) {
+                       v = 0.0;
+               }
+               table[y] = v * 255;
+       }
 
-void do_mul_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+}
+
+static void make_cb_table_float(float lift, float gain, float gamma,
+                               float * table, float mul)
 {
-       int  xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
+       int y;
+
+       for (y = 0; y < 256; y++) {
+               float v = (float) y * 1.0 / 255.0;
+               v += lift;
+               v *= gain;
+               v = pow(v, gamma);
+               v *= mul;
+               table[y] = v;
+       }
+}
 
-       xo= x;
-       rt1= (char *)rect1;
-       rt2= (char *)rect2;
-       rt= (char *)out;
+static void color_balance_byte_byte(Sequence * seq, TStripElem* se,
+                                   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;
 
-       fac1= (int)(256.0*facf0);
-       fac3= (int)(256.0*facf1);
+       StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
-       /* formula:
-        *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+a
-        */
+       for (c = 0; c < 3; c++) {
+               make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c],
+                                  cb_tab[c], mul);
+       }
 
-       while(y--) {
+       while (p < e) {
+               p[0] = cb_tab[0][p[0]];
+               p[1] = cb_tab[1][p[1]];
+               p[2] = cb_tab[2][p[2]];
+               
+               p += 4;
+       }
+}
 
-               x= xo;
-               while(x--) {
+static void color_balance_byte_float(Sequence * seq, TStripElem* se,
+                                    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;
+       float * o;
+       StripColorBalance cb;
 
-                       rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
-                       rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
-                       rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
-                       rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
+       imb_addrectfloatImBuf(se->ibuf);
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
-               }
+       o = se->ibuf->rect_float;
+
+       cb = calc_cb(seq->strip->color_balance);
 
-               if(y==0) break;
-               y--;
+       for (c = 0; c < 3; c++) {
+               make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
+                                   cb_tab[c], mul);
+       }
+
+       for (i = 0; i < 256; i++) {
+               cb_tab[3][i] = ((float)i)*(1.0f/255.0f);
+       }
 
-               x= xo;
-               while(x--) {
+       while (p < e) {
+               o[0] = cb_tab[0][p[0]];
+               o[1] = cb_tab[1][p[1]];
+               o[2] = cb_tab[2][p[2]];
+               o[3] = cb_tab[3][p[3]];
 
-                       rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
-                       rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
-                       rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
-                       rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
+               p += 4; o += 4;
+       }
+}
 
-                       rt1+= 4; rt2+= 4; rt+= 4;
+static void color_balance_float_float(Sequence * seq, TStripElem* se,
+                                     float mul)
+{
+       float * p = se->ibuf->rect_float;
+       float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->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.lift[c]) * cb.gain[c], 
+                                  cb.gamma[c]) * mul;
                }
+               p += 4;
        }
 }
 
-// This function calculates the blur band for the wipe effects
-float in_band(float width,float dist, float perc,int side,int dir){
-       
-       float t1,t2,alpha,percwidth;
-       if(width == 0)
-               return (float)side;
-       if(side == 1)
-               percwidth = width * perc;
-       else
-               percwidth = width * (1 - perc);
-       
-       if(width < dist)
-               return side;
-       
-       t1 = dist / width;  //percentange of width that is
-       t2 = 1 / width;  //amount of alpha per % point
-       
-       if(side == 1)
-               alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
-       else
-               alpha = (1-perc) - (t1*t2*100);
-       
-       if(dir == 0)
-               alpha = 1-alpha;
-       return alpha;
-}
-
-float check_zone(int x, int y, int xo, int yo, Sequence *seq, float facf0) {
-
-   float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
-   /*some future stuff
-   float hyp3,hyp4,b4,b5          
-   */
-   float temp1,temp2,temp3,temp4; //some placeholder variables
-   float halfx = xo/2;
-   float halfy = yo/2;
-   float widthf,output=0;
-   WipeVars *wipe = (WipeVars *)seq->effectdata;
-   int width;
-
-       angle = wipe->angle;
-       if(angle < 0){
-               x = xo-x;
-               //y = yo-y
-               }
-       angle = pow(fabs(angle)/45,log(xo)/log(2));
-
-       posy = facf0 * yo;
-       if(wipe->forward){
-               posx = facf0 * xo;
-               posy = facf0 * yo;
-       } else{
-               posx = xo - facf0 * xo;
-               posy = yo - facf0 * yo;
-       }
-   switch (wipe->wipetype) {
-       case DO_SINGLE_WIPE:
-         width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
-         hwidth = (float)width/2.0;       
-                
-         if (angle == 0.0)angle = 0.000001;
-         b1 = posy - (-angle)*posx;
-         b2 = y - (-angle)*x;
-         hyp  = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1);
-         if(angle < 0){
-                temp1 = b1;
-                b1 = b2;
-                b2 = temp1;
-         }
-         if(wipe->forward){     
-                    if(b1 < b2)
-                               output = in_band(width,hyp,facf0,1,1);
-                else
-                               output = in_band(width,hyp,facf0,0,1);
-                }
-                else{   
-                if(b1 < b2)
-                               output = in_band(width,hyp,facf0,0,1);
-                else
-                               output = in_band(width,hyp,facf0,1,1);
-                }
-                break;
-        
-        
-         case DO_DOUBLE_WIPE:
-                if(!wipe->forward)facf0 = 1-facf0;   // Go the other direction
-
-            width = (int)(wipe->edgeWidth*((xo+yo)/2.0));  // calculate the blur width
-            hwidth = (float)width/2.0;       
-            if (angle == 0)angle = 0.000001;
-            b1 = posy/2 - (-angle)*posx/2;
-            b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
-            b2 = y - (-angle)*x;
-
-            hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
-            hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-            
-            temp1 = xo*(1-facf0/2)-xo*facf0/2;
-            temp2 = yo*(1-facf0/2)-yo*facf0/2;
-                pointdist = sqrt(temp1*temp1 + temp2*temp2);
-
-                        if(b2 < b1 && b2 < b3 ){
-                               if(hwidth < pointdist)
-                                       output = in_band(hwidth,hyp,facf0,0,1);
-                       }
-                        else if(b2 > b1 && b2 > b3 ){
-                               if(hwidth < pointdist)
-                                       output = in_band(hwidth,hyp2,facf0,0,1);        
-                       } 
-                    else{
-                        if(  hyp < hwidth && hyp2 > hwidth )
-                                output = in_band(hwidth,hyp,facf0,1,1);
-                        else if(  hyp > hwidth && hyp2 < hwidth )
-                                        output = in_band(hwidth,hyp2,facf0,1,1);
-                                else
-                                        output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
-                    }
-                    if(!wipe->forward)output = 1-output;
-        break;     
-        case DO_CLOCK_WIPE:
-                       /*
-                               temp1: angle of effect center in rads
-                               temp2: angle of line through (halfx,halfy) and (x,y) in rads
-                               temp3: angle of low side of blur
-                               temp4: angle of high side of blur
-                       */
-                       output = 1-facf0;
-                       widthf = wipe->edgeWidth*2*3.14159;
-                       temp1 = 2 * 3.14159 * facf0;
-                       
-                       if(wipe->forward){
-                               temp1 = 2*3.14159-temp1;
-                       }
-                       
-                       x = x - halfx;
-                       y = y - halfy;
-
-                       temp2 = asin(abs(y)/sqrt(x*x + y*y));
-                       if(x <= 0 && y >= 0)
-                               temp2 = 3.14159 - temp2;
-                       else if(x<=0 && y <= 0)
-                               temp2 += 3.14159;
-                       else if(x >= 0 && y <= 0)
-                               temp2 = 2*3.14159 - temp2;
-                       
-                       if(wipe->forward){
-                               temp3 = temp1-(widthf/2)*facf0;
-                               temp4 = temp1+(widthf/2)*(1-facf0);
-                       }
-                       else{
-                               temp3 = temp1-(widthf/2)*(1-facf0);
-                               temp4 = temp1+(widthf/2)*facf0;
-                       }
-                       if (temp3 < 0)  temp3 = 0;
-                       if (temp4 > 2*3.14159) temp4 = 2*3.14159;
-                       
-                       
-                       if(temp2 < temp3)
-                               output = 0;
-                       else if (temp2 > temp4)
-                               output = 1;
-                       else
-                               output = (temp2-temp3)/(temp4-temp3);
-                       if(x == 0 && y == 0){
-                               output = 1;
-                       }
-                       if(output != output)
-                               output = 1;
-                       if(wipe->forward)
-                               output = 1 - output;
-       break;
-       /* BOX WIPE IS NOT WORKING YET */
-     /* case DO_CROSS_WIPE: */
-       /* BOX WIPE IS NOT WORKING YET */
-     /* case DO_BOX_WIPE: 
-                if(invert)facf0 = 1-facf0;
-
-            width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
-            hwidth = (float)width/2.0;       
-            if (angle == 0)angle = 0.000001;
-            b1 = posy/2 - (-angle)*posx/2;
-            b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
-            b2 = y - (-angle)*x;
-
-            hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
-            hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-            
-            temp1 = xo*(1-facf0/2)-xo*facf0/2;
-            temp2 = yo*(1-facf0/2)-yo*facf0/2;
-                pointdist = sqrt(temp1*temp1 + temp2*temp2);
-
-                        if(b2 < b1 && b2 < b3 ){
-                               if(hwidth < pointdist)
-                                       output = in_band(hwidth,hyp,facf0,0,1);
-                       }
-                        else if(b2 > b1 && b2 > b3 ){
-                               if(hwidth < pointdist)
-                                       output = in_band(hwidth,hyp2,facf0,0,1);        
-                       } 
-                    else{
-                        if(  hyp < hwidth && hyp2 > hwidth )
-                                output = in_band(hwidth,hyp,facf0,1,1);
-                        else if(  hyp > hwidth && hyp2 < hwidth )
-                                        output = in_band(hwidth,hyp2,facf0,1,1);
-                                else
-                                        output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
-                    }
-                if(invert)facf0 = 1-facf0;
-            angle = -1/angle;
-            b1 = posy/2 - (-angle)*posx/2;
-            b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
-            b2 = y - (-angle)*x;
-
-            hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
-            hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-          
-                if(b2 < b1 && b2 < b3 ){
-                               if(hwidth < pointdist)
-                                       output *= in_band(hwidth,hyp,facf0,0,1);
-                       }
-                        else if(b2 > b1 && b2 > b3 ){
-                               if(hwidth < pointdist)
-                                       output *= in_band(hwidth,hyp2,facf0,0,1);       
-                       } 
-                    else{
-                        if(  hyp < hwidth && hyp2 > hwidth )
-                                output *= in_band(hwidth,hyp,facf0,1,1);
-                        else if(  hyp > hwidth && hyp2 < hwidth )
-                                        output *= in_band(hwidth,hyp2,facf0,1,1);
-                                else
-                                        output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
-                    }
-                    
-        break;*/
-      case DO_IRIS_WIPE:
-        if(xo > yo) yo = xo;
-        else xo = yo;
-        
-               if(!wipe->forward)
-                       facf0 = 1-facf0;
-
-            width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
-            hwidth = (float)width/2.0; 
-            
-        temp1 = (halfx-(halfx)*facf0);     
-                pointdist = sqrt(temp1*temp1 + temp1*temp1);
-                
-                temp2 = sqrt((halfx-x)*(halfx-x)  +  (halfy-y)*(halfy-y));
-                if(temp2 > pointdist)
-                        output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1);
-                else
-                        output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1);
-                
-               if(!wipe->forward)
-                       output = 1-output;
-                       
-        break;
-   }
-   if     (output < 0) output = 0;
-   else if(output > 1) output = 1;
-   return output;
+static void color_balance(Sequence * seq, TStripElem* se, float mul)
+{
+       if (se->ibuf->rect_float) {
+               color_balance_float_float(seq, se, mul);
+       } else if(seq->flag & SEQ_MAKE_FLOAT) {
+               color_balance_byte_float(seq, se, mul);
+       } else {
+               color_balance_byte_byte(seq, se, mul);
+       }
 }
 
-void init_wipe_effect(Sequence *seq)
+/*
+  input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE
+
+  Do all the things you can't really do afterwards using sequence effects
+  (read: before rescaling to render resolution has been done)
+
+  Order is important!
+
+  - Deinterlace
+  - Crop and transform in image source coordinate space
+  - 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)
+  - Premultiply
+
+*/
+
+static int input_have_to_preprocess(Sequence * seq, TStripElem* se, int cfra)
 {
-       if(seq->effectdata)MEM_freeN(seq->effectdata);
-       seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
+       float mul;
+
+       if ((seq->flag & SEQ_FILTERY) || 
+           (seq->flag & SEQ_USE_CROP) ||
+           (seq->flag & SEQ_USE_TRANSFORM) ||
+           (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)) {
+               return TRUE;
+       }
+
+       mul = seq->mul;
+
+       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+               if (seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(seq, cfra);
+                       mul *= seq->facf0;
+               }
+               mul *= seq->blend_opacity / 100.0;
+       }
+
+       if (mul != 1.0) {
+               return TRUE;
+       }
+               
+       return FALSE;
 }
 
-void do_wipe_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+static void input_preprocess(Sequence * seq, TStripElem* se, int cfra)
 {
-       int xo, yo;
-       char *rt1, *rt2, *rt;
-       rt1 = (char *)rect1;
-       rt2 = (char *)rect2;
-       rt = (char *)out;
+       float mul;
 
-       xo = x;
-       yo = y;
-       for(y=0;y<yo;y++) {
+       seq->strip->orx= se->ibuf->x;
+       seq->strip->ory= se->ibuf->y;
 
-      for(x=0;x<xo;x++) {
-                       float check = check_zone(x,y,xo,yo,seq,facf0);
-                       if (check) {
-                               if (rt1) {
-                                       rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
-                                       rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
-                                       rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
-                                       rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
-                               } else {
-                                       rt[0] = 0;
-                                       rt[1] = 0;
-                                       rt[2] = 0;
-                                       rt[3] = 255;
-                               }
-                       } else {
-                               if (rt2) {
-                                       rt[0] = rt2[0];
-                                       rt[1] = rt2[1];
-                                       rt[2] = rt2[2];
-                                       rt[3] = rt2[3];
-                               } else {
-                                       rt[0] = 0;
-                                       rt[1] = 0;
-                                       rt[2] = 0;
-                                       rt[3] = 255;
-                               }
-                       }
+       if(seq->flag & SEQ_FILTERY) {
+               IMB_filtery(se->ibuf);
+       }
+
+       if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
+               StripCrop c;
+               StripTransform t;
 
-                       rt+=4;
-                       if(rt1 !=NULL){
-                               rt1+=4;
+               memset(&c, 0, sizeof(StripCrop));
+               memset(&t, 0, sizeof(StripTransform));
+
+               if(seq->flag & SEQ_USE_CROP && seq->strip->crop) {
+                       c = *seq->strip->crop;
+               }
+               if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) {
+                       t = *seq->strip->transform;
+               }
+
+               if (c.top + c.bottom >= se->ibuf->y ||
+                   c.left + c.right >= se->ibuf->x ||
+                   t.xofs >= se->ibuf->x ||
+                   t.yofs >= se->ibuf->y) {
+                       make_black_ibuf(se->ibuf);
+               } else {
+                       ImBuf * i;
+                       int sx = se->ibuf->x - c.left - c.right;
+                       int sy = se->ibuf->y - c.top - c.bottom;
+                       int dx = sx;
+                       int dy = sy;
+
+                       if (seq->flag & SEQ_USE_TRANSFORM) {
+                               dx = seqrectx;
+                               dy = seqrecty;
                        }
-                       if(rt2 !=NULL){
-                               rt2+=4;
+
+                       if (se->ibuf->rect_float) {
+                               i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
+                       } else {
+                               i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
                        }
+
+                       IMB_rectcpy(i, se->ibuf, 
+                                   t.xofs, t.yofs, 
+                                   c.left, c.bottom, 
+                                   sx, sy);
+
+                       IMB_freeImBuf(se->ibuf);
+
+                       se->ibuf = i;
                }
-       }
-}
+       } 
 
-/* Glow Functions */
+       if(seq->flag & SEQ_FLIPX) {
+               IMB_flipx(se->ibuf);
+       }
+       if(seq->flag & SEQ_FLIPY) {
+               IMB_flipy(se->ibuf);
+       }
 
-void RVBlurBitmap2 ( unsigned char* map, int width,int height,float blur,
-   int quality)
-/*     MUUUCCH better than the previous blur. */
-/*     We do the blurring in two passes which is a whole lot faster. */
-/*     I changed the math arount to implement an actual Gaussian */
-/*     distribution. */
-/* */
-/*     Watch out though, it tends to misbehaven with large blur values on */
-/*     a small bitmap.  Avoid avoid avoid. */
-/*=============================== */
-{
-       unsigned char*  temp=NULL,*swap;
-       float   *filter=NULL;
-       int     x,y,i,fx,fy;
-       int     index, ix, halfWidth;
-       float   fval, k, curColor[3], curColor2[3], weight=0;
+       if(seq->mul == 0.0) {
+               seq->mul = 1.0;
+       }
 
-       /*      If we're not really blurring, bail out */
-       if (blur<=0)
-               return;
+       mul = seq->mul;
 
-       /*      Allocate memory for the tempmap and the blur filter matrix */
-       temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
-       if (!temp)
-               return;
+       if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+               if (seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(seq, cfra);
+                       mul *= seq->facf0;
+               }
+               mul *= seq->blend_opacity / 100.0;
+       }
 
-       /*      Allocate memory for the filter elements */
-       halfWidth = ((quality+1)*blur);
-       filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
-       if (!filter){
-               MEM_freeN (temp);
-               return;
+       if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
+               color_balance(seq, se, mul);
+               mul = 1.0;
        }
 
-       /*      Apparently we're calculating a bell curve */
-       /*      based on the standard deviation (or radius) */
-       /*      This code is based on an example */
-       /*      posted to comp.graphics.algorithms by */
-       /*      Blancmange (bmange@airdmhor.gen.nz) */
-
-       k = -1.0/(2.0*3.14159*blur*blur);
-       fval=0;
-       for (ix = 0;ix< halfWidth;ix++){
-               weight = (float)exp(k*(ix*ix));
-               filter[halfWidth - ix] = weight;
-               filter[halfWidth + ix] = weight;
-       }
-       filter[0] = weight;
-
-       /*      Normalize the array */
-       fval=0;
-       for (ix = 0;ix< halfWidth*2;ix++)
-               fval+=filter[ix];
-
-       for (ix = 0;ix< halfWidth*2;ix++)
-               filter[ix]/=fval;
-
-       /*      Blur the rows */
-       for (y=0;y<height;y++){
-               /*      Do the left & right strips */
-               for (x=0;x<halfWidth;x++){
-                       index=(x+y*width)*4;
-                       fx=0;
-                       curColor[0]=curColor[1]=curColor[2]=0;
-                       curColor2[0]=curColor2[1]=curColor2[2]=0;
-
-                       for (i=x-halfWidth;i<x+halfWidth;i++){
-                          if ((i>=0)&&(i<width)){
-                               curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
-                               curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
-                               curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
-
-                               curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
-                                   filter[fx];
-                               curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
-                                   filter[fx];
-                               curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
-                                   filter[fx];
-                               }
-                               fx++;
-                       }
-                       temp[index+GlowR]=curColor[0];
-                       temp[index+GlowG]=curColor[1];
-                       temp[index+GlowB]=curColor[2];
-
-                       temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
-                       temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
-                       temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
-
-               }
-               /*      Do the main body */
-               for (x=halfWidth;x<width-halfWidth;x++){
-                       index=(x+y*width)*4;
-                       fx=0;
-                       curColor[0]=curColor[1]=curColor[2]=0;
-                       for (i=x-halfWidth;i<x+halfWidth;i++){
-                               curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
-                               curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
-                               curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
-                               fx++;
-                       }
-                       temp[index+GlowR]=curColor[0];
-                       temp[index+GlowG]=curColor[1];
-                       temp[index+GlowB]=curColor[2];
-               }
-       }
-
-       /*      Swap buffers */
-       swap=temp;temp=map;map=swap;
-
-
-       /*      Blur the columns */
-       for (x=0;x<width;x++){
-               /*      Do the top & bottom strips */
-               for (y=0;y<halfWidth;y++){
-                       index=(x+y*width)*4;
-                       fy=0;
-                       curColor[0]=curColor[1]=curColor[2]=0;
-                       curColor2[0]=curColor2[1]=curColor2[2]=0;
-                       for (i=y-halfWidth;i<y+halfWidth;i++){
-                               if ((i>=0)&&(i<height)){
-                                  /*   Bottom */
-                                  curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
-                                  curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
-                                  curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
-
-                                  /*   Top */
-                                  curColor2[0]+=map[(x+(height-1-i)*width) *
-                                      4+GlowR]*filter[fy];
-                                  curColor2[1]+=map[(x+(height-1-i)*width) *
-                                      4+GlowG]*filter[fy];
-                                  curColor2[2]+=map[(x+(height-1-i)*width) *
-                                      4+GlowB]*filter[fy];
-                               }
-                               fy++;
-                       }
-                       temp[index+GlowR]=curColor[0];
-                       temp[index+GlowG]=curColor[1];
-                       temp[index+GlowB]=curColor[2];
-                       temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
-                       temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
-                       temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
+       if(seq->flag & SEQ_MAKE_FLOAT) {
+               if (!se->ibuf->rect_float) {
+                       IMB_float_from_rect(se->ibuf);
                }
-               /*      Do the main body */
-               for (y=halfWidth;y<height-halfWidth;y++){
-                       index=(x+y*width)*4;
-                       fy=0;
-                       curColor[0]=curColor[1]=curColor[2]=0;
-                       for (i=y-halfWidth;i<y+halfWidth;i++){
-                               curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
-                               curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
-                               curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
-                               fy++;
-                       }
-                       temp[index+GlowR]=curColor[0];
-                       temp[index+GlowG]=curColor[1];
-                       temp[index+GlowB]=curColor[2];
+               if (se->ibuf->rect) {
+                       imb_freerectImBuf(se->ibuf);
                }
        }
 
+       if(mul != 1.0) {
+               multibuf(se->ibuf, mul);
+       }
+
+       if(seq->flag & SEQ_MAKE_PREMUL) {
+               if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
+                       converttopremul(se->ibuf);
+               }
+       }
 
-       /*      Swap buffers */
-       swap=temp;temp=map;map=swap;
 
-       /*      Tidy up  */
-       MEM_freeN (filter);
-       MEM_freeN (temp);
+       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+               if(G.scene->r.mode & R_OSA) {
+                       IMB_scaleImBuf(se->ibuf, 
+                                      (short)seqrectx, (short)seqrecty);
+               } else {
+                       IMB_scalefastImBuf(se->ibuf, 
+                                          (short)seqrectx, (short)seqrecty);
+               }
+       }
 }
 
+/* test if image too small or discarded from cache: reload */
 
-/*     Adds two bitmaps and puts the results into a third map. */
-/*     C must have been previously allocated but it may be A or B. */
-/*     We clamp values to 255 to prevent weirdness */
-/*=============================== */
-void RVAddBitmaps (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
+static void test_and_auto_discard_ibuf(TStripElem * se)
 {
-       int     x,y,index;
+       if (se->ibuf) {
+               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
+                  || !(se->ibuf->rect || se->ibuf->rect_float)) {
+                       IMB_freeImBuf(se->ibuf);
 
-       for (y=0;y<height;y++){
-               for (x=0;x<width;x++){
-                       index=(x+y*width)*4;
-                       c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
-                       c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
-                       c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
-                       c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
+                       se->ibuf= 0;
+                       se->ok= STRIPELEM_OK;
+               }
+       }
+       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;
                }
        }
 }
 
-/*     For each pixel whose total luminance exceeds the threshold, */
-/*     Multiply it's value by BOOST and add it to the output map */
-void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp)
+static void test_and_auto_discard_ibuf_stills(Strip * strip)
 {
-       int x,y,index;
-       int     intensity;
+       if (strip->ibuf_startstill) {
+               if (!strip->ibuf_startstill->rect &&
+                   !strip->ibuf_startstill->rect_float) {
+                       IMB_freeImBuf(strip->ibuf_startstill);
+                       strip->ibuf_startstill = 0;
+               }
+       }
+       if (strip->ibuf_endstill) {
+               if (!strip->ibuf_endstill->rect &&
+                   !strip->ibuf_endstill->rect_float) {
+                       IMB_freeImBuf(strip->ibuf_endstill);
+                       strip->ibuf_endstill = 0;
+               }
+       }
+}
 
+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);
 
-       for(y=0;y< height;y++) {
-               for (x=0;x< width;x++) {
-                  index= (x+y*width)*4;
+                       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);
 
-                  /*   Isolate the intensity */
-                  intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
-                  if (intensity>0){
-                       out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
-                       out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
-                       out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
-                       }
-                       else{
-                               out[index+GlowR]=0;
-                               out[index+GlowG]=0;
-                               out[index+GlowB]=0;
-                       }
+                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
                }
        }
 }
 
-void init_glow_effect(Sequence *seq)
+static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
 {
-       GlowVars *glow;
+       if (se->ibuf) {
+               if (se->nr == 0) {
+                       seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
 
-       if(seq->effectdata)MEM_freeN(seq->effectdata);
-       seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
+                       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);
 
-       glow = (GlowVars *)seq->effectdata;
-       glow->fMini = 0.25;
-       glow->fClamp = 1.0;
-       glow->fBoost = 0.5;
-       glow->dDist = 3.0;
-       glow->dQuality = 3;
-       glow->bNoComp = 0;
+                       IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
+                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
+               }
+       }
 }
 
 
-//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
-void do_glow_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
+static TStripElem* do_build_seq_array_recursively(
+       ListBase *seqbasep, int cfra, int chanshown);
+
+static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
+                             int build_proxy_run)
 {
-       unsigned char *outbuf=(unsigned char *)out;
-       unsigned char *inbuf=(unsigned char *)rect1;
-       GlowVars *glow = (GlowVars *)seq->effectdata;
+       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;
+               use_limiter = FALSE;
+
+               if (!build_proxy_run && se->ibuf == 0) {
+                       se->ibuf = seq_proxy_fetch(seq, cfra);
+                       if (se->ibuf) {
+                               use_limiter = TRUE;
+                       }
+               }
+
+               if(!se->ibuf && seq->seqbase.first) {
+                       meta_se = do_build_seq_array_recursively(
+                               &seq->seqbase, seq->start + se->nr, 0);
+               }
+
+               se->ok = STRIPELEM_OK;
+
+               if(!se->ibuf && meta_se) {
+                       se->ibuf = meta_se->ibuf_comp;
+                       if(se->ibuf &&
+                          (!input_have_to_preprocess(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);
+
+                               se->ibuf = i;
+
+                               use_limiter = TRUE;
+                       }
+               }
+
+               if (use_limiter) {
+                       input_preprocess(seq, se, cfra);
+               }
+       } else if(seq->type & SEQ_EFFECT) {
+               /* should the effect be recalculated? */
+               
+               if (!build_proxy_run && se->ibuf == 0) {
+                       se->ibuf = seq_proxy_fetch(seq, cfra);
+               }
+
+               if(se->ibuf == 0) {
+                       /* if one of two first inputs are rectfloat, output is float too */
+                       if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
+                          (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       
+                       do_effect(cfra, seq, se);
+               }
+       } else if(seq->type == SEQ_IMAGE) {
+               if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
+                       StripElem * s_elem = give_stripelem(seq, cfra);
+                       
+                       strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
+                       strncat(name, s_elem->name, FILE_MAXFILE);
+                       BLI_convertstringcode(name, G.sce);
+                       BLI_convertstringframe(name, G.scene->r.cfra);
+                       if (!build_proxy_run) {
+                               se->ibuf = seq_proxy_fetch(seq, cfra);
+                       }
+                       copy_from_ibuf_still(seq, se);
+
+                       if (!se->ibuf) {
+                               se->ibuf= IMB_loadiffname(
+                                       name, IB_rect);
+                               copy_to_ibuf_still(seq, se);
+                       }
+                       
+                       if(se->ibuf == 0) {
+                               se->ok = STRIPELEM_FAILED;
+                       } else if (!build_proxy_run) {
+                               input_preprocess(seq, se, cfra);
+                       }
+               }
+       } else if(seq->type == SEQ_MOVIE) {
+               if(se->ok == STRIPELEM_OK && se->ibuf==0) {
+                       if(!build_proxy_run) {
+                               se->ibuf = seq_proxy_fetch(seq, cfra);
+                       }
+                       copy_from_ibuf_still(seq, se);
+
+                       if (se->ibuf == 0) {
+                               if(seq->anim==0) {
+                                       strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
+                                       strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1);
+                                       BLI_convertstringcode(name, G.sce);
+                                       BLI_convertstringframe(name, G.scene->r.cfra);
+                               
+                                       seq->anim = openanim(name, IB_rect);
+                               }
+                               if(seq->anim) {
+                                       IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
+                                       se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
+                               }
+                               copy_to_ibuf_still(seq, se);
+                       }
+                       
+                       if(se->ibuf == 0) {
+                               se->ok = STRIPELEM_FAILED;
+                       } else if (!build_proxy_run) {
+                               input_preprocess(seq, se, cfra);
+                       }
+               }
+       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
+               int oldcfra = CFRA;
+               Scene *sce= seq->scene, *oldsce= G.scene;
+               Render *re;
+               RenderResult rres;
+               int doseq, rendering= G.rendering;
+               char scenename[64];
+               int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ);
+                       
+               if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
+                       se->ibuf = seq_proxy_fetch(seq, cfra);
+                       if (se->ibuf) {
+                               input_preprocess(seq, se, cfra);
+                       }
+               }
+
+               if (se->ibuf == NULL && sce_valid) {
+                       copy_from_ibuf_still(seq, se);
+                       if (se->ibuf) {
+                               input_preprocess(seq, se, cfra);
+                       }
+               }
+               
+               if (!sce_valid) {
+                       se->ok = STRIPELEM_FAILED;
+               } else if (se->ibuf==NULL && sce_valid) {
+                       waitcursor(1);
+                       
+                       /* Hack! This function can be called from do_render_seq(), in that case
+                          the seq->scene can already have a Render initialized with same name, 
+                          so we have to use a default name. (compositor uses G.scene name to
+                          find render).
+                          However, when called from within the UI (image preview in sequencer)
+                          we do want to use scene Render, that way the render result is defined
+                          for display in render/imagewindow */
+                       if(rendering) {
+                               BLI_strncpy(scenename, sce->id.name+2, 64);
+                               strcpy(sce->id.name+2, " do_build_seq_ibuf");
+                       }
+                       re= RE_NewRender(sce->id.name);
+                       
+                       /* prevent eternal loop */
+                       doseq= G.scene->r.scemode & R_DOSEQ;
+                       G.scene->r.scemode &= ~R_DOSEQ;
+                       
+                       BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
+                       
+                       /* hrms, set_scene still needed? work on that... */
+                       if(sce!=oldsce) set_scene_bg(sce);
+                       RE_BlenderFrame(re, sce,
+                                       seq->sfra+se->nr+seq->anim_startofs);
+                       if(sce!=oldsce) set_scene_bg(oldsce);
+                       
+                       /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
+                       G.rendering= rendering;
+                       if(rendering)
+                               BLI_strncpy(sce->id.name+2, scenename, 64);
+                       
+                       RE_GetResultImage(re, &rres);
+                       
+                       if(rres.rectf) {
+                               se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                               memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
+                               if(rres.rectz) {
+                                       addzbuffloatImBuf(se->ibuf);
+                                       memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
+                               }
+                       } 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);
+                       }
+                       
+                       BIF_end_render_callbacks();
+                       
+                       /* restore */
+                       G.scene->r.scemode |= doseq;
+                       
+                       if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */
+                               waitcursor(0);
+                       CFRA = oldcfra;
+
+                       copy_to_ibuf_still(seq, se);
+
+                       if (!build_proxy_run) {
+                               if(se->ibuf == NULL) {
+                                       se->ok = STRIPELEM_FAILED;
+                               } else {
+                                       input_preprocess(seq, se, cfra);
+                               }
+                       }
 
-       RVIsolateHighlights     (inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp);
-       RVBlurBitmap2 (outbuf, x, y, glow->dDist,glow->dQuality);
-       if (!glow->bNoComp)
-               RVAddBitmaps (inbuf , outbuf, outbuf, x, y);
+               }       
+       }
+       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);
+               }
+       }
 }
 
-void make_black_ibuf(ImBuf *ibuf)
+static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra);
+
+static void do_effect_seq_recursively(Sequence * seq, TStripElem *se, int cfra)
 {
-       unsigned int *rect;
-       int tot;
+       float fac, facf;
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
+       int early_out;
 
-       if(ibuf==0 || ibuf->rect==0) return;
+       se->se1 = 0;
+       se->se2 = 0;
+       se->se3 = 0;
 
-       tot= ibuf->x*ibuf->y;
-       rect= ibuf->rect;
-       while(tot--) *(rect++)= 0;
+       if(seq->ipo && seq->ipo->curve.first) {
+               do_seq_ipo(seq, cfra);
+               fac= seq->facf0;
+               facf= seq->facf1;
+       } else {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+       } 
+
+       if( G.scene->r.mode & R_FIELDS ); else facf= fac;
+       
+       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(seq->seq1, cfra);
+               se->se2 = do_build_seq_recursively(seq->seq2, cfra);
+               if (seq->seq3) {
+                       se->se3 = do_build_seq_recursively(seq->seq3, cfra);
+               }
+               break;
+       case 1:
+               se->se1 = do_build_seq_recursively(seq->seq1, cfra);
+               break;
+       case 2:
+               se->se2 = do_build_seq_recursively(seq->seq2, cfra);
+               break;
+       }
+
+
+       do_build_seq_ibuf(seq, se, cfra, FALSE);
 
+       /* children are not needed anymore ... */
+
+       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);
+       }
 }
 
-void multibuf(ImBuf *ibuf, float fmul)
+static TStripElem* do_build_seq_recursively_impl(Sequence * seq, int cfra)
 {
-       char *rt;
-       int a, mul, icol;
+       TStripElem *se;
 
-       mul= (int)(256.0*fmul);
+       se = give_tstripelem(seq, cfra);
 
-       a= ibuf->x*ibuf->y;
-       rt= (char *)ibuf->rect;
-       while(a--) {
+       if(se) {
+               if (seq->type & SEQ_EFFECT) {
+                       do_effect_seq_recursively(seq, se, cfra);
+               } else {
+                       do_build_seq_ibuf(seq, se, cfra, FALSE);
+               }
+       }
+       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...
+
+*/
+
+static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra)
+{
+       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
+       int nr = cfra - seq->start;
+       float f_cfra;
+       int cfra_left;
+       int cfra_right;
+       TStripElem * se = 0;
+       TStripElem * se1 = 0;
+       TStripElem * se2 = 0;
+       
+       sequence_effect_speed_rebuild_map(seq, 0);
+       
+       f_cfra = seq->start + s->frameMap[nr];
+       
+       cfra_left = (int) floor(f_cfra);
+       cfra_right = (int) ceil(f_cfra);
+
+       se = give_tstripelem(seq, cfra);
+
+       if (cfra_left == cfra_right || 
+           (s->flags & SEQ_SPEED_BLEND) == 0) {
+               test_and_auto_discard_ibuf(se);
+
+               if (se->ibuf == NULL) {
+                       se1 = do_build_seq_recursively_impl(
+                               seq->seq1, cfra_left);
+
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+
+                       if (se1 == 0 || se1->ibuf == 0) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               if (se->ibuf != se1->ibuf) {
+                                       if (se->ibuf) {
+                                               IMB_freeImBuf(se->ibuf);
+                                       }
+
+                                       se->ibuf = se1->ibuf;
+                                       IMB_refImBuf(se->ibuf);
+                               }
+                       }
+               }
+       } 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;
+                       }
+               }
+
+               if (se->ibuf == NULL) {
+                       se1 = do_build_seq_recursively_impl(
+                               seq->seq1, cfra_left);
+                       se2 = do_build_seq_recursively_impl(
+                               seq->seq1, cfra_right);
+
+                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+                       else
+                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       
+                       if (!se1 || !se2) {
+                               make_black_ibuf(se->ibuf);
+                       } else {
+                               sh = get_sequence_effect(seq);
+
+                               sh.execute(seq, cfra, 
+                                          f_cfra - (float) cfra_left, 
+                                          f_cfra - (float) cfra_left, 
+                                          se->ibuf->x, se->ibuf->y, 
+                                          se1->ibuf, se2->ibuf, 0, se->ibuf);
+                       }
+               }
+
+       }
+
+       /* 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);
+       }
+
+       /* 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);
+
+       return se;
+}
 
-               icol= (mul*rt[0])>>8;
-               if(icol>254) rt[0]= 255; else rt[0]= icol;
-               icol= (mul*rt[1])>>8;
-               if(icol>254) rt[1]= 255; else rt[1]= icol;
-               icol= (mul*rt[2])>>8;
-               if(icol>254) rt[2]= 255; else rt[2]= icol;
-               icol= (mul*rt[3])>>8;
-               if(icol>254) rt[3]= 255; else rt[3]= icol;
+/* 
+ * 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
+ * 
+ */
 
-               rt+= 4;
+static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra)
+{
+       if (seq->type == SEQ_SPEED) {
+               return do_handle_speed_effect(seq, cfra);
+       } else {
+               return do_build_seq_recursively_impl(seq, cfra);
        }
 }
 
-void do_effect(int cfra, Sequence *seq, StripElem *se)
+static TStripElem* do_build_seq_array_recursively(
+       ListBase *seqbasep, int cfra, int chanshown)
 {
-       StripElem *se1, *se2, *se3;
-       float fac, facf;
-       int x, y;
-       char *cp;
+       Sequence* seq_arr[MAXSEQ+1];
+       int count;
+       int i;
+       TStripElem* se = 0;
 
-       if(se->se1==0 || se->se2==0 || se->se3==0) {
-               make_black_ibuf(se->ibuf);
-               return;
+       count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
+
+       if (!count) {
+               return 0;
        }
 
-       /* if metastrip: other se's */
-       if(se->se1->ok==2) se1= se->se1->se1;
-       else se1= se->se1;
+       se = give_tstripelem(seq_arr[count - 1], cfra);
 
-       if(se->se2->ok==2) se2= se->se2->se1;
-       else se2= se->se2;
+       if (!se) {
+               return 0;
+       }
 
-       if(se->se3->ok==2) se3= se->se3->se1;
-       else se3= se->se3;
+       test_and_auto_discard_ibuf(se);
 
-       if(se1==0 || se2==0 || se3==0 || se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) {
-               make_black_ibuf(se->ibuf);
-               return;
+       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(count == 1) {
+               se = do_build_seq_recursively(seq_arr[0], cfra);
+               if (se->ibuf) {
+                       se->ibuf_comp = se->ibuf;
+                       IMB_refImBuf(se->ibuf_comp);
+               }
+               return se;
+       }
+
+
+       for (i = count - 1; i >= 0; i--) {
+               int early_out;
+               Sequence * seq = seq_arr[i];
+               struct SeqEffectHandle sh;
+
+               se = give_tstripelem(seq, cfra);
+
+               test_and_auto_discard_ibuf(se);
+
+               if (se->ibuf_comp != 0) {
+                       break;
+               }
+               if (seq->blend_mode == SEQ_BLEND_REPLACE) {
+                       do_build_seq_recursively(seq, cfra);
+                       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);
+                       }
+                       break;
+               }
+
+               sh = get_sequence_blend(seq);
+
+               seq->facf0 = seq->facf1 = 1.0;
+
+               if(seq->ipo && seq->ipo->curve.first) {
+                       do_seq_ipo(seq, cfra);
+               } 
+
+               if( G.scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1;
+
+               seq->facf0 *= seq->blend_opacity / 100.0;
+               seq->facf1 *= seq->blend_opacity / 100.0;
+
+               early_out = sh.early_out(seq, seq->facf0, seq->facf1);
+
+               switch (early_out) {
+               case -1:
+               case 2:
+                       do_build_seq_recursively(seq, cfra);
+                       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);
+                       }
+                       break;
+               case 1:
+                       if (i == 0) {
+                               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);
+                       }
+                       break;
+               case 0:
+                       do_build_seq_recursively(seq, cfra);
+                       if (!se->ibuf) {
+                               se->ibuf = IMB_allocImBuf(
+                                       (short)seqrectx, (short)seqrecty, 
+                                       32, IB_rect, 0);
+                       }
+                       if (i == 0) {
+                               se->ibuf_comp = se->ibuf;
+                               IMB_refImBuf(se->ibuf_comp);
+                       }
+                       break;
+               }
+       
+               if (se->ibuf_comp) {
+                       break;
+               }
        }
 
-       x= se2->ibuf->x;
-       y= se2->ibuf->y;
+       i++;
 
-       if(seq->ipo && seq->ipo->curve.first) {
-               do_seq_ipo(seq);
-               fac= seq->facf0;
-               facf= seq->facf1;
-       }
-       else if ( seq->type==SEQ_CROSS || seq->type==SEQ_GAMCROSS || seq->type==SEQ_PLUGIN || seq->type==SEQ_WIPE) {
-               fac= (float)(cfra - seq->startdisp);
-               facf= (float)(fac+0.5);
-               fac /= seq->len;
-               facf /= seq->len;
-       }
-       else {
-               fac= facf= 1.0;
-       }
+       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);
+       
+               int early_out = sh.early_out(seq, seq->facf0, seq->facf1);
+               switch (early_out) {
+               case 0: {
+                       int x= se2->ibuf->x;
+                       int y= se2->ibuf->y;
+                       int swap_input = FALSE;
+
+                       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( G.scene->r.mode & R_FIELDS ); else facf= fac;
 
-       switch(seq->type) {
-       case SEQ_CROSS:
-               do_cross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_GAMCROSS:
-               do_gammacross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_ADD:
-               do_add_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_SUB:
-               do_sub_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_MUL:
-               do_mul_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_ALPHAOVER:
-               do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_OVERDROP:
-               do_drop_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_ALPHAUNDER:
-               do_alphaunder_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_WIPE:
-               do_wipe_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_GLOW:
-               do_glow_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
-               break;
-       case SEQ_PLUGIN:
-               if(seq->plugin && seq->plugin->doit) {
+                       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((G.f & G_PLAYANIM)==0) waitcursor(1);
+                       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);
+                       }
 
-                       if(seq->plugin->cfra) *(seq->plugin->cfra)= frame_to_float(CFRA);
+                       /* bad hack, to fix crazy input ordering of 
+                          those two effects */
 
-                       cp= PIL_dynlib_find_symbol(seq->plugin->handle, "seqname");
-                       if(cp) strcpy(cp, seq->name+2);
+                       if (seq->blend_mode == SEQ_ALPHAOVER ||
+                           seq->blend_mode == SEQ_ALPHAUNDER ||
+                           seq->blend_mode == SEQ_OVERDROP) {
+                               swap_input = TRUE;
+                       }
 
-                       if (seq->plugin->version<=2) {
-                               if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf->x*se1->ibuf->y, se1->ibuf->rect);
-                               if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf->x*se2->ibuf->y, se2->ibuf->rect);
-                               if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf->x*se3->ibuf->y, se3->ibuf->rect);
+                       if (swap_input) {
+                               sh.execute(seq, cfra, 
+                                          seq->facf0, seq->facf1, x, y, 
+                                          se2->ibuf, se1->ibuf_comp, 0,
+                                          se2->ibuf_comp);
+                       } else {
+                               sh.execute(seq, cfra, 
+                                          seq->facf0, seq->facf1, x, y, 
+                                          se1->ibuf_comp, se2->ibuf, 0,
+                                          se2->ibuf_comp);
                        }
+                       
+                       IMB_cache_limiter_insert(se2->ibuf_comp);
+                       IMB_cache_limiter_ref(se2->ibuf_comp);
+                       IMB_cache_limiter_touch(se2->ibuf_comp);
 
-                       ((SeqDoit)seq->plugin->doit)(seq->plugin->data, fac, facf, x, y,
-                                               se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf);
+                       IMB_cache_limiter_unref(se1->ibuf_comp);
+                       IMB_cache_limiter_unref(se2->ibuf);
 
-                       if (seq->plugin->version<=2) {
-                               if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf->x*se1->ibuf->y, se1->ibuf->rect);
-                               if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf->x*se2->ibuf->y, se2->ibuf->rect);
-                               if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf->x*se3->ibuf->y, se3->ibuf->rect);
-                               IMB_convert_rgba_to_abgr(se->ibuf->x*se->ibuf->y, se->ibuf->rect);
-                       }
+                       break;
+               }
+               case 1: {
+                       se2->ibuf_comp = se1->ibuf;
+                       IMB_refImBuf(se2->ibuf_comp);
 
-                       if((G.f & G_PLAYANIM)==0) waitcursor(0);
+                       break;
                }
-               break;
+               }
+               se = se2;
        }
 
+       return se;
 }
 
-int evaluate_seq_frame(int cfra)
+/*
+ * returned ImBuf is refed!
+ * you have to unref after usage!
+ */
+
+static ImBuf *give_ibuf_seq_impl(int rectx, int recty, int cfra, int chanshown)
 {
-       Sequence *seq;
        Editing *ed;
-       int totseq=0;
-
-       memset(seq_arr, 0, 4*MAXSEQ);
+       int count;
+       ListBase *seqbasep;
+       TStripElem *se;
 
        ed= G.scene->ed;
        if(ed==0) return 0;
 
-       seq= ed->seqbasep->first;
-       while(seq) {
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
-                       seq_arr[seq->machine]= seq;
-                       totseq++;
-               }
-               seq= seq->next;
+       count = BLI_countlist(&ed->metastack);
+       if((chanshown < 0) && (count > 0)) {
+               count = MAX2(count + chanshown, 0);
+               seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep;
+       } else {
+               seqbasep= ed->seqbasep;
        }
 
-       return totseq;
+       seqrectx= rectx;        /* bad bad global! */
+       seqrecty= recty;
+
+       se = do_build_seq_array_recursively(seqbasep, cfra, chanshown);
+
+       if(!se) { 
+               return 0;
+       }
+
+       return se->ibuf_comp;
 }
 
-StripElem *give_stripelem(Sequence *seq, int cfra)
+ImBuf *give_ibuf_seq_direct(int rectx, int recty, int cfra,
+                           Sequence * seq)
 {
-       Strip *strip;
-       StripElem *se;
-       int nr;
+       TStripElem* se;
 
-       strip= seq->strip;
-       se= strip->stripdata;
+       seqrectx= rectx;        /* bad bad global! */
+       seqrecty= recty;
 
-       if(se==0) return 0;
-       if(seq->startdisp >cfra || seq->enddisp <= cfra) return 0;
+       se = do_build_seq_recursively(seq, cfra);
 
-       if(cfra <= seq->start) nr= 0;
-       else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
-       else nr= cfra-seq->start;
+       if(!se) { 
+               return 0;
+       }
 
-       se+= nr;
-       se->nr= nr;
+       if (se->ibuf) {
+               IMB_cache_limiter_unref(se->ibuf);
+       }
 
-       return se;
+       return se->ibuf;
 }
 
-void set_meta_stripdata(Sequence *seqm)
+ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown)
 {
-       Sequence *seq, *seqim, *seqeff;
-       Editing *ed;
-       ListBase *tempbase;
-       StripElem *se;
-       int a, cfra, b;
+       ImBuf* i = give_ibuf_seq_impl(rectx, recty, cfra, chanshown);
 
-       /* sets all ->se1 pointers in stripdata, to read the ibuf from it */
+       if (i) {
+               IMB_cache_limiter_unref(i);
+       }
+       return i;
+}
 
-       ed= G.scene->ed;
-       if(ed==0) return;
+/* threading api */
 
-       tempbase= ed->seqbasep;
-       ed->seqbasep= &seqm->seqbase;
+static ListBase running_threads;
+static ListBase prefetch_wait;
+static ListBase prefetch_done;
 
-       se= seqm->strip->stripdata;
-       for(a=0; a<seqm->len; a++, se++) {
-               cfra= a+seqm->start;
-               if(evaluate_seq_frame(cfra)) {
+static pthread_mutex_t queue_lock          = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t wakeup_lock         = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  wakeup_cond         = PTHREAD_COND_INITIALIZER;
 
-                       /* we take the upper effect strip or the lowest imagestrip/metastrip */
-                       seqim= seqeff= 0;
+static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
 
-                       for(b=1; b<MAXSEQ; b++) {
-                               if(seq_arr[b]) {
-                                       seq= seq_arr[b];
-                                       if(seq->type & SEQ_EFFECT) {
-                                               if(seqeff==0) seqeff= seq;
-                                               else if(seqeff->machine < seq->machine) seqeff= seq;
-                                       }
-                                       else {
-                                               if(seqim==0) seqim= seq;
-                                               else if(seqim->machine > seq->machine) seqim= seq;
-                                       }
-                               }
-                       }
-                       if(seqeff) seq= seqeff;
-                       else if(seqim) seq= seqim;
-                       else seq= 0;
+static pthread_mutex_t frame_done_lock     = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  frame_done_cond     = PTHREAD_COND_INITIALIZER;
 
-                       if(seq) {
-                               se->se1= give_stripelem(seq, cfra);
-                       }
-                       else se->se1= 0;
-               }
-       }
+static volatile int seq_thread_shutdown = FALSE;
+static volatile int seq_last_given_monoton_cfra = 0;
+static int monoton_cfra = 0;
 
-       ed->seqbasep= tempbase;
-}
+typedef struct PrefetchThread {
+       struct PrefetchThread *next, *prev;
+       struct PrefetchQueueElem *current;
+       pthread_t pthread;
+       int running;
+} PrefetchThread;
 
+typedef struct PrefetchQueueElem {
+       struct PrefetchQueueElem *next, *prev;
+       
+       int rectx;
+       int recty;
+       int cfra;
+       int chanshown;
 
+       int monoton_cfra;
 
-/* HELP FUNCTIONS FOR GIVE_IBUF_SEQ */
+       struct ImBuf * ibuf;
+} PrefetchQueueElem;
 
-void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra)
+static void * seq_prefetch_thread(void * This_)
 {
-       Sequence *seq;
+       PrefetchThread * This = This_;
 
-       seq= seqbase->first;
-       while(seq) {
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+       while (!seq_thread_shutdown) {
+               PrefetchQueueElem * e;
+               int s_last;
+
+               pthread_mutex_lock(&queue_lock);
+               e = prefetch_wait.first;
+               if (e) {
+                       BLI_remlink(&prefetch_wait, e);
+               }
+               s_last = seq_last_given_monoton_cfra;
+
+               This->current = e;
 
-                       if(seq->seqbase.first) {
+               pthread_mutex_unlock(&queue_lock);
 
-                               if(cfra< seq->start) do_seq_count_cfra(&seq->seqbase, totseq, seq->start);
-                               else if(cfra> seq->start+seq->len-1) do_seq_count_cfra(&seq->seqbase, totseq, seq->start+seq->len-1);
-                               else do_seq_count_cfra(&seq->seqbase, totseq, cfra);
+               if (!e) {
+                       pthread_mutex_lock(&prefetch_ready_lock);
+
+                       This->running = FALSE;
+
+                       pthread_cond_signal(&prefetch_ready_cond);
+                       pthread_mutex_unlock(&prefetch_ready_lock);
+
+                       pthread_mutex_lock(&wakeup_lock);
+                       if (!seq_thread_shutdown) {
+                               pthread_cond_wait(&wakeup_cond, &wakeup_lock);
                        }
+                       pthread_mutex_unlock(&wakeup_lock);
+                       continue;
+               }
 
-                       (*totseq)++;
+               This->running = TRUE;
+               
+               if (e->cfra >= s_last) { 
+                       e->ibuf = give_ibuf_seq_impl(
+                               e->rectx, e->recty, e->cfra, e->chanshown);
                }
-               seq= seq->next;
+
+               pthread_mutex_lock(&queue_lock);
+
+               BLI_addtail(&prefetch_done, e);
+
+               for (e = prefetch_wait.first; e; e = e->next) {
+                       if (s_last > e->monoton_cfra) {
+                               BLI_remlink(&prefetch_wait, e);
+                               MEM_freeN(e);
+                       }
+               }
+
+               for (e = prefetch_done.first; e; e = e->next) {
+                       if (s_last > e->monoton_cfra) {
+                               if (e->ibuf) {
+                                       IMB_cache_limiter_unref(e->ibuf);
+                               }
+                               BLI_remlink(&prefetch_done, e);
+                               MEM_freeN(e);
+                       }
+               }
+
+               pthread_mutex_unlock(&queue_lock);
+
+               pthread_mutex_lock(&frame_done_lock);
+               pthread_cond_signal(&frame_done_cond);
+               pthread_mutex_unlock(&frame_done_lock);
        }
+       return 0;
 }
 
-void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra)
+void seq_start_threads()
 {
-       Sequence *seq;
-       StripElem *se;
-       Scene *oldsce;
-       unsigned int *rectot;
-       int oldx, oldy, oldcfra, doseq;
-       char name[FILE_MAXDIR];
+       int i;
 
-       if(seqar==NULL) return;
-       
-       seq= seqbase->first;
-       while(seq) {
+       running_threads.first = running_threads.last = NULL;
+       prefetch_wait.first = prefetch_wait.last = NULL;
+       prefetch_done.first = prefetch_done.last = NULL;
 
-               /* set at zero because free_imbuf_seq... */
-               seq->curelem= 0;
+       seq_thread_shutdown = FALSE;
+       seq_last_given_monoton_cfra = monoton_cfra = 0;
 
-               if ((seq->type == SEQ_SOUND) && (seq->ipo)
-                 &&(seq->startdisp<=cfra+2) && (seq->enddisp>cfra)) do_seq_ipo(seq);
+       /* since global structures are modified during the processing
+          of one frame, only one render thread is currently possible... 
 
-               if(seq->startdisp <=cfra && seq->enddisp > cfra) {
+          (but we code, in the hope, that we can remove this restriction
+          soon...)
+       */
 
-                       if(seq->seqbase.first) {
-                               if(cfra< seq->start) do_build_seqar_cfra(&seq->seqbase, seqar, seq->start);
-                               else if(cfra> seq->start+seq->len-1) do_build_seqar_cfra(&seq->seqbase, seqar, seq->start+seq->len-1);
-                               else do_build_seqar_cfra(&seq->seqbase, seqar, cfra);
-                       }
+       fprintf(stderr, "SEQ-THREAD: seq_start_threads\n");
 
-                       **seqar= seq;
-                       (*seqar)++;
+       for (i = 0; i < 1; i++) {
+               PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), 
+                                               "prefetch_thread");
+               t->running = TRUE;
+               BLI_addtail(&running_threads, t);
 
-                       se=seq->curelem= give_stripelem(seq, cfra);
+               pthread_create(&t->pthread, NULL, seq_prefetch_thread, t);
+       }
 
-                       if(se) {
-                               if(seq->type == SEQ_META) {
-                                       se->ok= 2;
-                                       if(se->se1==0) set_meta_stripdata(seq);
-                                       if(se->se1) {
-                                               se->ibuf= se->se1->ibuf;
-                                       }
-                               }
-                               else if(seq->type == SEQ_SOUND) {
-                                       se->ok= 2;
-                               }
-                               else if(seq->type & SEQ_EFFECT) {
-
-                                       /* test if image is too small: reload */
-                                       if(se->ibuf) {
-                                               if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty) {
-                                                       IMB_freeImBuf(se->ibuf);
-                                                       se->ibuf= 0;
-                                               }
-                                       }
+       /* init malloc mutex */
+       BLI_init_threads(0, 0, 0);
+}
 
-                                       /* does the effect should be recalculated? */
+void seq_stop_threads()
+{
+       PrefetchThread *tslot;
+       PrefetchQueueElem * e;
 
-                                       if(se->ibuf==0 || (se->se1 != seq->seq1->curelem) || (se->se2 != seq->seq2->curelem) || (se->se3 != seq->seq3->curelem)) {
-                                               se->se1= seq->seq1->curelem;
-                                               se->se2= seq->seq2->curelem;
-                                               se->se3= seq->seq3->curelem;
+       fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n");
 
-                                               if(se->ibuf==0) se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+       if (seq_thread_shutdown) {
+               fprintf(stderr, "SEQ-THREAD: ... already stopped\n");
+               return;
+       }
+       
+       pthread_mutex_lock(&wakeup_lock);
 
-                                               do_effect(cfra, seq, se);
-                                       }
+       seq_thread_shutdown = TRUE;
 
-                                       /* test size */
-                                       if(se->ibuf) {
-                                               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
-                                                       if(G.scene->r.mode & R_OSA)
-                                                               IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                       else
-                                                               IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                               }
-                                       }
-                               }
-                               else if(seq->type < SEQ_EFFECT) {
-
-                                       if(se->ibuf) {
-                                               /* test if image too small: reload */
-                                               if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty) {
-                                                       IMB_freeImBuf(se->ibuf);
-                                                       se->ibuf= 0;
-                                                       se->ok= 1;
-                                               }
-                                       }
+        pthread_cond_broadcast(&wakeup_cond);
+        pthread_mutex_unlock(&wakeup_lock);
 
-                                       if(seq->type==SEQ_IMAGE) {
-                                               if(se->ok && se->ibuf==0) {
-
-                                                       /* if playanim or render: no waitcursor */
-                                                       if((G.f & G_PLAYANIM)==0) waitcursor(1);
-
-                                                       strcpy(name, seq->strip->dir);
-                                                       strcat(name, se->name);
-                                                       BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
-                                                       se->ibuf= IMB_loadiffname(name, IB_rect);
-
-                                                       if((G.f & G_PLAYANIM)==0) waitcursor(0);
-
-                                                       if(se->ibuf==0) se->ok= 0;
-                                                       else {
-                                                               if(seq->flag & SEQ_MAKE_PREMUL) {
-                                                                       if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf);
-                                                               }
-                                                               seq->strip->orx= se->ibuf->x;
-                                                               seq->strip->ory= se->ibuf->y;
-                                                               if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
-                                                               if(seq->mul==0.0) seq->mul= 1.0;
-                                                               if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
-                                                       }
-                                               }
-                                       }
-                                       else if(seq->type==SEQ_MOVIE) {
-                                               if(se->ok && se->ibuf==0) {
-
-                                                       /* if playanim r render: no waitcursor */
-                                                       if((G.f & G_PLAYANIM)==0) waitcursor(1);
-
-                                                       if(seq->anim==0) {
-                                                               strcpy(name, seq->strip->dir);
-                                                               strcat(name, seq->strip->stripdata->name);
-                                                               BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
-
-                                                               seq->anim = openanim(name, IB_rect);
-                                                       }
-                                                       if(seq->anim) {
-                                                               se->ibuf = IMB_anim_absolute(seq->anim, se->nr);
-                                                       }
-
-                                                       if(se->ibuf==0) se->ok= 0;
-                                                       else {
-                                                               if(seq->flag & SEQ_MAKE_PREMUL) {
-                                                                       if(se->ibuf->depth==32) converttopremul(se->ibuf);
-                                                               }
-                                                               seq->strip->orx= se->ibuf->x;
-                                                               seq->strip->ory= se->ibuf->y;
-                                                               if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf);
-                                                               if(seq->mul==0.0) seq->mul= 1.0;
-                                                               if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
-                                                       }
-                                                       if((G.f & G_PLAYANIM)==0) waitcursor(0);
-                                               }
-                                       }
-                                       else if(seq->type==SEQ_SCENE && se->ibuf==0 && seq->scene) {    // scene can be NULL after deletions
-                                               View3D *vd;
-                                               
-                                               oldsce= G.scene;
-                                               set_scene_bg(seq->scene);
-
-                                               /* prevent eternal loop */
-                                               doseq= G.scene->r.scemode & R_DOSEQ;
-                                               G.scene->r.scemode &= ~R_DOSEQ;
-
-                                               /* store stuffies */
-                                               oldcfra= CFRA; CFRA= seq->sfra + se->nr;
-                                               waitcursor(1);
-
-                                               rectot= R.rectot; R.rectot= NULL;
-                                               oldx= R.rectx; oldy= R.recty;
-                                               /* needed because current 3D window cannot define the layers, like in a background render */
-                                               vd= G.vd;
-                                               G.vd= NULL;
-
-                                               RE_initrender(NULL);
-                                               if (!G.background) {
-                                                       mainwindow_make_active();
-                                                       if(R.r.mode & R_FIELDS) update_for_newframe_muted();
-                                                       R.flag= 0;
-
-                                                       free_filesel_spec(G.scene->r.pic);
-                                               }
-
-                                               se->ibuf= IMB_allocImBuf(R.rectx, R.recty, 32, IB_rect, 0);
-                                               if(R.rectot) memcpy(se->ibuf->rect, R.rectot, 4*R.rectx*R.recty);
-                                               if(R.rectz) {
-                                                       se->ibuf->zbuf= (int *)R.rectz;
-                                                       /* make sure ibuf frees it */
-                                                       se->ibuf->mall |= IB_zbuf;
-                                                       R.rectz= NULL;
-                                               }
-
-                                               /* and restore */
-                                               G.vd= vd;
-
-                                               if((G.f & G_PLAYANIM)==0) waitcursor(0);
-                                               CFRA= oldcfra;
-                                               if(R.rectot) MEM_freeN(R.rectot);
-                                               R.rectot= rectot;
-                                               R.rectx=oldx; R.recty=oldy;
-                                               G.scene->r.scemode |= doseq;
-                                               set_scene_bg(oldsce);
-
-                                               /* restore!! */
-                                               R.rectx= seqrectx;
-                                               R.recty= seqrecty;
-
-                                               /* added because this flag is checked for
-                                                * movie writing when rendering an anim.
-                                                * very convoluted. fix. -zr
-                                                */
-                                               R.r.imtype= G.scene->r.imtype;
-                                       }
+       for(tslot = running_threads.first; tslot; tslot= tslot->next) {
+               pthread_join(tslot->pthread, NULL);
+       }
 
-                                       /* size test */
-                                       if(se->ibuf) {
-                                               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
-
-                                                       if (G.scene->r.mode & R_FIELDS) {
-
-                                                               if (seqrecty > 288) IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                               else {
-                                                                       IMB_de_interlace(se->ibuf);
-
-                                                                       if(G.scene->r.mode & R_OSA)
-                                                                               IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                                       else
-                                                                               IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                               }
-                                                       }
-                                                       else {
-                                                               if(G.scene->r.mode & R_OSA)
-                                                                       IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty);
-                                                               else
-                                                                       IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
 
-               seq= seq->next;
+       for (e = prefetch_wait.first; e; e = e->next) {
+               BLI_remlink(&prefetch_wait, e);
+               MEM_freeN(e);
+       }
+
+       for (e = prefetch_done.first; e; e = e->next) {
+               if (e->ibuf) {
+                       IMB_cache_limiter_unref(e->ibuf);
+               }
+               BLI_remlink(&prefetch_done, e);
+               MEM_freeN(e);
        }
+
+       BLI_freelistN(&running_threads);
+
+       /* deinit malloc mutex */
+       BLI_end_threads(0);
 }
 
-ImBuf *give_ibuf_seq(int cfra)
+void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown)
 {
-       Sequence **tseqar, **seqar;
-       Sequence *seq, *seqfirst=0;/*  , *effirst=0; */
-       Editing *ed;
-       StripElem *se;
-       int seqnr, totseq;
+       PrefetchQueueElem * e;
+       if (seq_thread_shutdown) {
+               return;
+       }
 
-       /* we make recursively a 'stack' of sequences, these are
-        * sorted nicely as well.
-        * this method has been developed especially for stills before or after metas
-        */
+       e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
+       e->rectx = rectx;
+       e->recty = recty;
+       e->cfra = cfra;
+       e->chanshown = chanshown;
+       e->monoton_cfra = monoton_cfra++;
 
-       totseq= 0;
-       ed= G.scene->ed;
-       if(ed==0) return 0;
-       do_seq_count_cfra(ed->seqbasep, &totseq, cfra);
+       pthread_mutex_lock(&queue_lock);
+       BLI_addtail(&prefetch_wait, e);
+       pthread_mutex_unlock(&queue_lock);
+       
+       pthread_mutex_lock(&wakeup_lock);
+       pthread_cond_signal(&wakeup_cond);
+       pthread_mutex_unlock(&wakeup_lock);
+}
+
+void seq_wait_for_prefetch_ready()
+{
+       PrefetchThread *tslot;
 
-       if(totseq==0) return 0;
+       if (seq_thread_shutdown) {
+               return;
+       }
 
-       seqrectx= (G.scene->r.size*G.scene->r.xsch)/100;
-       if(G.scene->r.mode & R_PANORAMA) seqrectx*= G.scene->r.xparts;
-       seqrecty= (G.scene->r.size*G.scene->r.ysch)/100;
+       fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n");
 
+       pthread_mutex_lock(&prefetch_ready_lock);
 
-       /* tseqar is neede because in do_build_... the pointer changes */
-       seqar= tseqar= MEM_callocN(sizeof(void *)*totseq, "seqar");
+       for(;;) {
+               for(tslot = running_threads.first; tslot; tslot= tslot->next) {
+                       if (tslot->running) {
+                               break;
+                       }
+               }
+               if (!tslot) {
+                       break;
+               }
+               pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock);
+       }
 
-       /* this call loads and makes the ibufs */
-       do_build_seqar_cfra(ed->seqbasep, &seqar, cfra);
-       seqar= tseqar;
+       pthread_mutex_unlock(&prefetch_ready_lock);
 
-       for(seqnr=0; seqnr<totseq; seqnr++) {
-               seq= seqar[seqnr];
+       fprintf(stderr, "SEQ-THREAD: prefetch done\n");
+}
 
-               se= seq->curelem;
-               if((seq->type != SEQ_SOUND) && (se)) {
-                       if(seq->type==SEQ_META) {
+ImBuf * give_ibuf_seq_threaded(int rectx, int recty, int cfra, int chanshown)
+{
+       PrefetchQueueElem * e = 0;
+       int found_something = FALSE;
 
-                               /* bottom strip! */
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine > seq->machine) seqfirst= seq;
+       if (seq_thread_shutdown) {
+               return give_ibuf_seq(rectx, recty, cfra, chanshown);
+       }
 
+       while (!e) {
+               int success = FALSE;
+               pthread_mutex_lock(&queue_lock);
+
+               for (e = prefetch_done.first; e; e = e->next) {
+                       if (cfra == e->cfra &&
+                           chanshown == e->chanshown &&
+                           rectx == e->rectx && 
+                           recty == e->recty) {
+                               success = TRUE;
+                               found_something = TRUE;
+                               break;
                        }
-                       else if(seq->type & SEQ_EFFECT) {
-
-                               /* top strip! */
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine < seq->machine) seqfirst= seq;
+               }
 
+               if (!e) {
+                       for (e = prefetch_wait.first; e; e = e->next) {
+                               if (cfra == e->cfra &&
+                                   chanshown == e->chanshown &&
+                                   rectx == e->rectx && 
+                                   recty == e->recty) {
+                                       found_something = TRUE;
+                                       break;
+                               }
+                       }
+               }
 
+               if (!e) {
+                       PrefetchThread *tslot;
+
+                       for(tslot = running_threads.first; 
+                           tslot; tslot= tslot->next) {
+                               if (tslot->current &&
+                                   cfra == tslot->current->cfra &&
+                                   chanshown == tslot->current->chanshown &&
+                                   rectx == tslot->current->rectx && 
+                                   recty == tslot->current->recty) {
+                                       found_something = TRUE;
+                                       break;
+                               }
                        }
-                       else if(seq->type < SEQ_EFFECT) {       /* images */
+               }
+
+               /* e->ibuf is unrefed by render thread on next round. */
 
-                               /* bottom strip! a feature that allows you to store junk in locations above */
+               if (e) {
+                       seq_last_given_monoton_cfra = e->monoton_cfra;
+               }
+
+               pthread_mutex_unlock(&queue_lock);
 
-                               if(seqfirst==0) seqfirst= seq;
-                               else if(seqfirst->depth > seq->depth) seqfirst= seq;
-                               else if(seqfirst->machine > seq->machine) seqfirst= seq;
+               if (!success) {
+                       e = NULL;
 
+                       if (!found_something) {
+                               fprintf(stderr, 
+                                       "SEQ-THREAD: Requested frame "
+                                       "not in queue ???\n");
+                               break;
                        }
+                       pthread_mutex_lock(&frame_done_lock);
+                       pthread_cond_wait(&frame_done_cond, &frame_done_lock);
+                       pthread_mutex_unlock(&frame_done_lock);
                }
        }
+       
+       return e ? e->ibuf : 0;
+}
 
-       MEM_freeN(seqar);
+/* Functions to free imbuf and anim data on changes */
 
-       if(!seqfirst) return 0;
-       if(!seqfirst->curelem) return 0;
-       return seqfirst->curelem->ibuf;
+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) {
+               IMB_free_anim(seq->anim);
+               seq->anim = 0;
+       }
 }
 
-void free_imbuf_effect_spec(int cfra)
+void free_imbuf_seq_except(int cfra)
 {
+       Editing *ed= G.scene->ed;
        Sequence *seq;
-       StripElem *se;
-       Editing *ed;
+       TStripElem *se;
        int a;
 
-       ed= G.scene->ed;
        if(ed==0) return;
 
        WHILE_SEQ(&ed->seqbase) {
-
                if(seq->strip) {
+                       TStripElem * curelem = give_tstripelem(seq, cfra);
 
-                       if(seq->type & SEQ_EFFECT) {
-                               se= seq->strip->stripdata;
-                               for(a=0; a<seq->len; a++, se++) {
-                                       if(se==seq->curelem && se->ibuf) {
-                                               IMB_freeImBuf(se->ibuf);
-                                               se->ibuf= 0;
-                                               se->ok= 1;
-                                               se->se1= se->se2= se->se3= 0;
-                                       }
+                       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);
                }
        }
        END_SEQ
 }
 
-void free_imbuf_seq_except(int cfra)
+void free_imbuf_seq()
 {
+       Editing *ed= G.scene->ed;
        Sequence *seq;
-       StripElem *se;
-       Editing *ed;
+       TStripElem *se;
        int a;
 
-       ed= G.scene->ed;
        if(ed==0) return;
 
        WHILE_SEQ(&ed->seqbase) {
-
                if(seq->strip) {
-
-                       if( seq->type==SEQ_META ) {
-                               ;
+                       for(a = 0, se = seq->strip->tstripdata; 
+                           a < seq->strip->len && se; a++, se++) {
+                               free_imbuf_strip_elem(se);
                        }
-                       else {
-                               se= seq->strip->stripdata;
-                               for(a=0; a<seq->len; a++, se++) {
-                                       if(se!=seq->curelem && se->ibuf) {
-                                               IMB_freeImBuf(se->ibuf);
-                                               se->ibuf= 0;
-                                               se->ok= 1;
-                                               se->se1= se->se2= se->se3= 0;
-                                       }
-                               }
+                       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->type==SEQ_MOVIE) {
-                               if(seq->startdisp > cfra || seq->enddisp < cfra) {
-                                       if(seq->anim) {
-                                               IMB_free_anim(seq->anim);
-                                               seq->anim = 0;
-                                       }
-                               }
+                       if(seq->strip->ibuf_endstill) {
+                               IMB_freeImBuf(seq->strip->ibuf_endstill);
+                               seq->strip->ibuf_endstill = 0;
+                       }
+
+                       if(seq->type==SEQ_MOVIE)
+                               free_anim_seq(seq);
+                       if(seq->type==SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
                        }
                }
        }
        END_SEQ
 }
 
-void free_imbuf_seq()
+void free_imbuf_seq_with_ipo(struct Ipo *ipo)
 {
+       /* force update of all sequences with this ipo, on ipo changes */
+       Editing *ed= G.scene->ed;
        Sequence *seq;
-       StripElem *se;
-       Editing *ed;
-       int a;
 
-       ed= G.scene->ed;
        if(ed==0) return;
 
        WHILE_SEQ(&ed->seqbase) {
+               if(seq->ipo == ipo) {
+                       update_changed_seq_and_deps(seq, 0, 1);
+                       if(seq->type == SEQ_SPEED) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
+                       }
+               }
+       }
+       END_SEQ
+}
 
-               if(seq->strip) {
+static int update_changed_seq_recurs(Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
+{
+       Sequence *subseq;
+       int a, free_imbuf = 0;
+       TStripElem *se;
 
-                       if( seq->type==SEQ_META ) {
-                               ;
-                       }
-                       else {
-                               se= seq->strip->stripdata;
-                               for(a=0; a<seq->len; a++, se++) {
-                                       if(se->ibuf) {
-                                               IMB_freeImBuf(se->ibuf);
-                                               se->ibuf= 0;
-                                               se->ok= 1;
-                                               se->se1= se->se2= se->se3= 0;
-                                       }
-                               }
-                       }
+       /* recurs downwards to see if this seq depends on the changed seq */
 
-                       if(seq->type==SEQ_MOVIE) {
-                               if(seq->anim) {
-                                       IMB_free_anim(seq->anim);
-                                       seq->anim = 0;
-                               }
+       if(seq == NULL)
+               return 0;
+
+       if(seq == changed_seq)
+               free_imbuf = 1;
+       
+       for(subseq=seq->seqbase.first; subseq; subseq=subseq->next)
+               if(update_changed_seq_recurs(subseq, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       
+       if(seq->seq1)
+               if(update_changed_seq_recurs(seq->seq1, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       if(seq->seq2 && (seq->seq2 != seq->seq1))
+               if(update_changed_seq_recurs(seq->seq2, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2))
+               if(update_changed_seq_recurs(seq->seq3, changed_seq, len_change, ibuf_change))
+                       free_imbuf = TRUE;
+       
+       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) {
+                               sequence_effect_speed_rebuild_map(seq, 1);
                        }
                }
+
+               if(len_change)
+                       calc_sequence(seq);
        }
-       END_SEQ
+       
+       return free_imbuf;
 }
 
-void do_render_seq()
+void update_changed_seq_and_deps(Sequence *changed_seq, int len_change, int ibuf_change)
 {
-/*     static ImBuf *lastibuf=0; */
-       ImBuf *ibuf;
+       Editing *ed= G.scene->ed;
+       Sequence *seq;
+
+       if (!ed) return;
 
-       /* copy image into R.rectot */
+       for (seq=ed->seqbase.first; seq; seq=seq->next)
+               update_changed_seq_recurs(seq, changed_seq, len_change, ibuf_change);
+}
+
+/* bad levell call... */
+void do_render_seq(RenderResult *rr, int cfra)
+{
+       ImBuf *ibuf;
 
        G.f |= G_PLAYANIM;      /* waitcursor patch */
 
-       ibuf= give_ibuf_seq(CFRA);
+       ibuf= give_ibuf_seq(rr->rectx, rr->recty, cfra, 0);
+       
        if(ibuf) {
+               if(ibuf->rect_float) {
+                       if (!rr->rectf)
+                               rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
+                       
+                       memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
+                       
+                       /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
+                          can hang around when sequence render has rendered a 32 bits one before */
+                       if(rr->rect32) {
+                               MEM_freeN(rr->rect32);
+                               rr->rect32= NULL;
+                       }
+               }
+               else if(ibuf->rect) {
+                       if (!rr->rect32)
+                               rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
 
-               memcpy(R.rectot, ibuf->rect, 4*R.rectx*R.recty);
-
-               /* if (ibuf->zbuf) { */
-               /*      if (R.rectz) freeN(R.rectz); */
-               /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
-               /* } */
+                       memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
 
-               free_imbuf_seq_except(CFRA);
+                       /* if (ibuf->zbuf) { */
+                       /*      if (R.rectz) freeN(R.rectz); */
+                       /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
+                       /* } */
+               }
+               
+               /* Let the cache limitor take care of this (schlaile) */
+               /* While render let's keep all memory available for render 
+                  (ton)
+                  At least if free memory is tight...
+                  This can make a big difference in encoding speed
+                  (it is around 4 times(!) faster, if we do not waste time
+                  on freeing _all_ buffers every time on long timelines...)
+                  (schlaile)
+               */
+               {
+                       extern int mem_in_use;
+                       extern int mmap_in_use;
+
+                       int max = MEM_CacheLimiter_get_maximum();
+                       if (max != 0 && mem_in_use + mmap_in_use > max) {
+                               fprintf(stderr, "mem_in_use = %d, max = %d\n",
+                                       mem_in_use + mmap_in_use, max);
+                               fprintf(stderr, "Cleaning up, please wait...\n"
+                                       "If this happens very often,\n"
+                                       "consider "
+                                       "raising the memcache limit in the "
+                                       "user preferences.\n");
+                               free_imbuf_seq();
+                       }
+               }
+       }
+       else {
+               /* render result is delivered empty in most cases, nevertheless we handle all cases */
+               if (rr->rectf)
+                       memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
+               else if (rr->rect32)
+                       memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
+               else
+                       rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
        }
+       
        G.f &= ~G_PLAYANIM;
 
 }