diff options
Diffstat (limited to 'source/blender/blenkernel/intern/sequencer.c')
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 2259 |
1 files changed, 972 insertions, 1287 deletions
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 790087334c6..b6bb5c3a51b 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -39,7 +39,9 @@ #include "DNA_scene_types.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" +#include "DNA_sound_types.h" +#include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_main.h" @@ -49,10 +51,12 @@ #include "RNA_access.h" #include "RE_pipeline.h" +#include "BLI_math.h" #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_threads.h" #include <pthread.h> #include "IMB_imbuf.h" @@ -69,8 +73,6 @@ #endif /* **** XXX ******** */ -static int seqrectx= 0; /* bad bad global! */ -static int seqrecty= 0; //static void waitcursor(int val) {} //static int blender_test_break() {return 0;} @@ -88,71 +90,38 @@ void printf_strip(Sequence *seq) fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0)); } -void seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg) +int seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg) { Sequence *iseq; for(iseq= seqbase->first; iseq; iseq= iseq->next) { - seq_recursive_apply(iseq, apply_func, arg); + if(seq_recursive_apply(iseq, apply_func, arg) == -1) + return -1; /* bail out */ } + return 1; } -void seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg) +int seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg) { - if(apply_func(seq, arg) && seq->seqbase.first) - seqbase_recursive_apply(&seq->seqbase, apply_func, arg); + int ret= apply_func(seq, arg); + + if(ret == -1) + return -1; /* bail out */ + + if(ret && seq->seqbase.first) + ret = seqbase_recursive_apply(&seq->seqbase, apply_func, arg); + + return ret; } /* ********************************************************************** alloc / free functions ********************************************************************** */ -static void free_tstripdata(int len, TStripElem *se) -{ - TStripElem *seo; - int a; - - seo= se; - if (!se) - return; - - for(a=0; a<len; a++, se++) { - if(se->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = 0; - } - if(se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - se->ibuf_comp = 0; - } - } - - MEM_freeN(seo); -} void new_tstripdata(Sequence *seq) { if(seq->strip) { - free_tstripdata(seq->strip->len, seq->strip->tstripdata); - free_tstripdata(seq->strip->endstill, - seq->strip->tstripdata_endstill); - free_tstripdata(seq->strip->startstill, - seq->strip->tstripdata_startstill); - - seq->strip->tstripdata= 0; - seq->strip->tstripdata_endstill= 0; - seq->strip->tstripdata_startstill= 0; - - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - seq->strip->len= seq->len; } } @@ -198,23 +167,11 @@ void seq_free_strip(Strip *strip) MEM_freeN(strip->color_balance); } - free_tstripdata(strip->len, strip->tstripdata); - free_tstripdata(strip->endstill, strip->tstripdata_endstill); - free_tstripdata(strip->startstill, strip->tstripdata_startstill); - - if(strip->ibuf_startstill) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } - - if(strip->ibuf_endstill) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } - MEM_freeN(strip); } +static void seq_free_animdata(Scene *scene, Sequence *seq); + void seq_free_sequence(Scene *scene, Sequence *seq) { if(seq->strip) seq_free_strip(seq->strip); @@ -236,6 +193,8 @@ void seq_free_sequence(Scene *scene, Sequence *seq) if(seq->scene_sound) sound_remove_scene_sound(scene, seq->scene_sound); + + seq_free_animdata(scene, seq); } MEM_freeN(seq); @@ -504,6 +463,31 @@ void calc_sequence_disp(Scene *scene, Sequence *seq) seq_update_sound(scene, seq); } +static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq) +{ + Sequence *seq; + + /* for sound we go over full meta tree to update bounds of the sound strips, + since sound is played outside of evaluating the imbufs, */ + for(seq=metaseq->seqbase.first; seq; seq=seq->next) { + if(seq->type == SEQ_META) { + seq_update_sound_bounds_recursive(scene, seq); + } + else if((seq->type == SEQ_SOUND) || (seq->type == SEQ_SCENE)) { + if(seq->scene_sound) { + int startofs = seq->startofs; + int endofs = seq->endofs; + if(seq->startofs + seq->start < metaseq->start + metaseq->startofs) + startofs = metaseq->start + metaseq->startofs - seq->start; + + if(seq->start + seq->len - seq->endofs > metaseq->start + metaseq->len - metaseq->endofs) + endofs = seq->start + seq->len - metaseq->start - metaseq->len + metaseq->endofs; + sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, seq->start+seq->len - endofs, startofs); + } + } + } +} + void calc_sequence(Scene *scene, Sequence *seq) { Sequence *seqm; @@ -547,8 +531,8 @@ void calc_sequence(Scene *scene, Sequence *seq) if(seq->type==SEQ_META) { seqm= seq->seqbase.first; if(seqm) { - min= 1000000; - max= -1000000; + min= MAXFRAME * 2; + max= -MAXFRAME * 2; while(seqm) { if(seqm->startdisp < min) min= seqm->startdisp; if(seqm->enddisp > max) max= seqm->enddisp; @@ -563,14 +547,18 @@ void calc_sequence(Scene *scene, Sequence *seq) new_tstripdata(seq); } } + seq_update_sound_bounds_recursive(scene, seq); } calc_sequence_disp(scene, seq); } } -void reload_sequence_new_file(Scene *scene, Sequence * seq) +/* note: caller should run calc_sequence(scene, seq) after */ +void reload_sequence_new_file(Main *bmain, Scene *scene, Sequence * seq, int lock_range) { char str[FILE_MAXDIR+FILE_MAXFILE]; + int prev_startdisp, prev_enddisp; + /* note: dont rename the strip, will break animation curves */ if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || seq->type == SEQ_SOUND || @@ -578,6 +566,14 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) return; } + if(lock_range) { + /* keep so we dont have to move the actual start and end points (only the data) */ + calc_sequence_disp(scene, seq); + prev_startdisp= seq->startdisp; + prev_enddisp= seq->enddisp; + } + + new_tstripdata(seq); if (seq->type != SEQ_SCENE && seq->type != SEQ_META && @@ -588,7 +584,8 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) if (seq->type == SEQ_IMAGE) { /* Hack? */ - int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); + size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); + seq->len = olen; seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; @@ -623,7 +620,8 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) } seq->strip->len = seq->len; } else if (seq->type == SEQ_SCENE) { - Scene * sce = G.main->scene.first; + /* 'seq->scenenr' should be replaced with something more reliable */ + Scene * sce = bmain->scene.first; int nr = 1; while(sce) { @@ -639,9 +637,6 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) } else { sce = seq->scene; } - - BLI_strncpy(seq->name+2, sce->id.name + 2, SEQ_NAME_MAXSTR-2); - seqbase_unique_name_recursive(&scene->ed->seqbase, seq); seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; seq->len -= seq->anim_startofs; @@ -654,6 +649,12 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) free_proxy_seq(seq); + if(lock_range) { + seq_tx_set_final_left(seq, prev_startdisp); + seq_tx_set_final_right(seq, prev_enddisp); + seq_single_fix(seq); + } + calc_sequence(scene, seq); } @@ -709,12 +710,12 @@ static int clear_scene_in_allseqs_cb(Sequence *seq, void *arg_pt) return 1; } -void clear_scene_in_allseqs(Scene *scene) +void clear_scene_in_allseqs(Main *bmain, Scene *scene) { Scene *scene_iter; /* when a scene is deleted: test all seqs */ - for(scene_iter= G.main->scene.first; scene_iter; scene_iter= scene_iter->id.next) { + for(scene_iter= bmain->scene.first; scene_iter; scene_iter= scene_iter->id.next) { if(scene_iter != scene && scene_iter->ed) { seqbase_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene); } @@ -740,7 +741,7 @@ static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui) Sequence *seq; for(seq=seqbasep->first; seq; seq= seq->next) { if (sui->seq != seq && strcmp(sui->name_dest, seq->name+2)==0) { - sprintf(sui->name_dest, "%.18s.%03d", sui->name_src, sui->count++); + sprintf(sui->name_dest, "%.17s.%03d", sui->name_src, sui->count++); /*24 - 2 for prefix, -1 for \0 */ sui->match= 1; /* be sure to re-scan */ } } @@ -761,12 +762,17 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq) strcpy(sui.name_src, seq->name+2); strcpy(sui.name_dest, seq->name+2); + sui.count= 1; + sui.match= 1; /* assume the worst to start the loop */ + /* Strip off the suffix */ - if ((dot=strrchr(sui.name_src, '.'))) + if ((dot=strrchr(sui.name_src, '.'))) { *dot= '\0'; + dot++; - sui.count= 1; - sui.match= 1; /* assume the worst to start the loop */ + if(*dot) + sui.count= atoi(dot) + 1; + } while(sui.match) { sui.match= 0; @@ -797,6 +803,7 @@ static char *give_seqname_by_type(int type) case SEQ_GLOW: return "Glow"; case SEQ_TRANSFORM: return "Transform"; case SEQ_COLOR: return "Color"; + case SEQ_MULTICAM: return "Multicam"; case SEQ_SPEED: return "Speed"; default: return 0; @@ -888,143 +895,16 @@ static void multibuf(ImBuf *ibuf, float fmul) } } -static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) +static float give_stripelem_index(Sequence *seq, float cfra) { - TStripElem *se1, *se2, *se3; - float fac, facf; - int x, y; - int early_out; - struct SeqEffectHandle sh = get_sequence_effect(seq); - FCurve *fcu= NULL; - - if (!sh.execute) { /* effect not supported in this version... */ - make_black_ibuf(se->ibuf); - return; - } - - if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { - sh.get_default_fac(seq, cfra, &fac, &facf); - if( scene->r.mode & R_FIELDS ); else facf= fac; - } else { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - if (fcu) { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); - } - } else { - fac = facf = seq->effect_fader; - } - } - - early_out = sh.early_out(seq, fac, facf); + float nr; - if (early_out == -1) { /* no input needed */ - sh.execute(scene, seq, cfra, fac, facf, - se->ibuf->x, se->ibuf->y, - 0, 0, 0, se->ibuf); - return; - } - - switch (early_out) { - case 0: - if (se->se1==0 || se->se2==0 || se->se3==0) { - make_black_ibuf(se->ibuf); - return; - } - - se1= se->se1; - se2= se->se2; - se3= se->se3; - - if ( (se1==0 || se2==0 || se3==0) - || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) { - make_black_ibuf(se->ibuf); - return; - } - - break; - case 1: - if (se->se1 == 0) { - make_black_ibuf(se->ibuf); - return; - } - - se1= se->se1; - - if (se1 == 0 || se1->ibuf == 0) { - make_black_ibuf(se->ibuf); - return; - } - - if (se->ibuf != se1->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } - return; - case 2: - if (se->se2 == 0) { - make_black_ibuf(se->ibuf); - return; - } - - se2= se->se2; - - if (se2 == 0 || se2->ibuf == 0) { - make_black_ibuf(se->ibuf); - return; - } - if (se->ibuf != se2->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se2->ibuf; - IMB_refImBuf(se->ibuf); - } - return; - default: - make_black_ibuf(se->ibuf); - return; - } - - x= se2->ibuf->x; - y= se2->ibuf->y; - - if (!se1->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se1->ibuf); - } - if (!se2->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se2->ibuf); - } - if (!se3->ibuf->rect_float && se->ibuf->rect_float) { - IMB_float_from_rect(se3->ibuf); - } - - if (!se1->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se1->ibuf); - } - if (!se2->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se2->ibuf); - } - if (!se3->ibuf->rect && !se->ibuf->rect_float) { - IMB_rect_from_float(se3->ibuf); - } - - sh.execute(scene, seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, - se->ibuf); -} - -static int give_stripelem_index(Sequence *seq, int cfra) -{ - int nr; - - if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1; if(seq->len == 0) return -1; if(seq->flag&SEQ_REVERSE_FRAMES) { /*reverse frame in this sequence */ if(cfra <= seq->start) nr= seq->len-1; else if(cfra >= seq->start+seq->len-1) nr= 0; - else nr= (seq->start + seq->len) - cfra; + else nr= (seq->start + seq->len - 1) - cfra; } else { if(cfra <= seq->start) nr= 0; else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; @@ -1032,93 +912,12 @@ static int give_stripelem_index(Sequence *seq, int cfra) } if (seq->strobe < 1.0) seq->strobe = 1.0; if (seq->strobe > 1.0) { - nr -= (int)fmod((double)nr, (double)seq->strobe); + nr -= fmod((double)nr, (double)seq->strobe); } return nr; } -static TStripElem* alloc_tstripdata(int len, const char * name) -{ - int i; - TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name); - for (i = 0; i < len; i++) { - se[i].ok = STRIPELEM_OK; - } - return se; -} - -static TStripElem *give_tstripelem(Sequence *seq, int cfra) -{ - TStripElem *se; - int nr; - - se = seq->strip->tstripdata; - if (se == 0 && seq->len > 0) { - se = seq->strip->tstripdata = alloc_tstripdata(seq->len, - "tstripelems"); - } - nr = give_stripelem_index(seq, cfra); - - if (nr == -1) return 0; - if (se == 0) return 0; - - se += nr; - - /* if there are IPOs with blend modes active, one has to watch out - for startstill + endstill area: we can't use the same tstripelem - here for all ibufs, since then, blending with IPOs won't work! - - Rather common case, if you use a single image and try to fade - it in and out... or want to use your strip as a watermark in - alpha over mode... - */ - if (seq->blend_mode != SEQ_BLEND_REPLACE || - (/*seq->ipo && seq->ipo->curve.first &&*/ - (!(seq->type & SEQ_EFFECT) || !seq->seq1))) { - Strip * s = seq->strip; - if (cfra < seq->start) { - se = s->tstripdata_startstill; - if (seq->startstill > s->startstill) { - free_tstripdata(s->startstill, - s->tstripdata_startstill); - se = 0; - } - - if (se == 0) { - s->startstill = seq->startstill; - se = seq->strip->tstripdata_startstill - = alloc_tstripdata( - s->startstill, - "tstripelems_startstill"); - } - se += seq->start - cfra - 1; - - } else if (cfra > seq->start + seq->len-1) { - se = s->tstripdata_endstill; - if (seq->endstill > s->endstill) { - free_tstripdata(s->endstill, - s->tstripdata_endstill); - se = 0; - } - - if (se == 0) { - s->endstill = seq->endstill; - se = seq->strip->tstripdata_endstill - = alloc_tstripdata( - s->endstill, - "tstripelems_endstill"); - } - se += cfra - (seq->start + seq->len-1) - 1; - } - } - - - se->nr= nr; - - return se; -} - StripElem *give_stripelem(Sequence *seq, int cfra) { StripElem *se= seq->strip->stripdata; @@ -1127,7 +926,7 @@ StripElem *give_stripelem(Sequence *seq, int cfra) /* use the first */ } else { - int nr = give_stripelem_index(seq, cfra); + int nr = (int) give_stripelem_index(seq, cfra); if (nr == -1) return 0; if (se == 0) return 0; @@ -1231,7 +1030,8 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na return FALSE; } - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { + if ((seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) + || (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE)) { strcpy(dir, seq->strip->proxy->dir); } else { if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { @@ -1257,17 +1057,15 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na dir, render_size, se->name); frameno = 1; } else if (seq->type == SEQ_MOVIE) { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; + frameno = (int) give_stripelem_index(seq, cfra) + + seq->anim_startofs; snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, seq->strip->stripdata->name, render_size); } else { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; + frameno = (int) give_stripelem_index(seq, cfra) + + seq->anim_startofs; snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, render_size); @@ -1296,10 +1094,11 @@ static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, in } if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { - TStripElem * tse = give_tstripelem(seq, cfra); - int frameno = tse->nr + seq->anim_startofs; + int frameno = (int) give_stripelem_index(seq, cfra) + + seq->anim_startofs; if (!seq->strip->proxy->anim) { - if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + if (!seq_proxy_get_fname( + scene, seq, cfra, name, render_size)) { return 0; } @@ -1327,7 +1126,7 @@ static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, in static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, int build_proxy_run, int render_size); -static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size) +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty) { char name[PROXY_MAXFILE]; int quality; @@ -1364,7 +1163,8 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } - do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size); + do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size, + seqrectx, seqrecty); if (!se->ibuf) { return; @@ -1398,7 +1198,8 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } -static void seq_proxy_rebuild(Scene *scene, Sequence * seq) +static void seq_proxy_rebuild(Scene *scene, Sequence * seq, int seqrectx, + int seqrecty) { int cfra; float rsize = seq->strip->proxy->size; @@ -1430,7 +1231,8 @@ static void seq_proxy_rebuild(Scene *scene, Sequence * seq) if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { //XXX set_timecursor(cfra); - seq_proxy_build_frame(scene, seq, cfra, rsize); + seq_proxy_build_frame(scene, seq, cfra, rsize, + seqrectx, seqrecty); tse->flag |= STRIPELEM_PREVIEW_DONE; } if (blender_test_break()) { @@ -1444,7 +1246,8 @@ static void seq_proxy_rebuild(Scene *scene, Sequence * seq) if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { //XXX set_timecursor(cfra); - seq_proxy_build_frame(scene, seq, cfra, rsize); + seq_proxy_build_frame(scene, seq, cfra, rsize, + seqrectx, seqrecty); tse->flag |= STRIPELEM_PREVIEW_DONE; } if (blender_test_break()) { @@ -1466,15 +1269,21 @@ static StripColorBalance calc_cb(StripColorBalance * cb_) StripColorBalance cb = *cb_; int c; - if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) { - for (c = 0; c < 3; c++) { - cb.lift[c] = 1.0 - cb.lift[c]; - } - } else { + for (c = 0; c < 3; c++) { + cb.lift[c] = 2.0f - cb.lift[c]; + } + + if(cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) { for (c = 0; c < 3; c++) { - cb.lift[c] = -(1.0 - cb.lift[c]); + /* tweak to give more subtle results + * values above 1.0 are scaled */ + if(cb.lift[c] > 1.0f) + cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0f) + 1.0f; + + cb.lift[c] = 2.0f - cb.lift[c]; } } + if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) { for (c = 0; c < 3; c++) { if (cb.gain[c] != 0.0) { @@ -1498,25 +1307,27 @@ static StripColorBalance calc_cb(StripColorBalance * cb_) return cb; } +/* note: lift is actually 2-lift */ +MINLINE float color_balance_fl(float in, const float lift, const float gain, const float gamma, const float mul) +{ + float x= (((in - 1.0f) * lift) + 1.0f) * gain; + + /* prevent NaN */ + if (x < 0.f) x = 0.f; + + return powf(x, gamma) * mul; +} + static void make_cb_table_byte(float lift, float gain, float gamma, unsigned char * table, float mul) { int y; for (y = 0; y < 256; y++) { - float v = 1.0 * y / 255; - v *= gain; - v += lift; - v = pow(v, gamma); - v *= mul; - if ( v > 1.0) { - v = 1.0; - } else if (v < 0.0) { - v = 0.0; - } + float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul); + CLAMP(v, 0.0f, 1.0f); table[y] = v * 255; } - } static void make_cb_table_float(float lift, float gain, float gamma, @@ -1525,21 +1336,17 @@ static void make_cb_table_float(float lift, float gain, float gamma, int y; for (y = 0; y < 256; y++) { - float v = (float) y * 1.0 / 255.0; - v *= gain; - v += lift; - v = pow(v, gamma); - v *= mul; + float v= color_balance_fl((float)y * (1.0 / 255.0f), lift, gain, gamma, mul); table[y] = v; } } -static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul) +static void color_balance_byte_byte(Sequence * seq, ImBuf* ibuf, float mul) { unsigned char cb_tab[3][256]; int c; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + unsigned char * p = (unsigned char*) ibuf->rect; + unsigned char * e = p + ibuf->x * 4 * ibuf->y; StripColorBalance cb = calc_cb(seq->strip->color_balance); @@ -1557,24 +1364,24 @@ static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul) } } -static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul) +static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul) { float cb_tab[4][256]; int c,i; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + unsigned char * p = (unsigned char*) ibuf->rect; + unsigned char * e = p + ibuf->x * 4 * ibuf->y; float * o; StripColorBalance cb; - imb_addrectfloatImBuf(se->ibuf); + imb_addrectfloatImBuf(ibuf); - o = se->ibuf->rect_float; + o = ibuf->rect_float; cb = calc_cb(seq->strip->color_balance); for (c = 0; c < 3; c++) { make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], - cb_tab[c], mul); + cb_tab[c], mul); } for (i = 0; i < 256; i++) { @@ -1591,30 +1398,29 @@ static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul) } } -static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul) +static void color_balance_float_float(Sequence * seq, ImBuf* ibuf, float mul) { - float * p = se->ibuf->rect_float; - float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y; + float * p = ibuf->rect_float; + float * e = ibuf->rect_float + ibuf->x * 4* ibuf->y; StripColorBalance cb = calc_cb(seq->strip->color_balance); while (p < e) { int c; for (c = 0; c < 3; c++) { - p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], - cb.gamma[c]) * mul; + p[c]= color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul); } p += 4; } } -static void color_balance(Sequence * seq, TStripElem* se, float mul) +static void color_balance(Sequence * seq, ImBuf* ibuf, float mul) { - if (se->ibuf->rect_float) { - color_balance_float_float(seq, se, mul); + if (ibuf->rect_float) { + color_balance_float_float(seq, ibuf, mul); } else if(seq->flag & SEQ_MAKE_FLOAT) { - color_balance_byte_float(seq, se, mul); + color_balance_byte_float(seq, ibuf, mul); } else { - color_balance_byte_byte(seq, se, mul); + color_balance_byte_byte(seq, ibuf, mul); } } @@ -1637,44 +1443,49 @@ static void color_balance(Sequence * seq, TStripElem* se, float mul) */ -static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra) +int input_have_to_preprocess( + Scene *scene, Sequence * seq, float cfra, int seqrectx, int seqrecty) { 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)) { + (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)) { return TRUE; } mul = seq->mul; - if(seq->blend_mode == SEQ_BLEND_REPLACE && - !(seq->type & SEQ_EFFECT)) { + if(seq->blend_mode == SEQ_BLEND_REPLACE) { mul *= seq->blend_opacity / 100.0; } if (mul != 1.0) { return TRUE; } + + if (seq->sat != 1.0) { + return TRUE; + } return FALSE; } -static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra) +static ImBuf * input_preprocess( + Scene *scene, Sequence *seq, float cfra, int seqrectx, int seqrecty, + ImBuf * ibuf) { float mul; - seq->strip->orx= se->ibuf->x; - seq->strip->ory= se->ibuf->y; + seq->strip->orx= ibuf->x; + seq->strip->ory= ibuf->y; if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { - IMB_filtery(se->ibuf); + IMB_filtery(ibuf); } if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { @@ -1692,8 +1503,8 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf t = *seq->strip->transform; } - sx = se->ibuf->x - c.left - c.right; - sy = se->ibuf->y - c.top - c.bottom; + sx = ibuf->x - c.left - c.right; + sy = ibuf->y - c.top - c.bottom; dx = sx; dy = sy; @@ -1702,39 +1513,62 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf dy = scene->r.ysch; } - if (c.top + c.bottom >= se->ibuf->y || - c.left + c.right >= se->ibuf->x || + if (c.top + c.bottom >= ibuf->y || + c.left + c.right >= ibuf->x || t.xofs >= dx || t.yofs >= dy) { - make_black_ibuf(se->ibuf); + make_black_ibuf(ibuf); } else { ImBuf * i; - if (se->ibuf->rect_float) { + if (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); + IMB_rectcpy(i, ibuf, + t.xofs, t.yofs, + c.left, c.bottom, + sx, sy); + + IMB_freeImBuf(ibuf); - se->ibuf = i; + ibuf = i; } } if(seq->flag & SEQ_FLIPX) { - IMB_flipx(se->ibuf); + IMB_flipx(ibuf); } + if(seq->flag & SEQ_FLIPY) { - IMB_flipy(se->ibuf); + IMB_flipy(ibuf); } - if(seq->mul == 0.0) { - seq->mul = 1.0; + if(seq->sat != 1.0f) { + /* inline for now, could become an imbuf function */ + int i; + char *rct= (char *)ibuf->rect; + float *rctf= ibuf->rect_float; + const float sat= seq->sat; + float hsv[3]; + + if(rct) { + float rgb[3]; + for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { + rgb_byte_to_float(rct, rgb); + rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); + hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2); + rgb_float_to_byte(rgb, rct); + } + } + + if(rctf) { + for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { + rgb_to_hsv(rctf[0], rctf[1], rctf[2], hsv, hsv+1, hsv+2); + hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf+1, rctf+2); + } + } } mul = seq->mul; @@ -1744,708 +1578,520 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf } if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - color_balance(seq, se, mul); + color_balance(seq, ibuf, mul); mul = 1.0; } if(seq->flag & SEQ_MAKE_FLOAT) { - if (!se->ibuf->rect_float) { - int profile = IB_PROFILE_NONE; - - /* no color management: - * don't disturb the existing profiles */ - SWAP(int, se->ibuf->profile, profile); + if (!ibuf->rect_float) + IMB_float_from_rect_simple(ibuf); - IMB_float_from_rect(se->ibuf); - - SWAP(int, se->ibuf->profile, profile); - } - if (se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); + if (ibuf->rect) { + imb_freerectImBuf(ibuf); } } if(mul != 1.0) { - multibuf(se->ibuf, mul); + multibuf(ibuf, mul); } if(seq->flag & SEQ_MAKE_PREMUL) { - if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) { - converttopremul(se->ibuf); + if(ibuf->depth == 32 && ibuf->zbuf == 0) { + IMB_premultiply_alpha(ibuf); } } - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { + if(ibuf->x != seqrectx || ibuf->y != seqrecty ) { if(scene->r.mode & R_OSA) { - IMB_scaleImBuf(se->ibuf, - (short)seqrectx, (short)seqrecty); + IMB_scaleImBuf(ibuf, + (short)seqrectx, (short)seqrecty); } else { - IMB_scalefastImBuf(se->ibuf, + IMB_scalefastImBuf(ibuf, (short)seqrectx, (short)seqrecty); } } + return ibuf; } -/* test if image too small or discarded from cache: reload */ - -static void test_and_auto_discard_ibuf(TStripElem * se) +static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr, + int seqrectx, int seqrecty) { - if (se->ibuf) { - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty - || !(se->ibuf->rect || se->ibuf->rect_float)) { - IMB_freeImBuf(se->ibuf); + ImBuf * rval = 0; + ImBuf * ibuf = 0; - se->ibuf= 0; - se->ok= STRIPELEM_OK; - } + if (nr == 0) { + ibuf = seq_stripelem_cache_get( + seq, seqrectx, seqrecty, seq->start, + SEQ_STRIPELEM_IBUF_STARTSTILL); + } + if (nr == seq->len - 1) { + ibuf = seq_stripelem_cache_get( + seq, seqrectx, seqrecty, seq->start, + SEQ_STRIPELEM_IBUF_ENDSTILL); } - if (se->ibuf_comp) { - if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty - || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) { - IMB_freeImBuf(se->ibuf_comp); - se->ibuf_comp = 0; - } + if (ibuf) { + rval = IMB_dupImBuf(ibuf); + IMB_freeImBuf(ibuf); } + + return rval; } -static void test_and_auto_discard_ibuf_stills(Strip * strip) +static void copy_to_ibuf_still(Sequence * seq, float nr, + ImBuf * ibuf) { - if (strip->ibuf_startstill) { - if (!strip->ibuf_startstill->rect && - !strip->ibuf_startstill->rect_float) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } + if (nr == 0) { + seq_stripelem_cache_put( + seq, 0, 0, seq->start, + SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); } - if (strip->ibuf_endstill) { - if (!strip->ibuf_endstill->rect && - !strip->ibuf_endstill->rect_float) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } + if (nr == seq->len - 1) { + seq_stripelem_cache_put( + seq, 0, 0, seq->start, + SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf); } } -static void copy_from_ibuf_still(Sequence * seq, TStripElem * se) -{ - if (!se->ibuf) { - if (se->nr == 0 && seq->strip->ibuf_startstill) { - IMB_cache_limiter_touch(seq->strip->ibuf_startstill); - - se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill); - } - if (se->nr == seq->len - 1 - && (seq->len != 1) - && seq->strip->ibuf_endstill) { - IMB_cache_limiter_touch(seq->strip->ibuf_endstill); - - se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill); - } - } -} +/* ********************************************************************** + strip rendering functions + ********************************************************************** */ -static void copy_to_ibuf_still(Sequence * seq, TStripElem * se) -{ - if (se->ibuf) { - if (se->nr == 0) { - seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf); +static ImBuf* seq_render_strip_stack( + Main *bmain, Scene *scene, + ListBase *seqbasep, float cfra, int chanshown, int render_size, + int seqrectx, int seqrecty); - IMB_cache_limiter_insert(seq->strip->ibuf_startstill); - IMB_cache_limiter_touch(seq->strip->ibuf_startstill); - } - if (se->nr == seq->len - 1 && seq->len != 1) { - seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf); +static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra, + int render_size, + int seqrectx, int seqrecty); - IMB_cache_limiter_insert(seq->strip->ibuf_endstill); - IMB_cache_limiter_touch(seq->strip->ibuf_endstill); - } - } -} -static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown) +static ImBuf* seq_render_effect_strip_impl( + Main *bmain, Scene *scene, float cfra, Sequence *seq, int render_size, + int seqrectx, int seqrecty) { - Sequence* seq_arr[MAXSEQ+1]; + float fac, facf; + int early_out; int i; - TStripElem* se = 0; + int must_preprocess = FALSE; - evaluate_seq_frame_gen(seq_arr, seqbasep, cfra); - - for (i = 0; i < MAXSEQ; i++) { - if (!video_seq_is_rendered(seq_arr[i])) { - continue; - } - se = give_tstripelem(seq_arr[i], cfra); - if (se) { - if (se->ibuf) { - IMB_freeImBuf(se->ibuf); - - se->ibuf= 0; - se->ok= STRIPELEM_OK; - } + struct SeqEffectHandle sh = get_sequence_effect(seq); + FCurve *fcu= NULL; + ImBuf * ibuf[3]; + ImBuf * out = 0; - if (se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); + ibuf[0] = ibuf[1] = ibuf[2] = 0; - se->ibuf_comp = 0; - } - } + if (!sh.execute) { /* effect not supported in this version... */ + goto finish; } - -} -static void check_limiter_refcount(const char * func, TStripElem *se) -{ - if (se && se->ibuf) { - int refcount = IMB_cache_limiter_get_refcount(se->ibuf); - if (refcount != 1) { - /* can happen on complex pipelines */ - if (refcount > 1 && (G.f & G_DEBUG) == 0) { - return; - } - - fprintf(stderr, - "sequencer: (ibuf) %s: " - "suspicious memcache " - "limiter refcount: %d\n", func, refcount); - } - } -} - -static void check_limiter_refcount_comp(const char * func, TStripElem *se) -{ - if (se && se->ibuf_comp) { - int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp); - if (refcount != 1) { - /* can happen on complex pipelines */ - if (refcount > 1 && (G.f & G_DEBUG) == 0) { - return; + if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { + sh.get_default_fac(seq, cfra, &fac, &facf); + if( scene->r.mode & R_FIELDS ); else facf= fac; + } else { + fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, + "effect_fader", 0); + if (fcu) { + fac = facf = evaluate_fcurve(fcu, cfra); + if( scene->r.mode & R_FIELDS ) { + facf = evaluate_fcurve(fcu, cfra + 0.5); } - fprintf(stderr, - "sequencer: (ibuf comp) %s: " - "suspicious memcache " - "limiter refcount: %d\n", func, refcount); + } else { + fac = facf = seq->effect_fader; } } -} - -static TStripElem* do_build_seq_array_recursively(Scene *scene, - ListBase *seqbasep, int cfra, int chanshown, int render_size); - -static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run, int render_size) -{ - char name[FILE_MAXDIR+FILE_MAXFILE]; - int use_limiter = TRUE; - - test_and_auto_discard_ibuf(se); - test_and_auto_discard_ibuf_stills(seq->strip); - - if(seq->type == SEQ_META) { - TStripElem * meta_se = 0; - int use_preprocess = FALSE; - use_limiter = FALSE; - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - use_limiter = TRUE; - use_preprocess = TRUE; - } - } - if(!se->ibuf && seq->seqbase.first) { - meta_se = do_build_seq_array_recursively(scene, - &seq->seqbase, seq->start + se->nr, 0, - render_size); - - check_limiter_refcount("do_build_seq_ibuf: for META", meta_se); - } - - se->ok = STRIPELEM_OK; - - if(!se->ibuf && meta_se) { - se->ibuf = meta_se->ibuf_comp; - if(se->ibuf && - (!input_have_to_preprocess(scene, seq, se, cfra) || - build_proxy_run)) { - IMB_refImBuf(se->ibuf); - if (build_proxy_run) { - IMB_cache_limiter_unref(se->ibuf); - } - } else if (se->ibuf) { - struct ImBuf * i = IMB_dupImBuf(se->ibuf); + early_out = sh.early_out(seq, fac, facf); - IMB_cache_limiter_unref(se->ibuf); + if (early_out == -1) { /* no input needed */ + out = sh.execute(bmain, scene, seq, cfra, fac, facf, + seqrectx, seqrecty, render_size, + 0, 0, 0); + goto finish; + } - se->ibuf = i; - use_limiter = TRUE; - use_preprocess = TRUE; - } - } else if (se->ibuf) { - use_limiter = TRUE; - } - if (meta_se) { - free_metastrip_imbufs( - &seq->seqbase, seq->start + se->nr, 0); - } + must_preprocess = input_have_to_preprocess( + scene, seq, cfra, seqrectx, seqrecty); - if (use_preprocess) { - input_preprocess(scene, seq, se, cfra); - } - } else if(seq->type & SEQ_EFFECT) { - int use_preprocess = FALSE; - /* should the effect be recalculated? */ - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - use_preprocess = TRUE; - } + switch (early_out) { + case 0: + break; + case 1: + if (seq->seq1) { + ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra, + render_size, + seqrectx, seqrecty); } - - if(se->ibuf == 0) { - /* if any inputs are rectfloat, output is float too */ - if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || - (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) || - (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - do_effect(scene, cfra, seq, se); - if (input_have_to_preprocess(scene, seq, se, cfra) && - !build_proxy_run) { - if ((se->se1 && (se->ibuf == se->se1->ibuf)) || - (se->se2 && (se->ibuf == se->se2->ibuf))) { - struct ImBuf * i - = IMB_dupImBuf(se->ibuf); - - IMB_freeImBuf(se->ibuf); - - se->ibuf = i; - } - use_preprocess = TRUE; + if (ibuf[0]) { + if (must_preprocess) { + out = IMB_dupImBuf(ibuf[0]); + } else { + out = ibuf[0]; + IMB_refImBuf(out); } } - if (use_preprocess) { - input_preprocess(scene, seq, se, cfra); - } - } else if(seq->type == SEQ_IMAGE) { - if(se->ok == STRIPELEM_OK && se->ibuf == 0) { - StripElem * s_elem = give_stripelem(seq, cfra); - BLI_join_dirfile(name, seq->strip->dir, s_elem->name); - BLI_path_abs(name, G.sce); - if (!build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - copy_from_ibuf_still(seq, se); - - if (!se->ibuf) { - se->ibuf= IMB_loadiffname( - name, IB_rect); - /* we don't need both (speed reasons)! */ - if (se->ibuf && - se->ibuf->rect_float && se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } - - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(scene, seq, se, cfra); + goto finish; + case 2: + if (seq->seq2) { + ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra, + render_size, + seqrectx, seqrecty); + } + if (ibuf[1]) { + if (must_preprocess) { + out = IMB_dupImBuf(ibuf[1]); + } else { + out = ibuf[1]; + IMB_refImBuf(out); } } - } else if(seq->type == SEQ_MOVIE) { - if(se->ok == STRIPELEM_OK && se->ibuf==0) { - if(!build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - } - copy_from_ibuf_still(seq, se); + goto finish; + default: + goto finish; + } - if (se->ibuf == 0) { - if(seq->anim==0) { - BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); - BLI_path_abs(name, G.sce); - - seq->anim = openanim( - name, IB_rect | - ((seq->flag & SEQ_FILTERY) - ? IB_animdeinterlace : 0)); - } - if(seq->anim) { - IMB_anim_set_preseek(seq->anim, seq->anim_preseek); - se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs); - /* we don't need both (speed reasons)! */ - if (se->ibuf - && se->ibuf->rect_float - && se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } + if (seq->seq1) { + ibuf[0] = seq_render_strip(bmain, scene, seq->seq1, cfra, + render_size, + seqrectx, seqrecty); + } - } - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(scene, seq, se, cfra); - } - } - } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions - Scene *sce= seq->scene;// *oldsce= scene; - int have_seq= FALSE; - int sce_valid= FALSE; + if (seq->seq2) { + ibuf[1] = seq_render_strip(bmain, scene, seq->seq2, cfra, + render_size, + seqrectx, seqrecty); + } - if(sce) { - have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; - sce_valid= (sce->camera || have_seq); - } + if (seq->seq3) { + ibuf[2] = seq_render_strip(bmain, scene, seq->seq3, cfra, + render_size, + seqrectx, seqrecty); + } - if (se->ibuf == NULL && sce_valid && !build_proxy_run) { - se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (se->ibuf) { - input_preprocess(scene, seq, se, cfra); - } - } + if (!ibuf[0] || !ibuf[1]) { + goto finish; + } - if (se->ibuf == NULL && sce_valid) { - copy_from_ibuf_still(seq, se); - if (se->ibuf) { - input_preprocess(scene, seq, se, cfra); - } - } - - if (!sce_valid) { - se->ok = STRIPELEM_FAILED; - } - else if (se->ibuf==NULL && sce_valid) { - int frame= seq->sfra + se->nr + seq->anim_startofs; - int oldcfra = seq->scene->r.cfra; - Object *oldcamera= seq->scene->camera; - ListBase oldmarkers; - - /* Hack! This function can be called from do_render_seq(), in that case - the seq->scene can already have a Render initialized with same name, - so we have to use a default name. (compositor uses scene name to - find render). - However, when called from within the UI (image preview in sequencer) - we do want to use scene Render, that way the render result is defined - for display in render/imagewindow - - Hmm, don't see, why we can't do that all the time, - and since G.rendering is uhm, gone... (Peter) - */ - - int rendering = 1; - int doseq; - int doseq_gl= G.rendering ? (scene->r.seq_flag & R_SEQ_GL_REND) : (scene->r.seq_flag & R_SEQ_GL_PREV); - - /* prevent eternal loop */ - doseq= scene->r.scemode & R_DOSEQ; - scene->r.scemode &= ~R_DOSEQ; - - seq->scene->r.cfra= frame; - if(seq->scene_camera) seq->scene->camera= seq->scene_camera; - else scene_camera_switch_update(seq->scene); + out = sh.execute(bmain, scene, seq, cfra, fac, facf, seqrectx, seqrecty, + render_size, + ibuf[0], ibuf[1], ibuf[2]); -#ifdef DURIAN_CAMERA_SWITCH - /* stooping to new low's in hackyness :( */ - oldmarkers= seq->scene->markers; - seq->scene->markers.first= seq->scene->markers.last= NULL; -#endif +finish: + for (i = 0; i < 3; i++) { + IMB_freeImBuf(ibuf[i]); + } - if(sequencer_view3d_cb && doseq_gl && (seq->scene == scene || have_seq==0)) { - /* opengl offscreen render */ - scene_update_for_newframe(seq->scene, seq->scene->lay); - se->ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, scene->r.seq_prev_type); - } - else { - Render *re; - RenderResult rres; + if (!out) { + out = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + } - if(rendering) - re= RE_NewRender(" do_build_seq_ibuf"); - else - re= RE_NewRender(sce->id.name); + return out; +} - RE_BlenderFrame(re, sce, NULL, sce->lay, frame); - RE_AcquireResultImage(re, &rres); +static ImBuf * seq_render_scene_strip_impl( + Main *bmain, Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty) +{ + ImBuf * ibuf = 0; + float frame= seq->sfra + nr + seq->anim_startofs; + float oldcfra; + Object *oldcamera; + ListBase oldmarkers; + + /* Hack! This function can be called from do_render_seq(), in that case + the seq->scene can already have a Render initialized with same name, + so we have to use a default name. (compositor uses scene name to + find render). + However, when called from within the UI (image preview in sequencer) + we do want to use scene Render, that way the render result is defined + for display in render/imagewindow + + Hmm, don't see, why we can't do that all the time, + and since G.rendering is uhm, gone... (Peter) + */ - if(rres.rectf) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); - memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); - if(rres.rectz) { - addzbuffloatImBuf(se->ibuf); - memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); - } - } else if (rres.rect32) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); - memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); - } + int rendering = G.rendering; + int doseq; + int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV); + int have_seq= FALSE; + Scene *sce= seq->scene; /* dont refer to seq->scene above this point!, it can be NULL */ + int sce_valid= FALSE; - RE_ReleaseResultImage(re); + if(sce) { + have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first; + sce_valid= (sce->camera || have_seq); + } - // BIF_end_render_callbacks(); - } - - /* restore */ - scene->r.scemode |= doseq; + if (!sce_valid) + return NULL; - seq->scene->r.cfra = oldcfra; - seq->scene->camera= oldcamera; + oldcfra= seq->scene->r.cfra; + oldcamera= seq->scene->camera; + /* prevent eternal loop */ + doseq= scene->r.scemode & R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; + + seq->scene->r.cfra= frame; + if(seq->scene_camera) + seq->scene->camera= seq->scene_camera; + else + scene_camera_switch_update(seq->scene); + #ifdef DURIAN_CAMERA_SWITCH - /* stooping to new low's in hackyness :( */ - seq->scene->markers= oldmarkers; + /* stooping to new low's in hackyness :( */ + oldmarkers= seq->scene->markers; + seq->scene->markers.first= seq->scene->markers.last= NULL; #endif - - copy_to_ibuf_still(seq, se); - - if (!build_proxy_run) { - if(se->ibuf == NULL) { - se->ok = STRIPELEM_FAILED; - } else { - input_preprocess(scene, seq, se, cfra); - } + + if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) { + /* opengl offscreen render */ + scene_update_for_newframe(bmain, seq->scene, seq->scene->lay); + ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, IB_rect, + scene->r.seq_prev_type); + } + else { + Render *re; + RenderResult rres; + + if(rendering) + re= RE_NewRender(" do_build_seq_ibuf"); + else + re= RE_NewRender(sce->id.name); + + RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame); + + RE_AcquireResultImage(re, &rres); + + if(rres.rectf) { + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); + memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); + if(rres.rectz) { + addzbuffloatImBuf(ibuf); + memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); } + /* float buffers in the sequencer are not linear */ + ibuf->profile= IB_PROFILE_LINEAR_RGB; + IMB_convert_profile(ibuf, IB_PROFILE_SRGB); } - } - if (!build_proxy_run) { - if (se->ibuf && use_limiter) { - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); + else if (rres.rect32) { + ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); + memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); } + + RE_ReleaseResultImage(re); + + // BIF_end_render_callbacks(); } -} + + /* restore */ + scene->r.scemode |= doseq; + + seq->scene->r.cfra = oldcfra; + seq->scene->camera= oldcamera; + +#ifdef DURIAN_CAMERA_SWITCH + /* stooping to new low's in hackyness :( */ + seq->scene->markers= oldmarkers; +#endif -static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size); + return ibuf; +} -static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size) +static ImBuf * seq_render_strip(Main *bmain, Scene *scene, Sequence * seq, float cfra, + int render_size, + int seqrectx, int seqrecty) { - float fac, facf; - struct SeqEffectHandle sh = get_sequence_effect(seq); - int early_out; - FCurve *fcu= NULL; - - se->se1 = 0; - se->se2 = 0; - se->se3 = 0; - - if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) { - sh.get_default_fac(seq, cfra, &fac, &facf); - if( scene->r.mode & R_FIELDS ); else facf= fac; - } else { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, - "effect_fader", 0); - if (fcu) { - fac = facf = evaluate_fcurve(fcu, cfra); - if( scene->r.mode & R_FIELDS ) { - facf = evaluate_fcurve(fcu, cfra + 0.5); - } - } else { - fac = facf = seq->effect_fader; - } - } + char name[FILE_MAXDIR+FILE_MAXFILE]; + int use_preprocess = input_have_to_preprocess( + scene, seq, cfra, seqrectx, seqrecty); + ImBuf * ibuf = seq_stripelem_cache_get( + seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF); + float nr = give_stripelem_index(seq, cfra); - early_out = sh.early_out(seq, fac, facf); - switch (early_out) { - case -1: - /* no input needed */ - break; - case 0: - se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); - se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); - if (seq->seq3) { - se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size); - } - break; - case 1: - se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); - break; - case 2: - se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); - break; + /* currently, we cache preprocessed images */ + if (ibuf) { + use_preprocess = FALSE; } + if(seq->type == SEQ_META) { + ImBuf * meta_ibuf = 0; - do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + if (ibuf == 0) { + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } - /* children are not needed anymore ... */ + if(!ibuf && seq->seqbase.first) { + meta_ibuf = seq_render_strip_stack( + bmain, scene, + &seq->seqbase, seq->start + nr, 0, + render_size, seqrectx, seqrecty); + } - if (se->se1 && se->se1->ibuf) { - IMB_cache_limiter_unref(se->se1->ibuf); - } - if (se->se2 && se->se2->ibuf) { - IMB_cache_limiter_unref(se->se2->ibuf); - } - if (se->se3 && se->se3->ibuf) { - IMB_cache_limiter_unref(se->se3->ibuf); - } - check_limiter_refcount("do_effect_seq_recursively", se); -} + if(!ibuf && meta_ibuf) { + ibuf = meta_ibuf; + if(ibuf && use_preprocess) { + struct ImBuf * i = IMB_dupImBuf(ibuf); -static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - TStripElem *se; + IMB_freeImBuf(ibuf); - se = give_tstripelem(seq, cfra); + ibuf = i; + } + } + } else if(seq->type == SEQ_SPEED) { + ImBuf * child_ibuf = 0; - if(se) { - if (seq->type & SEQ_EFFECT) { - do_effect_seq_recursively(scene, seq, se, cfra, render_size); - } else { - do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + if (ibuf == 0) { + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); } - } - return se; -} -/* FIXME: - -If cfra was float throughout blender (especially in the render -pipeline) one could even _render_ with subframe precision -instead of faking using the blend code below... + if (ibuf == 0) { + float f_cfra; + SpeedControlVars * s + = (SpeedControlVars *)seq->effectdata; -*/ + sequence_effect_speed_rebuild_map(scene, seq, 0); -static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; - int nr = cfra - seq->start; - float f_cfra; - int cfra_left; - int cfra_right; - TStripElem * se = 0; - TStripElem * se1 = 0; - TStripElem * se2 = 0; - - sequence_effect_speed_rebuild_map(scene, seq, 0); - - f_cfra = seq->start + s->frameMap[nr]; - - cfra_left = (int) floor(f_cfra); - cfra_right = (int) ceil(f_cfra); + /* weeek! */ + f_cfra = seq->start + s->frameMap[(int) nr]; - se = give_tstripelem(seq, cfra); + child_ibuf = seq_render_strip(bmain, scene, seq->seq1, f_cfra, + render_size, + seqrectx, seqrecty); + } - if (!se) { - return se; - } + if (!ibuf && child_ibuf) { + ibuf = child_ibuf; + if(ibuf && use_preprocess) { + struct ImBuf * i = IMB_dupImBuf(ibuf); - if (cfra_left == cfra_right || - (s->flags & SEQ_SPEED_BLEND) == 0) { - test_and_auto_discard_ibuf(se); + IMB_freeImBuf(ibuf); - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); + ibuf = i; + } + } + } else if(seq->type & SEQ_EFFECT) { + /* should the effect be recalculated? */ + + if (ibuf == 0) { + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + if(ibuf == 0) { + ibuf = seq_render_effect_strip_impl( + bmain, scene, cfra, seq, render_size, + seqrectx, seqrecty); + } + } else if(seq->type == SEQ_IMAGE) { + StripElem * s_elem = give_stripelem(seq, cfra); - if (se1 == 0 || se1->ibuf == 0) { - make_black_ibuf(se->ibuf); - } else { - if (se->ibuf != se1->ibuf) { - if (se->ibuf) { - IMB_freeImBuf(se->ibuf); - } + if(ibuf == 0 && s_elem) { + BLI_join_dirfile(name, seq->strip->dir, s_elem->name); + BLI_path_abs(name, G.sce); - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } - } + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); } - } 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 (ibuf == 0) { + ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty); } - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); - se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size); + if (ibuf == 0 && s_elem && + (ibuf = IMB_loadiffname(name, IB_rect))) { + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); + + /* all sequencer color is done in SRGB space, linear gives odd crossfades */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + IMB_convert_profile(ibuf, IB_PROFILE_NONE); - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + copy_to_ibuf_still(seq, nr, ibuf); + } + } else if(seq->type == SEQ_MOVIE) { + if(ibuf == 0) { + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); - if (!se1 || !se2) { - make_black_ibuf(se->ibuf); - } else { - sh = get_sequence_effect(seq); + } + + if (ibuf == 0) { + ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty); + } + + if (ibuf == 0) { + if(seq->anim==0) { + BLI_join_dirfile(name, + seq->strip->dir, + seq->strip->stripdata->name); + BLI_path_abs(name, G.sce); + + seq->anim = openanim( + name, IB_rect | + ((seq->flag & SEQ_FILTERY) + ? IB_animdeinterlace : 0)); + } + if(seq->anim) { + IMB_anim_set_preseek(seq->anim, + seq->anim_preseek); + ibuf = IMB_anim_absolute(seq->anim, + nr + + seq->anim_startofs); + /* we don't need both (speed reasons)! */ + if (ibuf && ibuf->rect_float + && ibuf->rect) { + imb_freerectImBuf(ibuf); + } - sh.execute(scene, seq, cfra, - f_cfra - (float) cfra_left, - f_cfra - (float) cfra_left, - se->ibuf->x, se->ibuf->y, - se1->ibuf, se2->ibuf, 0, se->ibuf); } + copy_to_ibuf_still(seq, nr, ibuf); } + + } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions + if (ibuf == 0) { + ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + if (ibuf == 0) { + ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty); + } + + if (ibuf == 0) { + ibuf = seq_render_scene_strip_impl(bmain, scene, seq, nr, + seqrectx, seqrecty); + copy_to_ibuf_still(seq, nr, 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); + if (!ibuf) { + ibuf = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, 32, IB_rect, 0); } - /* 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); - - check_limiter_refcount("do_handle_speed_effect", se); - - return se; -} - -/* - * 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 - * - */ + if (ibuf->x != seqrectx || ibuf->y != seqrecty) { + use_preprocess = TRUE; + } -static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size) -{ - TStripElem *se; - if (seq->type == SEQ_SPEED) { - se = do_handle_speed_effect(scene, seq, cfra, render_size); - } else { - se = do_build_seq_recursively_impl(scene, seq, cfra, render_size); + if (use_preprocess) { + ibuf = input_preprocess(scene, seq, cfra, seqrectx, + seqrecty, ibuf); } - check_limiter_refcount("do_build_seq_recursively", se); + seq_stripelem_cache_put( + seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf); - return se; + return ibuf; } +/* ********************************************************************** + strip stack rendering functions + ********************************************************************** */ + static int seq_must_swap_input_in_blend_mode(Sequence * seq) { int swap_input = FALSE; @@ -2482,45 +2128,48 @@ static int seq_get_early_out_for_blend_mode(Sequence * seq) return early_out; } -static TStripElem* do_build_seq_array_recursively(Scene *scene, - ListBase *seqbasep, int cfra, int chanshown, int render_size) +static ImBuf* seq_render_strip_stack( + Main *bmain, Scene *scene, ListBase *seqbasep, float cfra, int chanshown, + int render_size, int seqrectx, int seqrecty) { Sequence* seq_arr[MAXSEQ+1]; int count; int i; - TStripElem* se = 0; + ImBuf* out = 0; count = get_shown_sequences(seqbasep, cfra, chanshown, - (Sequence **)&seq_arr); + (Sequence **)&seq_arr); if (!count) { return 0; } - se = give_tstripelem(seq_arr[count - 1], cfra); - - if (!se) { - return 0; +#if 0 /* commentind since this breaks keyframing, since it resets the value on draw */ + if(scene->r.cfra != cfra) { + // XXX for prefetch and overlay offset!..., very bad!!! + AnimData *adt= BKE_animdata_from_id(&scene->id); + BKE_animsys_evaluate_animdata(&scene->id, adt, cfra, ADT_RECALC_ANIM); } +#endif - test_and_auto_discard_ibuf(se); + out = seq_stripelem_cache_get( + seq_arr[count - 1], + seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP); - if (se->ibuf_comp != 0) { - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - return se; + if (out) { + return out; } - if(count == 1) { - se = do_build_seq_recursively(scene, seq_arr[0], - cfra, render_size); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } - return se; + out = seq_render_strip(bmain, scene, seq_arr[0], + cfra, render_size, + seqrectx, seqrecty); + seq_stripelem_cache_put( + seq_arr[0], + seqrectx, seqrecty, cfra, + SEQ_STRIPELEM_IBUF_COMP, out); + + return out; } @@ -2528,28 +2177,17 @@ static TStripElem* do_build_seq_array_recursively(Scene *scene, int early_out; Sequence * seq = seq_arr[i]; - se = give_tstripelem(seq, cfra); - - test_and_auto_discard_ibuf(se); + out = seq_stripelem_cache_get( + seq, + seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP); - if (se->ibuf_comp != 0) { + if (out) { break; } if (seq->blend_mode == SEQ_BLEND_REPLACE) { - do_build_seq_recursively( - scene, seq, cfra, render_size); - - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } + out = seq_render_strip(bmain, scene, seq, cfra, + render_size, + seqrectx, seqrecty); break; } @@ -2558,152 +2196,87 @@ static TStripElem* do_build_seq_array_recursively(Scene *scene, switch (early_out) { case -1: case 2: - do_build_seq_recursively( - scene, seq, cfra, render_size); - - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } + out = seq_render_strip(bmain, scene, seq, cfra, + render_size, + seqrectx, seqrecty); break; case 1: if (i == 0) { - se->ibuf_comp = IMB_allocImBuf( + out = IMB_allocImBuf( (short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); } break; case 0: - do_build_seq_recursively( - scene, seq, cfra, render_size); - - if (!se->ibuf) { - se->ibuf = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); - } if (i == 0) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); + out = seq_render_strip(bmain, scene, seq, cfra, + render_size, + seqrectx, seqrecty); } + break; } - - if (se->ibuf_comp) { + if (out) { break; } } + seq_stripelem_cache_put( + seq_arr[i], seqrectx, seqrecty, cfra, + SEQ_STRIPELEM_IBUF_COMP, out); + + i++; for (; i < count; i++) { Sequence * seq = seq_arr[i]; - struct SeqEffectHandle sh = get_sequence_blend(seq); - TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra); - TStripElem* se2 = give_tstripelem(seq_arr[i], cfra); - - float facf = seq->blend_opacity / 100.0; - int swap_input = seq_must_swap_input_in_blend_mode(seq); - int early_out = seq_get_early_out_for_blend_mode(seq); - switch (early_out) { - case 0: { - int x= se2->ibuf->x; - int y= se2->ibuf->y; + if (seq_get_early_out_for_blend_mode(seq) == 0) { + struct SeqEffectHandle sh = get_sequence_blend(seq); + ImBuf * ibuf1 = out; + ImBuf * ibuf2 = seq_render_strip(bmain, scene, seq, cfra, + render_size, + seqrectx, seqrecty); - if(se1->ibuf_comp == NULL) - continue; + float facf = seq->blend_opacity / 100.0; + int swap_input + = seq_must_swap_input_in_blend_mode(seq); - 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); - } + int x= seqrectx; + int y= seqrecty; - - if (!se1->ibuf_comp->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se1->ibuf_comp); - } - if (!se2->ibuf->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se2->ibuf); - } - - if (!se1->ibuf_comp->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se1->ibuf_comp); - } - if (!se2->ibuf->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se2->ibuf); - } - if (swap_input) { - sh.execute(scene, seq, cfra, - facf, facf, x, y, - se2->ibuf, se1->ibuf_comp, 0, - se2->ibuf_comp); + out = sh.execute(bmain, scene, seq, cfra, + facf, facf, x, y, render_size, + ibuf2, ibuf1, 0); } else { - sh.execute(scene, seq, cfra, - facf, facf, x, y, - se1->ibuf_comp, se2->ibuf, 0, - se2->ibuf_comp); + out = sh.execute(bmain, scene, seq, cfra, + facf, facf, x, y, render_size, + ibuf1, ibuf2, 0); } - - IMB_cache_limiter_insert(se2->ibuf_comp); - IMB_cache_limiter_ref(se2->ibuf_comp); - IMB_cache_limiter_touch(se2->ibuf_comp); - - IMB_cache_limiter_unref(se1->ibuf_comp); - IMB_cache_limiter_unref(se2->ibuf); - - break; + + IMB_freeImBuf(ibuf1); + IMB_freeImBuf(ibuf2); } - case 1: { - se2->ibuf_comp = se1->ibuf_comp; - if(se2->ibuf_comp) - IMB_refImBuf(se2->ibuf_comp); - break; - } - } - se = se2; + seq_stripelem_cache_put( + seq_arr[i], seqrectx, seqrecty, cfra, + SEQ_STRIPELEM_IBUF_COMP, out); } - return se; + return out; } /* * returned ImBuf is refed! - * you have to unref after usage! + * you have to free after usage! */ -static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +ImBuf *give_ibuf_seq(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) { Editing *ed= seq_give_editing(scene, FALSE); int count; ListBase *seqbasep; - TStripElem *se; - if(ed==NULL) return NULL; @@ -2715,50 +2288,19 @@ static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, i seqbasep= ed->seqbasep; } - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size); - - if(!se) { - return 0; - } - - check_limiter_refcount_comp("give_ibuf_seq_impl", se); - - return se->ibuf_comp; + return seq_render_strip_stack( + bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty); } -ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) +ImBuf *give_ibuf_seqbase(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep) { - TStripElem* se; - - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_recursively(scene, seq, cfra, render_size); - - if(!se) { - return 0; - } - - check_limiter_refcount("give_ibuf_seq_direct", se); - - if (se->ibuf) { - IMB_cache_limiter_unref(se->ibuf); - } - - return se->ibuf; + return seq_render_strip_stack(bmain, scene, seqbasep, cfra, chanshown, render_size, rectx, recty); } -ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) -{ - ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size); - if (i) { - IMB_cache_limiter_unref(i); - } - return i; +ImBuf *give_ibuf_seq_direct(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) +{ + return seq_render_strip(bmain, scene, seq, cfra, render_size, rectx, recty); } #if 0 @@ -2789,7 +2331,7 @@ static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER; -static volatile int seq_thread_shutdown = FALSE; +static volatile int seq_thread_shutdown = TRUE; static volatile int seq_last_given_monoton_cfra = 0; static int monoton_cfra = 0; @@ -3024,13 +2566,13 @@ static void seq_wait_for_prefetch_ready() } #endif -ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +ImBuf *give_ibuf_seq_threaded(Main *bmain, Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) { PrefetchQueueElem *e = NULL; int found_something = FALSE; if (seq_thread_shutdown) { - return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size); + return give_ibuf_seq(bmain, scene, rectx, recty, cfra, chanshown, render_size); } while (!e) { @@ -3107,20 +2649,6 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int /* Functions to free imbuf and anim data on changes */ -static void free_imbuf_strip_elem(TStripElem *se) -{ - if(se->ibuf) { - IMB_freeImBuf(se->ibuf); - } - if(se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - } - se->ibuf_comp = 0; - se->ibuf= 0; - se->ok= STRIPELEM_OK; - se->se1= se->se2= se->se3= 0; -} - static void free_anim_seq(Sequence *seq) { if(seq->anim) { @@ -3129,63 +2657,10 @@ static void free_anim_seq(Sequence *seq) } } -#if 0 -static void free_imbuf_seq_except(Scene *scene, int cfra) -{ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq; - TStripElem *se; - int a; - - if(ed==NULL) return; - - SEQ_BEGIN(ed, seq) { - if(seq->strip) { - TStripElem * curelem = give_tstripelem(seq, cfra); - - for(a = 0, se = seq->strip->tstripdata; - a < seq->strip->len && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - for(a = 0, se = seq->strip->tstripdata_startstill; - a < seq->strip->startstill && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - for(a = 0, se = seq->strip->tstripdata_endstill; - a < seq->strip->endstill && se; a++, se++) { - if(se != curelem) { - free_imbuf_strip_elem(se); - } - } - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - - if(seq->type==SEQ_MOVIE) - if(seq->startdisp > cfra || seq->enddisp < cfra) - free_anim_seq(seq); - free_proxy_seq(seq); - } - } - SEQ_END -} -#endif - -void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage) +void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage, + int keep_file_handles) { Sequence *seq; - TStripElem *se; - int a; if (check_mem_usage) { /* Let the cache limitor take care of this (schlaile) */ @@ -3211,39 +2686,19 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage) } } + seq_stripelem_cache_cleanup(); for(seq= seqbase->first; seq; seq= seq->next) { if(seq->strip) { - for(a = 0, se = seq->strip->tstripdata; - a < seq->strip->len && se; a++, se++) { - free_imbuf_strip_elem(se); - } - for(a = 0, se = seq->strip->tstripdata_startstill; - a < seq->strip->startstill && se; a++, se++) { - free_imbuf_strip_elem(se); - } - for(a = 0, se = seq->strip->tstripdata_endstill; - a < seq->strip->endstill && se; a++, se++) { - free_imbuf_strip_elem(se); - } - if(seq->strip->ibuf_startstill) { - IMB_freeImBuf(seq->strip->ibuf_startstill); - seq->strip->ibuf_startstill = 0; - } - - if(seq->strip->ibuf_endstill) { - IMB_freeImBuf(seq->strip->ibuf_endstill); - seq->strip->ibuf_endstill = 0; - } - - if(seq->type==SEQ_MOVIE) + if(seq->type==SEQ_MOVIE && !keep_file_handles) free_anim_seq(seq); if(seq->type==SEQ_SPEED) { sequence_effect_speed_rebuild_map(scene, seq, 1); } } if(seq->type==SEQ_META) { - free_imbuf_seq(scene, &seq->seqbase, FALSE); + free_imbuf_seq(scene, &seq->seqbase, FALSE, + keep_file_handles); } if(seq->type==SEQ_SCENE) { /* FIXME: recurs downwards, @@ -3256,8 +2711,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage) static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) { Sequence *subseq; - int a, free_imbuf = 0; - TStripElem *se; + int free_imbuf = 0; /* recurs downwards to see if this seq depends on the changed seq */ @@ -3283,12 +2737,6 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan if(free_imbuf) { if(ibuf_change) { - se= seq->strip->tstripdata; - if (se) { - for(a=0; a<seq->len; a++, se++) - free_imbuf_strip_elem(se); - } - if(seq->type == SEQ_MOVIE) free_anim_seq(seq); if(seq->type == SEQ_SPEED) { @@ -3314,39 +2762,6 @@ void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_ch update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change); } -#if 0 // XXX from 2.4x, needs updating -void free_imbuf_seq() -{ - Scene * sce = G.main->scene.first; - while(sce) { - free_imbuf_seq_editing(sce->ed); - sce= sce->id.next; - } -} -#endif - -#if 0 // XXX old animation system -static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) -{ - /* force update of all sequences with this ipo, on ipo changes */ - Editing *ed= seq_give_editing(scene, FALSE); - Sequence *seq; - - if(ed==NULL) return; - - SEQ_BEGIN(ed, seq) { - if(seq->ipo == ipo) { - update_changed_seq_and_deps(scene, seq, 0, 1); - if(seq->type == SEQ_SPEED) { - sequence_effect_speed_rebuild_map(seq, 1); - } - free_proxy_seq(seq); - } - } - SEQ_END -} -#endif - /* seq funcs's for transforming internally notice the difference between start/end and left/right. @@ -3407,7 +2822,8 @@ void seq_tx_set_final_right(Sequence *seq, int val) since they work a bit differently to normal image seq's (during transform) */ int seq_single_check(Sequence *seq) { - if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR)) + if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR + || seq->type == SEQ_MULTICAM)) return 1; else return 0; @@ -3730,6 +3146,57 @@ ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq) return NULL; } +int seq_swap(Sequence *seq_a, Sequence *seq_b) +{ + char name[sizeof(seq_a->name)]; + + if(seq_a->len != seq_b->len) + return 0; + + /* type checking, could be more advanced but disalow sound vs non-sound copy */ + if(seq_a->type != seq_b->type) { + if(seq_a->type == SEQ_SOUND || seq_b->type == SEQ_SOUND) { + return 0; + } + + /* disallow effects to swap with non-effects strips */ + if((seq_a->type & SEQ_EFFECT) != (seq_b->type & SEQ_EFFECT)) { + return 0; + } + + if((seq_a->type & SEQ_EFFECT) && (seq_b->type & SEQ_EFFECT)) { + if(get_sequence_effect_num_inputs(seq_a->type) != get_sequence_effect_num_inputs(seq_b->type)) { + return 0; + } + } + } + + SWAP(Sequence, *seq_a, *seq_b); + + /* swap back names so animation fcurves dont get swapped */ + strcpy(name, seq_a->name+2); + strcpy(seq_a->name+2, seq_b->name+2); + strcpy(seq_b->name+2, name); + + /* swap back opacity, and overlay mode */ + SWAP(int, seq_a->blend_mode, seq_b->blend_mode); + SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity); + + + SWAP(void *, seq_a->prev, seq_b->prev); + SWAP(void *, seq_a->next, seq_b->next); + SWAP(int, seq_a->start, seq_b->start); + SWAP(int, seq_a->startofs, seq_b->startofs); + SWAP(int, seq_a->endofs, seq_b->endofs); + SWAP(int, seq_a->startstill, seq_b->startstill); + SWAP(int, seq_a->endstill, seq_b->endstill); + SWAP(int, seq_a->machine, seq_b->machine); + SWAP(int, seq_a->startdisp, seq_b->startdisp); + SWAP(int, seq_a->enddisp, seq_b->enddisp); + + return 1; +} + /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) { @@ -3754,6 +3221,62 @@ void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs) } } +void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to) +{ + char str_from[32]; + FCurve *fcu; + FCurve *fcu_last; + FCurve *fcu_cpy; + ListBase lb= {NULL, NULL}; + + if(scene->adt==NULL || scene->adt->action==NULL) + return; + + sprintf(str_from, "[\"%s\"]", name_from); + + fcu_last= scene->adt->action->curves.last; + + for (fcu= scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu= fcu->next) { + if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str_from)) { + fcu_cpy= copy_fcurve(fcu); + BLI_addtail(&lb, fcu_cpy); + } + } + + /* notice validate is 0, keep this because the seq may not be added to the scene yet */ + BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0); + + /* add the original fcurves back */ + addlisttolist(&scene->adt->action->curves, &lb); +} + +/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */ +static void seq_free_animdata(Scene *scene, Sequence *seq) +{ + char str[32]; + FCurve *fcu; + + if(scene->adt==NULL || scene->adt->action==NULL) + return; + + sprintf(str, "[\"%s\"]", seq->name+2); + + fcu= scene->adt->action->curves.first; + + while (fcu) { + if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) { + FCurve *next_fcu = fcu->next; + + BLI_remlink(&scene->adt->action->curves, fcu); + free_fcurve(fcu); + + fcu = next_fcu; + } else { + fcu = fcu->next; + } + } +} + Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive) { @@ -3772,14 +3295,14 @@ Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive) } -Sequence *active_seq_get(Scene *scene) +Sequence *seq_active_get(Scene *scene) { Editing *ed= seq_give_editing(scene, FALSE); if(ed==NULL) return NULL; return ed->act_seq; } -void active_seq_set(Scene *scene, Sequence *seq) +void seq_active_set(Scene *scene, Sequence *seq) { Editing *ed= seq_give_editing(scene, FALSE); if(ed==NULL) return; @@ -3787,12 +3310,41 @@ void active_seq_set(Scene *scene, Sequence *seq) ed->act_seq= seq; } +int seq_active_pair_get(Scene *scene, Sequence **seq_act, Sequence **seq_other) +{ + Editing *ed= seq_give_editing(scene, FALSE); + + *seq_act= seq_active_get(scene); + + if(*seq_act == NULL) { + return 0; + } + else { + Sequence *seq; + + *seq_other= NULL; + + for(seq= ed->seqbasep->first; seq; seq= seq->next) { + if(seq->flag & SELECT && (seq != (*seq_act))) { + if(*seq_other) { + return 0; + } + else { + *seq_other= seq; + } + } + } + + return (*seq_other != NULL); + } +} + /* api like funcs for adding */ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) { if(seq) { - strcpy(seq->name, seq_load->name); + BLI_strncpy(seq->name+2, seq_load->name, sizeof(seq->name)-2); seqbase_unique_name_recursive(&scene->ed->seqbase, seq); if(seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { @@ -3801,7 +3353,7 @@ void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) { seq_load->flag |= SELECT; - active_seq_set(scene, seq); + seq_active_set(scene, seq); } if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) { @@ -3829,6 +3381,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) seq->flag= SELECT; seq->start= cfra; seq->machine= machine; + seq->sat= 1.0; seq->mul= 1.0; seq->blend_opacity = 100.0; seq->volume = 1.0f; @@ -3846,8 +3399,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); seq->type= SEQ_IMAGE; - BLI_strncpy(seq->name+2, "Image", SEQ_NAME_MAXSTR-2); - seqbase_unique_name_recursive(&scene->ed->seqbase, seq); + seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */ /* basic defaults */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); @@ -3855,8 +3407,8 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo strip->len = seq->len = seq_load->len ? seq_load->len : 1; strip->us= 1; strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - BLI_split_dirfile(seq_load->path, strip->dir, se->name); - + BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir)); + seq_load_apply(scene, seq, seq_load); return seq; @@ -3874,7 +3426,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo AUD_SoundInfo info; - sound = sound_new_file(CTX_data_main(C), seq_load->path); + sound = sound_new_file(CTX_data_main(C), seq_load->path); /* handles relative paths */ if (sound==NULL || sound->playback_handle == NULL) { //if(op) @@ -3922,6 +3474,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { Scene *scene= CTX_data_scene(C); /* only for sound */ + char path[sizeof(seq_load->path)]; Sequence *seq, *soundseq; /* generic strip vars */ Strip *strip; @@ -3929,14 +3482,18 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo struct anim *an; - an = openanim(seq_load->path, IB_rect); + BLI_strncpy(path, seq_load->path, sizeof(path)); + BLI_path_abs(path, G.sce); + + an = openanim(path, IB_rect); if(an==NULL) return NULL; seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - seq->type= SEQ_MOVIE; + seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */ + seq->anim= an; seq->anim_preseek = IMB_anim_get_preseek(an); BLI_strncpy(seq->name+2, "Movie", SEQ_NAME_MAXSTR-2); @@ -3964,8 +3521,136 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo seq_load->channel--; } + if(seq_load->name[0] == '\0') + BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name)); + /* can be NULL */ seq_load_apply(scene, seq, seq_load); return seq; } + + +static Sequence *seq_dupli(struct Scene *scene, Sequence *seq, int dupe_flag) +{ + Sequence *seqn = MEM_dupallocN(seq); + + seq->tmp = seqn; + seqn->strip= MEM_dupallocN(seq->strip); + + // XXX: add F-Curve duplication stuff? + + if (seq->strip->crop) { + seqn->strip->crop = MEM_dupallocN(seq->strip->crop); + } + + if (seq->strip->transform) { + seqn->strip->transform = MEM_dupallocN(seq->strip->transform); + } + + if (seq->strip->proxy) { + seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy); + } + + if (seq->strip->color_balance) { + seqn->strip->color_balance + = MEM_dupallocN(seq->strip->color_balance); + } + + if(seq->type==SEQ_META) { + seqn->strip->stripdata = 0; + + seqn->seqbase.first= seqn->seqbase.last= 0; + /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */ + /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/ + } else if(seq->type == SEQ_SCENE) { + seqn->strip->stripdata = 0; + if(seq->scene_sound) + seqn->scene_sound = sound_scene_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + } else if(seq->type == SEQ_MOVIE) { + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->anim= 0; + } else if(seq->type == SEQ_SOUND) { + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + if(seq->scene_sound) + seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); + + seqn->sound->id.us++; + } else if(seq->type == SEQ_IMAGE) { + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + } else if(seq->type >= SEQ_EFFECT) { + if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp; + if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp; + if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp; + + if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh; + sh = get_sequence_effect(seq); + if(sh.copy) + sh.copy(seq, seqn); + } + + seqn->strip->stripdata = 0; + + } else { + fprintf(stderr, "Aiiiiekkk! sequence type not " + "handled in duplicate!\nExpect a crash" + " now...\n"); + } + + if(dupe_flag & SEQ_DUPE_UNIQUE_NAME) + seqbase_unique_name_recursive(&scene->ed->seqbase, seqn); + + if(dupe_flag & SEQ_DUPE_ANIM) + seq_dupe_animdata(scene, seq->name+2, seqn->name+2); + + return seqn; +} + +Sequence * seq_dupli_recursive(struct Scene *scene, Sequence * seq, int dupe_flag) +{ + Sequence * seqn = seq_dupli(scene, seq, dupe_flag); + if (seq->type == SEQ_META) { + Sequence *s; + for(s= seq->seqbase.first; s; s = s->next) { + Sequence *n = seq_dupli_recursive(scene, s, dupe_flag); + if (n) { + BLI_addtail(&seqn->seqbase, n); + } + } + } + return seqn; +} + +void seqbase_dupli_recursive(Scene *scene, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) +{ + Sequence *seq; + Sequence *seqn = 0; + Sequence *last_seq = seq_active_get(scene); + + for(seq= seqbase->first; seq; seq= seq->next) { + seq->tmp= NULL; + if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) { + seqn = seq_dupli(scene, seq, dupe_flag); + if (seqn) { /*should never fail */ + if(dupe_flag & SEQ_DUPE_CONTEXT) { + seq->flag &= ~SEQ_ALLSEL; + seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK); + } + + BLI_addtail(nseqbase, seqn); + if(seq->type==SEQ_META) + seqbase_dupli_recursive(scene, &seqn->seqbase, &seq->seqbase, dupe_flag); + + if(dupe_flag & SEQ_DUPE_CONTEXT) { + if (seq == last_seq) { + seq_active_set(scene, seqn); + } + } + } + } + } +} |