diff options
author | Peter Schlaile <peter@schlaile.de> | 2006-02-05 22:30:37 +0300 |
---|---|---|
committer | Peter Schlaile <peter@schlaile.de> | 2006-02-05 22:30:37 +0300 |
commit | 90f0e372637178de107dbe161f1e24561ef9513d (patch) | |
tree | f7721f0c52eaef89e306f53514a35500d576015e /source/blender/src/sequence.c | |
parent | f17bdcb2e4da09caaeb53b0ca7d8e881d79f901e (diff) |
* Adds configuration buttons for ffmpeg-output
* Large sequencer rewrite to support:
- Audio-tracks, which are not completely loaded into memory (hdaudio) but
kept on disk instead.
- A dependency tree, that builds only the Imbufs, that are really needed
- Cleaner sequencer code
- Per instance data in sequencer plugins (without this, the Dynamic
Noise Reduction plugin would be impossible)
- A Luma Waveform display
- A U/V scatter plot display
- Memcache limiting in sequencer
- Buttons changed according to the boosted framecount limit
Diffstat (limited to 'source/blender/src/sequence.c')
-rw-r--r-- | source/blender/src/sequence.c | 1028 |
1 files changed, 743 insertions, 285 deletions
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 65446317a3f..4e3480f8fc6 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -23,9 +23,7 @@ * 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): none yet. + * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005/2006 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -63,6 +61,7 @@ #include "BIF_screen.h" #include "BIF_space.h" #include "BIF_toolbox.h" +#include "BIF_editsound.h" #include "BSE_sequence.h" @@ -70,7 +69,8 @@ #include "blendef.h" -Sequence *seq_arr[MAXSEQ+1]; +static void do_build_seq_depend(Sequence * seq, int cfra); + int seqrectx, seqrecty; /* support for plugin sequences: */ @@ -78,6 +78,7 @@ int seqrectx, seqrecty; void open_plugin_seq(PluginSeq *pis, char *seqname) { int (*version)(); + void* (*alloc_private)(); char *cp; /* to be sure: (is tested for) */ @@ -86,6 +87,7 @@ void open_plugin_seq(PluginSeq *pis, char *seqname) pis->varstr= 0; pis->cfra= 0; pis->version= 0; + pis->instance_private_data = 0; /* clear the error list */ PIL_dynlib_get_error_as_string(NULL); @@ -133,6 +135,15 @@ void open_plugin_seq(PluginSeq *pis, char *seqname) return; } } + alloc_private = (void* (*)())PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_alloc_private_data"); + if (alloc_private) { + pis->instance_private_data = alloc_private(); + } + + pis->current_private_data = (void**) + PIL_dynlib_find_symbol( + pis->handle, "plugin_private_data"); } } @@ -168,10 +179,20 @@ PluginSeq *add_plugin_seq(char *str, char *seqname) void free_plugin_seq(PluginSeq *pis) { - if(pis==0) return; /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ + + if (pis->instance_private_data) { + void (*free_private)(void *); + + free_private = (void (*)(void *))PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_free_private_data"); + if (free_private) { + free_private(pis->instance_private_data); + } + } + MEM_freeN(pis); } @@ -185,7 +206,10 @@ void free_stripdata(int len, StripElem *se) seo= se; for(a=0; a<len; a++, se++) { - if(se->ibuf && se->ok!=2) IMB_freeImBuf(se->ibuf); + if(se->ibuf && se->ok!=2) { + IMB_freeImBuf(se->ibuf); + se->ibuf = 0; + } } MEM_freeN(seo); @@ -226,6 +250,7 @@ void free_sequence(Sequence *seq) if(seq->effectdata) MEM_freeN(seq->effectdata); if(seq->anim) IMB_free_anim(seq->anim); + if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); free_plugin_seq(seq->plugin); @@ -1619,14 +1644,11 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) if(se->se3->ok==2) se3= se->se3->se1; else se3= se->se3; - if(se1==0 || se2==0 || se3==0 || se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) { + if(se1==0 || se2==0 || se3==0) { make_black_ibuf(se->ibuf); return; } - x= se2->ibuf->x; - y= se2->ibuf->y; - if(seq->ipo && seq->ipo->curve.first) { do_seq_ipo(seq); fac= seq->facf0; @@ -1644,6 +1666,43 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) if( G.scene->r.mode & R_FIELDS ); else facf= fac; + /* FIXME: This should be made available to external plugins too... */ + if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS || + seq->type == SEQ_WIPE) { + if (fac == 0.0 && facf == 0.0) { + if (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; + } else if (fac == 1.0 && facf == 1.0) { + if (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; + } + } + + + if (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) { + make_black_ibuf(se->ibuf); + return; + } + + x= se2->ibuf->x; + y= se2->ibuf->y; + switch(seq->type) { case SEQ_CROSS: do_cross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); @@ -1681,19 +1740,28 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) if((G.f & G_PLAYANIM)==0) waitcursor(1); - if(seq->plugin->cfra) *(seq->plugin->cfra)= frame_to_float(CFRA); + if(seq->plugin->cfra) + *(seq->plugin->cfra)= frame_to_float(CFRA); + + cp = PIL_dynlib_find_symbol( + seq->plugin->handle, "seqname"); - cp= PIL_dynlib_find_symbol(seq->plugin->handle, "seqname"); if(cp) strncpy(cp, seq->name+2, 22); + if (seq->plugin->current_private_data) { + *seq->plugin->current_private_data + = seq->plugin->instance_private_data; + } + if (seq->plugin->version<=2) { if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf); if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf); if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf); } - ((SeqDoit)seq->plugin->doit)(seq->plugin->data, fac, facf, x, y, - se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf); + ((SeqDoit)seq->plugin->doit)( + seq->plugin->data, fac, facf, x, y, + se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf); if (seq->plugin->version<=2) { if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf); @@ -1709,29 +1777,6 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) } -int evaluate_seq_frame(int cfra) -{ - Sequence *seq; - Editing *ed; - int totseq=0; - - memset(seq_arr, 0, 4*MAXSEQ); - - 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; - } - - return totseq; -} - StripElem *give_stripelem(Sequence *seq, int cfra) { Strip *strip; @@ -1765,63 +1810,114 @@ StripElem *give_stripelem(Sequence *seq, int cfra) return se; } - -void set_meta_stripdata(Sequence *seqm) +static int evaluate_seq_frame_gen( + Sequence ** seq_arr, ListBase *seqbase, int cfra) { - Sequence *seq, *seqim, *seqeff; - Editing *ed; - ListBase *tempbase; - StripElem *se; - int a, cfra, b; + Sequence *seq; + int totseq=0; - /* sets all ->se1 pointers in stripdata, to read the ibuf from it */ + memset(seq_arr, 0, sizeof(Sequence*) * MAXSEQ); - ed= G.scene->ed; - if(ed==0) return; + seq= seqbase->first; + while(seq) { + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + seq_arr[seq->machine]= seq; + totseq++; + } + seq= seq->next; + } - tempbase= ed->seqbasep; - ed->seqbasep= &seqm->seqbase; + return totseq; +} - se= seqm->strip->stripdata; - for(a=0; a<seqm->len; a++, se++) { - cfra= a+seqm->start; - if(evaluate_seq_frame(cfra)) { +int evaluate_seq_frame(int cfra) +{ + Editing *ed; + Sequence *seq_arr[MAXSEQ+1]; - /* we take the upper effect strip or the lowest imagestrip/metastrip */ - seqim= seqeff= 0; + ed= G.scene->ed; + if(ed==0) return 0; + + return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra); - 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; - } +} + +static Sequence * get_shown_seq_from_metastrip(Sequence * seqm, int cfra) +{ + Sequence *seq, *seqim, *seqeff; + Sequence *seq_arr[MAXSEQ+1]; + int b; + + seq = 0; + + if(evaluate_seq_frame_gen(seq_arr, &seqm->seqbase, cfra)) { + + /* we take the upper effect strip or + the lowest imagestrip/metastrip */ + seqim= seqeff= 0; + + 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; + } + if(seqeff) seq= seqeff; + else if(seqim) seq= seqim; + else seq= 0; + } + + return seq; +} + +void set_meta_stripdata(Sequence *seqm) +{ + Sequence *seq; + StripElem *se; + int a, cfra; - if(seq) { - se->se1= give_stripelem(seq, cfra); - } - else se->se1= 0; + /* sets all ->se1 pointers in stripdata, to read the ibuf from it */ + + se= seqm->strip->stripdata; + for(a=0; a<seqm->len; a++, se++) { + cfra= a+seqm->start; + seq = get_shown_seq_from_metastrip(seqm, cfra); + if (seq) { + se->se1= give_stripelem(seq, cfra); + } else { + se->se1= 0; } } - ed->seqbasep= tempbase; } /* HELP FUNCTIONS FOR GIVE_IBUF_SEQ */ -void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra) +static void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + (*totseq)++; + } + seq= seq->next; + } +} + +static void do_seq_unref_cfra(ListBase *seqbase, int cfra) { Sequence *seq; @@ -1831,260 +1927,431 @@ void do_seq_count_cfra(ListBase *seqbase, int *totseq, int cfra) if(seq->seqbase.first) { - 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(cfra< seq->start) do_seq_unref_cfra(&seq->seqbase, seq->start); + else if(cfra> seq->start+seq->len-1) do_seq_unref_cfra(&seq->seqbase, seq->start+seq->len-1); + else do_seq_unref_cfra(&seq->seqbase, cfra); } - (*totseq)++; + if (seq->curelem && seq->curelem->ibuf + && seq->curelem->isneeded) { + IMB_cache_limiter_unref(seq->curelem->ibuf); + } } seq= seq->next; } } -void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra) +static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra) { Sequence *seq; - StripElem *se; - char name[FILE_MAXDIR+FILE_MAXFILE]; - if(seqar==NULL) return; - seq= seqbase->first; while(seq) { + if(seq->startdisp <=cfra && seq->enddisp > cfra) { - /* set at zero because free_imbuf_seq... */ - seq->curelem= 0; + if(seq->seqbase.first) { - if ((seq->type == SEQ_SOUND) && (seq->ipo) - &&(seq->startdisp<=cfra+2) && (seq->enddisp>cfra)) do_seq_ipo(seq); + if(cfra< seq->start) do_seq_test_unref_cfra(&seq->seqbase, seq->start); + else if(cfra> seq->start+seq->len-1) do_seq_test_unref_cfra(&seq->seqbase, seq->start+seq->len-1); + else do_seq_test_unref_cfra(&seq->seqbase, cfra); + } - if(seq->startdisp <=cfra && seq->enddisp > cfra) { + if (seq->curelem && seq->curelem->ibuf + && seq->curelem->isneeded) { + if (IMB_cache_limiter_get_refcount(seq->curelem->ibuf)) { + fprintf(stderr, "refcount Arggh: %p, %d\n", + seq, seq->type); + } + } + } + seq= seq->next; + } +} - 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); +static void do_effect_depend(int cfra, Sequence * seq, StripElem *se) +{ + float fac, facf; + + 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; + } + + if( G.scene->r.mode & R_FIELDS ); else facf= fac; + + /* FIXME: This should be made available to external plugins too... */ + if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS || + seq->type == SEQ_WIPE) { + if (fac == 0.0 && facf == 0.0) { + do_build_seq_depend(seq->seq1, cfra); + } else if (fac == 1.0 && facf == 1.0) { + do_build_seq_depend(seq->seq2, cfra); + } else { + do_build_seq_depend(seq->seq1, cfra); + do_build_seq_depend(seq->seq2, cfra); + } + } else { + do_build_seq_depend(seq->seq1, cfra); + do_build_seq_depend(seq->seq2, cfra); + } + do_build_seq_depend(seq->seq3, cfra); +} + +static void do_build_seq_depend(Sequence * seq, int cfra) +{ + StripElem *se; + + se=seq->curelem= give_stripelem(seq, cfra); + + if(se && !se->isneeded) { + se->isneeded = 1; + if(seq->seqbase.first) { + Sequence * seqmshown + = get_shown_seq_from_metastrip(seq, cfra); + if (seqmshown) { + if(cfra< seq->start) + do_build_seq_depend( + seqmshown, seq->start); + else if(cfra> seq->start+seq->len-1) + do_build_seq_depend( + seqmshown, seq->start + + seq->len-1); + else do_build_seq_depend(seqmshown, cfra); } + } - **seqar= seq; - (*seqar)++; + if (seq->type & SEQ_EFFECT) { + do_effect_depend(cfra, seq, se); + } + } +} + +static void do_build_seq_ibuf(Sequence * seq, int cfra) +{ + StripElem *se; + char name[FILE_MAXDIR+FILE_MAXFILE]; - se=seq->curelem= give_stripelem(seq, cfra); + se=seq->curelem= give_stripelem(seq, cfra); - 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; + if(se && se->isneeded) { + if(seq->type == SEQ_META) { + se->ok= 2; + if(se->se1==0) set_meta_stripdata(seq); + if(se->se1) { + se->ibuf= se->se1->ibuf; + } + } + else if(seq->type == SEQ_RAM_SOUND + || seq->type == SEQ_HD_SOUND) { + se->ok= 2; + } + else if(seq->type & SEQ_EFFECT) { + + /* test if image is too small or discarded from cache: reload */ + if(se->ibuf) { + if(se->ibuf->x < seqrectx + || se->ibuf->y < seqrecty + || !se->ibuf->rect) { + IMB_freeImBuf(se->ibuf); + se->ibuf= 0; + } + } + + /* does the effect should be recalculated? */ + + 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; + + if(se->ibuf==0) { + se->ibuf= IMB_allocImBuf( + (short)seqrectx, + (short)seqrecty, + 32, IB_rect, 0); + } + do_effect(cfra, seq, se); + } + + /* test size */ + if(se->ibuf) { + if(se->ibuf->x != seqrectx + || se->ibuf->y != seqrecty ) { + if(G.scene->r.mode & R_OSA) { + IMB_scaleImBuf( + se->ibuf, + (short)seqrectx, + (short)seqrecty); + } else { + IMB_scalefastImBuf( + se->ibuf, + (short)seqrectx, + (short)seqrecty); } } - else if(seq->type == SEQ_SOUND) { - se->ok= 2; + } + } + else if(seq->type < SEQ_EFFECT) { + if(se->ibuf) { + /* test if image too small + or discarded from cache: reload */ + if(se->ibuf->x < seqrectx + || se->ibuf->y < seqrecty + || !se->ibuf->rect) { + IMB_freeImBuf(se->ibuf); + se->ibuf= 0; + se->ok= 1; } - 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; + } + + if(seq->type==SEQ_IMAGE) { + if(se->ok && se->ibuf==0) { + + /* if playanim or render: no waitcursor */ + if((G.f & G_PLAYANIM)==0) waitcursor(1); + + strncpy(name, seq->strip->dir, FILE_MAXDIR-1); + strncat(name, se->name, FILE_MAXFILE); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + se->ibuf= IMB_loadiffname(name, IB_rect); + + if((G.f & G_PLAYANIM)==0) waitcursor(0); + + if(se->ibuf==0) se->ok= 0; + else { + if(seq->flag & SEQ_MAKE_PREMUL) { + if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf); } + seq->strip->orx= se->ibuf->x; + seq->strip->ory= se->ibuf->y; + if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf); + if(seq->mul==0.0) seq->mul= 1.0; + if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul); } - - /* does the effect should be recalculated? */ - - 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; - - if(se->ibuf==0) se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - do_effect(cfra, seq, se); + } + } + 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) { + strncpy(name, seq->strip->dir, FILE_MAXDIR-1); + strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + + seq->anim = openanim(name, IB_rect); } - - /* test size */ - if(se->ibuf) { - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { + 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 + printf("Sorry, sequence scene is not yet back...\n"); +#if 0 + View3D *vd; + Scene *oldsce; + unsigned int *rectot; + int oldcfra, doseq; + int redisplay= (!G.background && !(R.flag & R_RENDERING)); + + oldsce= G.scene; + if(seq->scene!=G.scene) set_scene_bg(seq->scene); + + /* prevent eternal loop */ + doseq= G.scene->r.scemode & R_DOSEQ; + G.scene->r.scemode &= ~R_DOSEQ; + + /* store Current FRAme */ + 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 (redisplay) { + 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; + if(seq->scene!=oldsce) set_scene_bg(oldsce); /* set_scene does full dep updates */ + + /* 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; +#endif + } + + /* size test */ + if(se->ibuf) { + if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { + + if (0) { // G.scene->r.mode & R_FIELDS) { + + if (seqrecty > 288) IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); + else { + IMB_de_interlace(se->ibuf); + if(G.scene->r.mode & R_OSA) IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); else IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); } } + else { + if(G.scene->r.mode & R_OSA) + IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty); + else + IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); + } } - else if(seq->type < SEQ_EFFECT) { + + } + } + if (se->ibuf) { + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + } +} - 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; - } - } +static void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra) +{ + Sequence *seq; + StripElem *se; - if(seq->type==SEQ_IMAGE) { - if(se->ok && se->ibuf==0) { - - /* if playanim or render: no waitcursor */ - if((G.f & G_PLAYANIM)==0) waitcursor(1); - - strncpy(name, seq->strip->dir, FILE_MAXDIR-1); - strncat(name, se->name, FILE_MAXFILE); - BLI_convertstringcode(name, G.sce, G.scene->r.cfra); - se->ibuf= IMB_loadiffname(name, IB_rect); - - if((G.f & G_PLAYANIM)==0) waitcursor(0); - - if(se->ibuf==0) se->ok= 0; - else { - if(seq->flag & SEQ_MAKE_PREMUL) { - if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf); - } - seq->strip->orx= se->ibuf->x; - seq->strip->ory= se->ibuf->y; - if(seq->flag & SEQ_FILTERY) IMB_filtery(se->ibuf); - if(seq->mul==0.0) seq->mul= 1.0; - if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul); - } - } - } - else if(seq->type==SEQ_MOVIE) { - if(se->ok && se->ibuf==0) { - - /* if playanim r render: no waitcursor */ - if((G.f & G_PLAYANIM)==0) waitcursor(1); - - if(seq->anim==0) { - strncpy(name, seq->strip->dir, FILE_MAXDIR-1); - strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1); - BLI_convertstringcode(name, G.sce, G.scene->r.cfra); - - seq->anim = openanim(name, IB_rect); - } - if(seq->anim) { - 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 - printf("Sorry, sequence scene is not yet back...\n"); -#if 0 - View3D *vd; - Scene *oldsce; - unsigned int *rectot; - int oldcfra, doseq; - int redisplay= (!G.background && !(G.rendering)); - - oldsce= G.scene; - if(seq->scene!=G.scene) set_scene_bg(seq->scene); + if(seqar==NULL) return; + + seq= seqbase->first; + while(seq) { - /* prevent eternal loop */ - doseq= G.scene->r.scemode & R_DOSEQ; - G.scene->r.scemode &= ~R_DOSEQ; + /* set at zero because free_imbuf_seq... */ + seq->curelem= 0; - /* store Current FRAme */ - oldcfra= CFRA; + if ((seq->type == SEQ_RAM_SOUND + || seq->type == SEQ_HD_SOUND) && (seq->ipo) + && (seq->startdisp <= cfra+2) + && (seq->enddisp > cfra)) { + do_seq_ipo(seq); + } - CFRA= ( seq->sfra + se->nr ); + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + **seqar= seq; + (*seqar)++; - waitcursor(1); + /* nobody is needed a priori */ + se = seq->curelem= give_stripelem(seq, cfra); + + if (se) { + se->isneeded = 0; + } + } -// 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; + seq= seq->next; + } +} -// RE_initrender(NULL); - if (redisplay) { - mainwindow_make_active(); -// if(R.r.mode & R_FIELDS) update_for_newframe_muted(); -// R.flag= 0; +static void do_build_seq_ibufs(ListBase *seqbase, int cfra) +{ + Sequence *seq; - free_filesel_spec(G.scene->r.pic); - } + seq= seqbase->first; + while(seq) { -// 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; - if(seq->scene!=oldsce) set_scene_bg(oldsce); /* set_scene does full dep updates */ - - /* 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; -#endif - } - /* size test */ - if(se->ibuf) { - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { - - if (0) { //G.scene->r.mode & R_FIELDS) { - - if (seqrecty > 288) IMB_scalefieldImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); - else { - IMB_de_interlace(se->ibuf); - - if(G.scene->r.mode & R_OSA) - IMB_scaleImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); - else - IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); - } - } - else { - if(G.scene->r.mode & R_OSA) - IMB_scaleImBuf(se->ibuf,(short)seqrectx, (short)seqrecty); - else - IMB_scalefastImBuf(se->ibuf, (short)seqrectx, (short)seqrecty); - } - } - } - } + /* set at zero because free_imbuf_seq... */ + seq->curelem= 0; + + if ((seq->type == SEQ_RAM_SOUND + || seq->type == SEQ_HD_SOUND) && (seq->ipo) + && (seq->startdisp <= cfra+2) + && (seq->enddisp > cfra)) { + do_seq_ipo(seq); + } + + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + if(seq->seqbase.first) { + if(cfra< seq->start) + do_build_seq_ibufs(&seq->seqbase, + seq->start); + else if(cfra> seq->start+seq->len-1) + do_build_seq_ibufs(&seq->seqbase, + seq->start + + seq->len-1); + else do_build_seq_ibufs(&seq->seqbase, cfra); } + + do_build_seq_ibuf(seq, cfra); } seq= seq->next; } } -ImBuf *give_ibuf_seq(int rectx, int recty, int cfra) +ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) { Sequence **tseqar, **seqar; Sequence *seq, *seqfirst=0;/* , *effirst=0; */ @@ -2094,7 +2361,8 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra) /* 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 + * this method has been developed especially for + * stills before or after metas */ totseq= 0; @@ -2110,15 +2378,18 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra) /* tseqar is needed because in do_build_... the pointer changes */ seqar= tseqar= MEM_callocN(sizeof(void *)*totseq, "seqar"); - /* this call loads and makes the ibufs */ + /* this call creates the sequence order array */ do_build_seqar_cfra(ed->seqbasep, &seqar, cfra); + seqar= tseqar; for(seqnr=0; seqnr<totseq; seqnr++) { seq= seqar[seqnr]; se= seq->curelem; - if((seq->type != SEQ_SOUND) && (se)) { + if((seq->type != SEQ_RAM_SOUND && seq->type != SEQ_HD_SOUND) + && (se) && + (chanshown == 0 || seq->machine == chanshown)) { if(seq->type==SEQ_META) { /* bottom strip! */ @@ -2150,12 +2421,197 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra) MEM_freeN(seqar); + /* we know, that we have to build the ibuf of seqfirst, + now build the dependencies and later the ibufs */ + + if (seqfirst) { + do_build_seq_depend(seqfirst, cfra); + do_build_seq_ibufs(ed->seqbasep, cfra); + do_seq_unref_cfra(ed->seqbasep, cfra); + do_seq_test_unref_cfra(ed->seqbasep, cfra); + } + + if(!seqfirst) return 0; if(!seqfirst->curelem) return 0; return seqfirst->curelem->ibuf; } +static void rgb_to_yuv(float rgb[3], float yuv[3]) { + yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]; + yuv[1]= 0.492*(rgb[2] - yuv[0]); + yuv[2]= 0.877*(rgb[0] - yuv[0]); + + /* Normalize */ + yuv[1]*= 255.0/(122*2.0); + yuv[1]+= 0.5; + + yuv[2]*= 255.0/(157*2.0); + yuv[2]+= 0.5; +} + +static inline void scope_put_pixel(unsigned char* table, unsigned char * pos) +{ + char newval = table[*pos]; + pos[0] = pos[1] = pos[2] = newval; + pos[3] = 255; +} + +static void wform_put_line(int w, + unsigned char * last_pos, unsigned char * new_pos) +{ + if (last_pos > new_pos) { + unsigned char* temp = new_pos; + new_pos = last_pos; + last_pos = temp; + } + + while (last_pos < new_pos) { + if (last_pos[0] == 0) { + last_pos[0] = last_pos[1] = last_pos[2] = 32; + last_pos[3] = 255; + } + last_pos += 4*w; + } +} + +struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0); + int x,y; + unsigned char* src = (unsigned char*) ibuf->rect; + unsigned char* tgt = (unsigned char*) rval->rect; + int w = ibuf->x + 3; + int h = 515; + float waveform_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + waveform_gamma)*255); + } + + for (y = 0; y < h; y++) { + unsigned char * last_p = 0; + + for (x = 0; x < w; x++) { + unsigned char * rgb = src + 4 * (ibuf->x * y + x); + float v = 1.0 * + ( 0.299*rgb[0] + + 0.587*rgb[1] + + 0.114*rgb[2]) / 255.0; + unsigned char * p = tgt; + p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); + + scope_put_pixel(wtable, p); + p += 4 * w; + scope_put_pixel(wtable, p); + + if (last_p != 0) { + wform_put_line(w, last_p, p); + } + last_p = p; + } + } + + for (x = 0; x < w; x++) { + unsigned char * p = tgt + 4 * x; + p[1] = p[3] = 255.0; + p[4 * w + 1] = p[4 * w + 3] = 255.0; + p = tgt + 4 * (w * (h - 1) + x); + p[1] = p[3] = 255.0; + p[-4 * w + 1] = p[-4 * w + 3] = 255.0; + } + + for (y = 0; y < h; y++) { + unsigned char * p = tgt + 4 * w * y; + p[1] = p[3] = 255.0; + p[4 + 1] = p[4 + 3] = 255.0; + p = tgt + 4 * (w * y + w - 1); + p[1] = p[3] = 255.0; + p[-4 + 1] = p[-4 + 3] = 255.0; + } + + return rval; +} + +static void vectorscope_put_cross(unsigned char r, unsigned char g, + unsigned char b, + char * tgt, int w, int h, int size) +{ + float rgb[3], yuv[3]; + char * p; + int x = 0; + int y = 0; + + rgb[0]= (float)r/255.0; + rgb[1]= (float)g/255.0; + rgb[2]= (float)b/255.0; + rgb_to_yuv(rgb, yuv); + + p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + + (int) ((yuv[1] * (w - 3) + 1))); + + if (r == 0 && g == 0 && b == 0) { + r = 255; + } + + for (y = -size; y <= size; y++) { + for (x = -size; x <= size; x++) { + char * q = p + 4 * (y * w + x); + q[0] = r; q[1] = g; q[2] = b; q[3] = 255; + } + } +} + +struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0); + int x,y; + char* src = (char*) ibuf->rect; + char* tgt = (char*) rval->rect; + float rgb[3], yuv[3]; + int w = 515; + int h = 515; + float scope_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + scope_gamma)*255); + } + + for (x = 0; x <= 255; x++) { + vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1); + vectorscope_put_cross(255 , x, 0, tgt, w, h, 1); + vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1); + vectorscope_put_cross(0, 255, x, tgt, w, h, 1); + vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); + vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); + } + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + char * src1 = src + 4 * (ibuf->x * y + x); + char * p; + + rgb[0]= (float)src1[0]/255.0; + rgb[1]= (float)src1[1]/255.0; + rgb[2]= (float)src1[2]/255.0; + rgb_to_yuv(rgb, yuv); + + p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + + (int) ((yuv[1] * (w - 3) + 1))); + scope_put_pixel(wtable, p); + } + } + + vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); + + return rval; +} + void free_imbuf_effect_spec(int cfra) { Sequence *seq; @@ -2269,13 +2725,13 @@ void free_imbuf_seq() } /* bad levell call... renderer makes a 32 bits rect to put result in */ -void do_render_seq(RenderResult *rr) +void do_render_seq(RenderResult *rr, int cfra) { ImBuf *ibuf; G.f |= G_PLAYANIM; /* waitcursor patch */ - ibuf= give_ibuf_seq(rr->rectx, rr->recty, CFRA); + ibuf= give_ibuf_seq(rr->rectx, rr->recty, cfra, 0); if(ibuf && rr->rect32) { printf("copied\n"); memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty); @@ -2285,7 +2741,9 @@ void do_render_seq(RenderResult *rr) /* R.rectz = BLI_dupallocN(ibuf->zbuf); */ /* } */ - free_imbuf_seq_except(CFRA); + /* Let the cache limitor take care of this + free_imbuf_seq_except(cfra); + */ } G.f &= ~G_PLAYANIM; |