diff options
Diffstat (limited to 'source/blender/src/sequence.c')
-rw-r--r-- | source/blender/src/sequence.c | 2990 |
1 files changed, 0 insertions, 2990 deletions
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c deleted file mode 100644 index 219768b2776..00000000000 --- a/source/blender/src/sequence.c +++ /dev/null @@ -1,2990 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006 - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include <string.h> -#include <math.h> -#include <stdlib.h> - -#include "MEM_guardedalloc.h" -#include "MEM_CacheLimiterC-Api.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" - -#include "DNA_ipo_types.h" -#include "DNA_scene_types.h" -#include "DNA_sequence_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_ipo.h" -#include "BKE_main.h" -#include "BKE_scene.h" -#include "BKE_texture.h" -#include "BKE_utildefines.h" - -#include "BIF_editsound.h" -#include "BIF_editseq.h" -#include "BSE_filesel.h" -#include "BSE_headerbuttons.h" -#include "BIF_interface.h" -#include "BIF_renderwin.h" -#include "BIF_screen.h" -#include "BIF_space.h" -#include "BIF_toolbox.h" - -#include "BSE_sequence.h" -#include "BSE_seqeffects.h" - -#include "RE_pipeline.h" // talks to entire render API - -#include "blendef.h" - -#include "BLI_threads.h" -#include <pthread.h> - -#ifdef WIN32 -#define snprintf _snprintf -#endif - -int seqrectx, seqrecty; - -/* ********************************************************************** - alloc / free functions - ********************************************************************** */ - -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 free_strip(Strip *strip) -{ - strip->us--; - if(strip->us>0) return; - if(strip->us<0) { - printf("error: negative users in strip\n"); - return; - } - - if (strip->stripdata) { - MEM_freeN(strip->stripdata); - } - - if (strip->proxy) { - MEM_freeN(strip->proxy); - } - if (strip->crop) { - MEM_freeN(strip->crop); - } - if (strip->transform) { - MEM_freeN(strip->transform); - } - if (strip->color_balance) { - MEM_freeN(strip->color_balance); - } - - free_tstripdata(strip->len, strip->tstripdata); - free_tstripdata(strip->endstill, strip->tstripdata_endstill); - free_tstripdata(strip->startstill, strip->tstripdata_startstill); - - if(strip->ibuf_startstill) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } - - if(strip->ibuf_endstill) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } - - MEM_freeN(strip); -} - -void new_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; - } -} - -void free_sequence(Sequence *seq) -{ - Sequence *last_seq = get_last_seq(); - - if(seq->strip) free_strip(seq->strip); - - if(seq->anim) IMB_free_anim(seq->anim); - if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); - - if (seq->type & SEQ_EFFECT) { - struct SeqEffectHandle sh = get_sequence_effect(seq); - - sh.free(seq); - } - - if(seq==last_seq) set_last_seq(NULL); - - MEM_freeN(seq); -} - -/* - ********************************************************************** - * build_seqar - ********************************************************************** - * Build a complete array of _all_ sequencies (including those - * in metastrips!) - ********************************************************************** -*/ - -static void do_seq_count(ListBase *seqbase, int *totseq) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - (*totseq)++; - if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq); - seq= seq->next; - } -} - -static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - seq->depth= depth; - if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1); - **seqar= seq; - (*seqar)++; - seq= seq->next; - } -} - -void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) -{ - Sequence **tseqar; - - *totseq= 0; - do_seq_count(seqbase, totseq); - - if(*totseq==0) { - *seqar= 0; - return; - } - *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); - tseqar= *seqar; - - do_build_seqar(seqbase, seqar, 0); - *seqar= tseqar; -} - -static void do_seq_count_cb(ListBase *seqbase, int *totseq, - int (*test_func)(Sequence * seq)) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - int test = test_func(seq); - if (test & BUILD_SEQAR_COUNT_CURRENT) { - (*totseq)++; - } - if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { - do_seq_count_cb(&seq->seqbase, totseq, test_func); - } - seq= seq->next; - } -} - -static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth, - int (*test_func)(Sequence * seq)) -{ - Sequence *seq; - - seq= seqbase->first; - while(seq) { - int test = test_func(seq); - seq->depth= depth; - - if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { - do_build_seqar_cb(&seq->seqbase, seqar, depth+1, - test_func); - } - if (test & BUILD_SEQAR_COUNT_CURRENT) { - **seqar= seq; - (*seqar)++; - } - seq= seq->next; - } -} - -void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, - int (*test_func)(Sequence * seq)) -{ - Sequence **tseqar; - - *totseq= 0; - do_seq_count_cb(seqbase, totseq, test_func); - - if(*totseq==0) { - *seqar= 0; - return; - } - *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); - tseqar= *seqar; - - do_build_seqar_cb(seqbase, seqar, 0, test_func); - *seqar= tseqar; -} - - -void free_editing(Editing *ed) -{ - MetaStack *ms; - Sequence *seq; - - if(ed==NULL) return; - set_last_seq(NULL); /* clear_last_seq doesnt work, it screws up free_sequence */ - - WHILE_SEQ(&ed->seqbase) { - free_sequence(seq); - } - END_SEQ - - while( (ms= ed->metastack.first) ) { - BLI_remlink(&ed->metastack, ms); - MEM_freeN(ms); - } - - MEM_freeN(ed); - -} - -void calc_sequence_disp(Sequence *seq) -{ - if(seq->startofs && seq->startstill) seq->startstill= 0; - if(seq->endofs && seq->endstill) seq->endstill= 0; - - seq->startdisp= seq->start + seq->startofs - seq->startstill; - seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill; - - seq->handsize= 10.0; /* 10 frames */ - if( seq->enddisp-seq->startdisp < 10 ) { - seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp)); - } - else if(seq->enddisp-seq->startdisp > 250) { - seq->handsize= (float)((seq->enddisp-seq->startdisp)/25); - } -} - -void calc_sequence(Sequence *seq) -{ - Sequence *seqm; - int min, max; - - /* check all metas recursively */ - seqm= seq->seqbase.first; - while(seqm) { - if(seqm->seqbase.first) calc_sequence(seqm); - seqm= seqm->next; - } - - /* effects and meta: automatic start and end */ - - if(seq->type & SEQ_EFFECT) { - /* pointers */ - if(seq->seq2==0) seq->seq2= seq->seq1; - if(seq->seq3==0) seq->seq3= seq->seq1; - - /* effecten go from seq1 -> seq2: test */ - - /* we take the largest start and smallest end */ - - // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp); - // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp); - - if (seq->seq1) { - seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); - seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); - seq->len= seq->enddisp - seq->startdisp; - } else { - calc_sequence_disp(seq); - } - - if(seq->strip && seq->len!=seq->strip->len) { - new_tstripdata(seq); - } - - } - else { - if(seq->type==SEQ_META) { - seqm= seq->seqbase.first; - if(seqm) { - min= 1000000; - max= -1000000; - while(seqm) { - if(seqm->startdisp < min) min= seqm->startdisp; - if(seqm->enddisp > max) max= seqm->enddisp; - seqm= seqm->next; - } - seq->start= min + seq->anim_startofs; - seq->len = max-min; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - - if(seq->strip && seq->len!=seq->strip->len) { - new_tstripdata(seq); - } - } - } - calc_sequence_disp(seq); - } -} - -void reload_sequence_new_file(Sequence * seq) -{ - char str[FILE_MAXDIR+FILE_MAXFILE]; - - if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || - seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND || - seq->type == SEQ_SCENE || seq->type == SEQ_META)) { - return; - } - - new_tstripdata(seq); - - if (seq->type != SEQ_SCENE && seq->type != SEQ_META && - seq->type != SEQ_IMAGE) { - BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name); - BLI_convertstringcode(str, G.sce); - BLI_convertstringframe(str, G.scene->r.cfra); - - } - - if (seq->type == SEQ_IMAGE) { - /* Hack? */ - int olen = MEM_allocN_len(seq->strip->stripdata) - / sizeof(struct StripElem); - seq->len = olen; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_MOVIE) { - if(seq->anim) IMB_free_anim(seq->anim); - seq->anim = openanim( - str, IB_rect | - ((seq->flag & SEQ_FILTERY) - ? IB_animdeinterlace : 0)); - - if (!seq->anim) { - return; - } - - seq->len = IMB_anim_get_duration(seq->anim); - - seq->anim_preseek = IMB_anim_get_preseek(seq->anim); - - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_HD_SOUND) { - if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); - seq->hdaudio = sound_open_hdaudio(str); - - if (!seq->hdaudio) { - return; - } - - seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS) - - seq->anim_startofs - seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_RAM_SOUND) { - seq->len = (int) ( ((float)(seq->sound->streamlen-1)/ - ((float)G.scene->audio.mixrate*4.0 )) - * FPS); - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } else if (seq->type == SEQ_SCENE) { - Scene * sce = G.main->scene.first; - int nr = 1; - while(sce) { - if(nr == seq->scenenr) { - break; - } - nr++; - sce= sce->id.next; - } - - if (sce) { - seq->scene = sce; - } else { - sce = seq->scene; - } - - strncpy(seq->name + 2, sce->id.name + 2, - sizeof(seq->name) - 2); - - seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; - seq->len -= seq->anim_startofs; - seq->len -= seq->anim_endofs; - if (seq->len < 0) { - seq->len = 0; - } - seq->strip->len = seq->len; - } - - calc_sequence(seq); -} - -void sort_seq() -{ - /* all strips together per kind, and in order of y location ("machine") */ - ListBase seqbase, effbase; - Editing *ed; - Sequence *seq, *seqt; - - ed= G.scene->ed; - if(ed==0) return; - - seqbase.first= seqbase.last= 0; - effbase.first= effbase.last= 0; - - while( (seq= ed->seqbasep->first) ) { - BLI_remlink(ed->seqbasep, seq); - - if(seq->type & SEQ_EFFECT) { - seqt= effbase.first; - while(seqt) { - if(seqt->machine>=seq->machine) { - BLI_insertlinkbefore(&effbase, seqt, seq); - break; - } - seqt= seqt->next; - } - if(seqt==0) BLI_addtail(&effbase, seq); - } - else { - seqt= seqbase.first; - while(seqt) { - if(seqt->machine>=seq->machine) { - BLI_insertlinkbefore(&seqbase, seqt, seq); - break; - } - seqt= seqt->next; - } - if(seqt==0) BLI_addtail(&seqbase, seq); - } - } - - addlisttolist(&seqbase, &effbase); - *(ed->seqbasep)= seqbase; -} - - -void clear_scene_in_allseqs(Scene *sce) -{ - Scene *sce1; - Editing *ed; - Sequence *seq; - - /* when a scene is deleted: test all seqs */ - - sce1= G.main->scene.first; - while(sce1) { - if(sce1!=sce && sce1->ed) { - ed= sce1->ed; - - WHILE_SEQ(&ed->seqbase) { - - if(seq->scene==sce) seq->scene= 0; - - } - END_SEQ - } - - sce1= sce1->id.next; - } -} - -char *give_seqname_by_type(int type) -{ - switch(type) { - case SEQ_META: return "Meta"; - case SEQ_IMAGE: return "Image"; - case SEQ_SCENE: return "Scene"; - case SEQ_MOVIE: return "Movie"; - case SEQ_RAM_SOUND: return "Audio (RAM)"; - case SEQ_HD_SOUND: return "Audio (HD)"; - case SEQ_CROSS: return "Cross"; - case SEQ_GAMCROSS: return "Gamma Cross"; - case SEQ_ADD: return "Add"; - case SEQ_SUB: return "Sub"; - case SEQ_MUL: return "Mul"; - case SEQ_ALPHAOVER: return "Alpha Over"; - case SEQ_ALPHAUNDER: return "Alpha Under"; - case SEQ_OVERDROP: return "Over Drop"; - case SEQ_WIPE: return "Wipe"; - case SEQ_GLOW: return "Glow"; - case SEQ_TRANSFORM: return "Transform"; - case SEQ_COLOR: return "Color"; - case SEQ_SPEED: return "Speed"; - default: - return 0; - } -} - -char *give_seqname(Sequence *seq) -{ - char * name = give_seqname_by_type(seq->type); - - if (!name) { - if(seq->type<SEQ_EFFECT) { - return seq->strip->dir; - } else if(seq->type==SEQ_PLUGIN) { - if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) && - seq->plugin && seq->plugin->doit) { - return seq->plugin->pname; - } else { - return "Plugin"; - } - } else { - return "Effect"; - } - } - return name; -} - -/* ***************** DO THE SEQUENCE ***************** */ - -static void make_black_ibuf(ImBuf *ibuf) -{ - unsigned int *rect; - float *rect_float; - int tot; - - if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; - - tot= ibuf->x*ibuf->y; - - rect= ibuf->rect; - rect_float = ibuf->rect_float; - - if (rect) { - memset(rect, 0, tot * sizeof(char) * 4); - } - - if (rect_float) { - memset(rect_float, 0, tot * sizeof(float) * 4); - } -} - -static void multibuf(ImBuf *ibuf, float fmul) -{ - char *rt; - float *rt_float; - - int a, mul, icol; - - mul= (int)(256.0*fmul); - rt= (char *)ibuf->rect; - rt_float = ibuf->rect_float; - - if (rt) { - a= ibuf->x*ibuf->y; - while(a--) { - - icol= (mul*rt[0])>>8; - if(icol>254) rt[0]= 255; else rt[0]= icol; - icol= (mul*rt[1])>>8; - if(icol>254) rt[1]= 255; else rt[1]= icol; - icol= (mul*rt[2])>>8; - if(icol>254) rt[2]= 255; else rt[2]= icol; - icol= (mul*rt[3])>>8; - if(icol>254) rt[3]= 255; else rt[3]= icol; - - rt+= 4; - } - } - if (rt_float) { - a= ibuf->x*ibuf->y; - while(a--) { - rt_float[0] *= fmul; - rt_float[1] *= fmul; - rt_float[2] *= fmul; - rt_float[3] *= fmul; - - rt_float += 4; - } - } -} - -static void do_effect(int cfra, Sequence *seq, TStripElem * se) -{ - TStripElem *se1, *se2, *se3; - float fac, facf; - int x, y; - int early_out; - struct SeqEffectHandle sh = get_sequence_effect(seq); - - if (!sh.execute) { /* effect not supported in this version... */ - make_black_ibuf(se->ibuf); - return; - } - - if(seq->ipo && seq->ipo->curve.first) { - do_seq_ipo(seq, cfra); - fac= seq->facf0; - facf= seq->facf1; - } else { - sh.get_default_fac(seq, cfra, &fac, &facf); - } - - if( !(G.scene->r.mode & R_FIELDS) ) facf = fac; - - early_out = sh.early_out(seq, fac, facf); - - if (early_out == -1) { /* no input needed */ - sh.execute(seq, cfra, fac, facf, - se->ibuf->x, se->ibuf->y, - 0, 0, 0, se->ibuf); - return; - } - - 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(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 { - if(cfra <= seq->start) nr= 0; - else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; - else nr= cfra-seq->start; - } - if (seq->strobe < 1.0) seq->strobe = 1.0; - if (seq->strobe > 1.0) { - nr -= (int)fmod((double)nr, (double)seq->strobe); - } - - 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; -} - -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; - int nr; - - se = seq->strip->stripdata; - nr = give_stripelem_index(seq, cfra); - - if (nr == -1) return 0; - if (se == 0) return 0; - - se += nr + seq->anim_startofs; - - return se; -} - -static int evaluate_seq_frame_gen( - Sequence ** seq_arr, ListBase *seqbase, int cfra) -{ - Sequence *seq; - int totseq=0; - - memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1)); - - seq= seqbase->first; - while(seq) { - if(seq->startdisp <=cfra && seq->enddisp > cfra) { - seq_arr[seq->machine]= seq; - totseq++; - } - seq= seq->next; - } - - return totseq; -} - -int evaluate_seq_frame(int cfra) -{ - Editing *ed; - Sequence *seq_arr[MAXSEQ+1]; - - ed= G.scene->ed; - if(ed==0) return 0; - - return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra); - -} - -static int video_seq_is_rendered(Sequence * seq) -{ - return (seq - && !(seq->flag & SEQ_MUTE) - && seq->type != SEQ_RAM_SOUND - && seq->type != SEQ_HD_SOUND); -} - -static int get_shown_sequences( - ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out) -{ - Sequence *seq_arr[MAXSEQ+1]; - int b = chanshown; - int cnt = 0; - - if (b > MAXSEQ) { - return 0; - } - - if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) { - if (b > 0) { - if (seq_arr[b] == 0) { - return 0; - } - } else { - for (b = MAXSEQ; b > 0; b--) { - if (video_seq_is_rendered(seq_arr[b])) { - break; - } - } - } - } - - chanshown = b; - - for (;b > 0; b--) { - if (video_seq_is_rendered(seq_arr[b])) { - if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) { - break; - } - } - } - - for (;b <= chanshown; b++) { - if (video_seq_is_rendered(seq_arr[b])) { - seq_arr_out[cnt++] = seq_arr[b]; - } - } - - return cnt; -} - - -/* ********************************************************************** - proxy management - ********************************************************************** */ - -#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE) - -static int seq_proxy_get_fname(Sequence * seq, int cfra, char * name) -{ - int frameno; - char dir[FILE_MAXDIR]; - - if (!seq->strip->proxy) { - return FALSE; - } - - if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { - strcpy(dir, seq->strip->proxy->dir); - } else { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { - snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", - seq->strip->dir); - } else { - return FALSE; - } - } - - /* generate a seperate proxy directory for each preview size */ - - if (seq->type == SEQ_IMAGE) { - StripElem * se = give_stripelem(seq, cfra); - snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", - dir, G.scene->r.size, se->name); - frameno = 1; - } else if (seq->type == SEQ_MOVIE) { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; - - snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, - seq->strip->stripdata->name, - G.scene->r.size); - } else { - TStripElem * tse = give_tstripelem(seq, cfra); - - frameno = tse->nr + seq->anim_startofs; - - snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, - G.scene->r.size); - } - - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, frameno); - - - strcat(name, ".jpg"); - - return TRUE; -} - -static struct ImBuf * seq_proxy_fetch(Sequence * seq, int cfra) -{ - char name[PROXY_MAXFILE]; - - if (!(seq->flag & SEQ_USE_PROXY)) { - return 0; - } - - /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (G.scene->r.size == 100.0) { - return 0; - } - - if (!seq_proxy_get_fname(seq, cfra, name)) { - return 0; - } - - if (BLI_exists(name)) { - return IMB_loadiffname(name, IB_rect); - } else { - return 0; - } -} - -static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run); - -static void seq_proxy_build_frame(Sequence * seq, int cfra) -{ - char name[PROXY_MAXFILE]; - int quality; - TStripElem * se; - int ok; - int rectx, recty; - struct ImBuf * ibuf; - - if (!(seq->flag & SEQ_USE_PROXY)) { - return; - } - - /* rendering at 100% ? No real sense in proxy-ing, right? */ - if (G.scene->r.size == 100.0) { - return; - } - - if (!seq_proxy_get_fname(seq, cfra, name)) { - return; - } - - se = give_tstripelem(seq, cfra); - if (!se) { - return; - } - - if(se->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = 0; - } - - do_build_seq_ibuf(seq, se, cfra, TRUE); - - if (!se->ibuf) { - return; - } - - rectx= (G.scene->r.size*G.scene->r.xsch)/100; - recty= (G.scene->r.size*G.scene->r.ysch)/100; - - ibuf = se->ibuf; - - if (ibuf->x != rectx || ibuf->y != recty) { - IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); - } - - /* quality is fixed, otherwise one has to generate seperate - directories for every quality... - - depth = 32 is intentionally left in, otherwise ALPHA channels - won't work... */ - quality = 90; - ibuf->ftype= JPG | quality; - - BLI_make_existing_file(name); - - ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); - if (ok == 0) { - perror(name); - } - - IMB_freeImBuf(ibuf); - se->ibuf = 0; -} - -void seq_proxy_rebuild(Sequence * seq) -{ - int cfra; - - waitcursor(1); - - G.afbreek = 0; - - /* flag management tries to account for strobe and - other "non-linearities", that might come in the future... - better way would be to "touch" the files, so that _really_ - no one is rebuild twice. - */ - - for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) { - TStripElem * tse = give_tstripelem(seq, cfra); - - tse->flag &= ~STRIPELEM_PREVIEW_DONE; - } - - /* a _lot_ faster for movie files, if we read frames in - sequential order */ - if (seq->flag & SEQ_REVERSE_FRAMES) { - for (cfra = seq->enddisp-seq->endstill-1; - cfra >= seq->startdisp + seq->startstill; cfra--) { - TStripElem * tse = give_tstripelem(seq, cfra); - - if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { - seq_proxy_build_frame(seq, cfra); - tse->flag |= STRIPELEM_PREVIEW_DONE; - } - if (blender_test_break()) { - break; - } - } - } else { - for (cfra = seq->startdisp + seq->startstill; - cfra < seq->enddisp - seq->endstill; cfra++) { - TStripElem * tse = give_tstripelem(seq, cfra); - - if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { - seq_proxy_build_frame(seq, cfra); - tse->flag |= STRIPELEM_PREVIEW_DONE; - } - if (blender_test_break()) { - break; - } - } - } - waitcursor(0); -} - - -/* ********************************************************************** - color balance - ********************************************************************** */ - -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] = -(1.0 - cb.lift[c]); - } - } - if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) { - for (c = 0; c < 3; c++) { - if (cb.gain[c] != 0.0) { - cb.gain[c] = 1.0/cb.gain[c]; - } else { - cb.gain[c] = 1000000; /* should be enough :) */ - } - } - } - - if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) { - for (c = 0; c < 3; c++) { - if (cb.gamma[c] != 0.0) { - cb.gamma[c] = 1.0/cb.gamma[c]; - } else { - cb.gamma[c] = 1000000; /* should be enough :) */ - } - } - } - - return cb; -} - -static void make_cb_table_byte(float lift, float gain, float gamma, - unsigned char * table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = 1.0 * y / 255; - v *= gain; - v += lift; - v = pow(v, gamma); - v *= mul; - if ( v > 1.0) { - v = 1.0; - } else if (v < 0.0) { - v = 0.0; - } - table[y] = v * 255; - } - -} - -static void make_cb_table_float(float lift, float gain, float gamma, - float * table, float mul) -{ - 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; - table[y] = v; - } -} - -static void color_balance_byte_byte(Sequence * seq, TStripElem* se, - float mul) -{ - unsigned char cb_tab[3][256]; - int c; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; - - StripColorBalance cb = calc_cb(seq->strip->color_balance); - - for (c = 0; c < 3; c++) { - make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], - cb_tab[c], mul); - } - - while (p < e) { - p[0] = cb_tab[0][p[0]]; - p[1] = cb_tab[1][p[1]]; - p[2] = cb_tab[2][p[2]]; - - p += 4; - } -} - -static void color_balance_byte_float(Sequence * seq, TStripElem* se, - float mul) -{ - float cb_tab[4][256]; - int c,i; - unsigned char * p = (unsigned char*) se->ibuf->rect; - unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; - float * o; - StripColorBalance cb; - - imb_addrectfloatImBuf(se->ibuf); - - o = se->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); - } - - for (i = 0; i < 256; i++) { - cb_tab[3][i] = ((float)i)*(1.0f/255.0f); - } - - while (p < e) { - o[0] = cb_tab[0][p[0]]; - o[1] = cb_tab[1][p[1]]; - o[2] = cb_tab[2][p[2]]; - o[3] = cb_tab[3][p[3]]; - - p += 4; o += 4; - } -} - -static void color_balance_float_float(Sequence * seq, TStripElem* se, - float mul) -{ - float * p = se->ibuf->rect_float; - float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y; - StripColorBalance cb = calc_cb(seq->strip->color_balance); - - while (p < e) { - int c; - for (c = 0; c < 3; c++) { - p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], - cb.gamma[c]) * mul; - } - p += 4; - } -} - -static void color_balance(Sequence * seq, TStripElem* se, float mul) -{ - if (se->ibuf->rect_float) { - color_balance_float_float(seq, se, mul); - } else if(seq->flag & SEQ_MAKE_FLOAT) { - color_balance_byte_float(seq, se, mul); - } else { - color_balance_byte_byte(seq, se, mul); - } -} - -/* - input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE - - Do all the things you can't really do afterwards using sequence effects - (read: before rescaling to render resolution has been done) - - Order is important! - - - Deinterlace - - Crop and transform in image source coordinate space - - Flip X + Flip Y (could be done afterwards, backward compatibility) - - Promote image to float data (affects pipeline operations afterwards) - - Color balance (is most efficient in the byte -> float - (future: half -> float should also work fine!) - case, if done on load, since we can use lookup tables) - - Premultiply - -*/ - -static int input_have_to_preprocess(Sequence * seq, TStripElem* se, int cfra) -{ - float mul; - - if ((seq->flag & SEQ_FILTERY) || - (seq->flag & SEQ_USE_CROP) || - (seq->flag & SEQ_USE_TRANSFORM) || - (seq->flag & SEQ_FLIPX) || - (seq->flag & SEQ_FLIPY) || - (seq->flag & SEQ_USE_COLOR_BALANCE) || - (seq->flag & SEQ_MAKE_PREMUL) || - (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) { - return TRUE; - } - - mul = seq->mul; - - if(seq->blend_mode == SEQ_BLEND_REPLACE) { - if (seq->ipo && seq->ipo->curve.first) { - do_seq_ipo(seq, cfra); - mul *= seq->facf0; - } - mul *= seq->blend_opacity / 100.0; - } - - if (mul != 1.0) { - return TRUE; - } - - return FALSE; -} - -static void input_preprocess(Sequence * seq, TStripElem* se, int cfra) -{ - float mul; - - seq->strip->orx= se->ibuf->x; - seq->strip->ory= se->ibuf->y; - - if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { - IMB_filtery(se->ibuf); - } - - if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { - StripCrop c; - StripTransform t; - int sx,sy,dx,dy; - - memset(&c, 0, sizeof(StripCrop)); - memset(&t, 0, sizeof(StripTransform)); - - if(seq->flag & SEQ_USE_CROP && seq->strip->crop) { - c = *seq->strip->crop; - } - if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) { - t = *seq->strip->transform; - } - - sx = se->ibuf->x - c.left - c.right; - sy = se->ibuf->y - c.top - c.bottom; - dx = sx; - dy = sy; - - if (seq->flag & SEQ_USE_TRANSFORM) { - dx = G.scene->r.xsch; - dy = G.scene->r.ysch; - } - - if (c.top + c.bottom >= se->ibuf->y || - c.left + c.right >= se->ibuf->x || - t.xofs >= dx || t.yofs >= dy) { - make_black_ibuf(se->ibuf); - } else { - ImBuf * i; - - if (se->ibuf->rect_float) { - i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); - } else { - i = IMB_allocImBuf(dx, dy,32, IB_rect, 0); - } - - IMB_rectcpy(i, se->ibuf, - t.xofs, t.yofs, - c.left, c.bottom, - sx, sy); - - IMB_freeImBuf(se->ibuf); - - se->ibuf = i; - } - } - - if(seq->flag & SEQ_FLIPX) { - IMB_flipx(se->ibuf); - } - if(seq->flag & SEQ_FLIPY) { - IMB_flipy(se->ibuf); - } - - if(seq->mul == 0.0) { - seq->mul = 1.0; - } - - mul = seq->mul; - - if(seq->blend_mode == SEQ_BLEND_REPLACE) { - if (seq->ipo && seq->ipo->curve.first) { - do_seq_ipo(seq, cfra); - mul *= seq->facf0; - } - mul *= seq->blend_opacity / 100.0; - } - - if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - color_balance(seq, se, mul); - mul = 1.0; - } - - if(seq->flag & SEQ_MAKE_FLOAT) { - if (!se->ibuf->rect_float) { - IMB_float_from_rect(se->ibuf); - } - if (se->ibuf->rect) { - imb_freerectImBuf(se->ibuf); - } - } - - if(mul != 1.0) { - multibuf(se->ibuf, mul); - } - - if(seq->flag & SEQ_MAKE_PREMUL) { - if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) { - converttopremul(se->ibuf); - } - } - - - if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { - if(G.scene->r.mode & R_OSA) { - IMB_scaleImBuf(se->ibuf, - (short)seqrectx, (short)seqrecty); - } else { - IMB_scalefastImBuf(se->ibuf, - (short)seqrectx, (short)seqrecty); - } - } -} - -/* test if image too small or discarded from cache: reload */ - -static void test_and_auto_discard_ibuf(TStripElem * se) -{ - 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; - se->ok= STRIPELEM_OK; - } - } - if (se->ibuf_comp) { - if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty - || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) { - IMB_freeImBuf(se->ibuf_comp); - - se->ibuf_comp = 0; - } - } -} - -static void test_and_auto_discard_ibuf_stills(Strip * strip) -{ - if (strip->ibuf_startstill) { - if (!strip->ibuf_startstill->rect && - !strip->ibuf_startstill->rect_float) { - IMB_freeImBuf(strip->ibuf_startstill); - strip->ibuf_startstill = 0; - } - } - if (strip->ibuf_endstill) { - if (!strip->ibuf_endstill->rect && - !strip->ibuf_endstill->rect_float) { - IMB_freeImBuf(strip->ibuf_endstill); - strip->ibuf_endstill = 0; - } - } -} - -static void copy_from_ibuf_still(Sequence * seq, TStripElem * se) -{ - if (!se->ibuf) { - if (se->nr == 0 && seq->strip->ibuf_startstill) { - IMB_cache_limiter_touch(seq->strip->ibuf_startstill); - - 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); - } - } -} - -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); - - 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); - - 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) -{ - Sequence* seq_arr[MAXSEQ+1]; - int i; - TStripElem* se = 0; - - 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; - } - - if (se->ibuf_comp) { - IMB_freeImBuf(se->ibuf_comp); - - se->ibuf_comp = 0; - } - } - } - -} - -static TStripElem* do_build_seq_array_recursively( - ListBase *seqbasep, int cfra, int chanshown); - -static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, - int build_proxy_run) -{ - char name[FILE_MAXDIR+FILE_MAXFILE]; - int use_limiter = TRUE; - - test_and_auto_discard_ibuf(se); - test_and_auto_discard_ibuf_stills(seq->strip); - - if(seq->type == SEQ_META) { - TStripElem * meta_se = 0; - use_limiter = FALSE; - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(seq, cfra); - if (se->ibuf) { - use_limiter = TRUE; - } - } - - if(!se->ibuf && seq->seqbase.first) { - meta_se = do_build_seq_array_recursively( - &seq->seqbase, seq->start + se->nr, 0); - } - - se->ok = STRIPELEM_OK; - - if(!se->ibuf && meta_se) { - se->ibuf = meta_se->ibuf_comp; - if(se->ibuf && - (!input_have_to_preprocess(seq, se, cfra) || - build_proxy_run)) { - IMB_refImBuf(se->ibuf); - if (build_proxy_run) { - IMB_cache_limiter_unref(se->ibuf); - } - } else if (se->ibuf) { - struct ImBuf * i = IMB_dupImBuf(se->ibuf); - - IMB_cache_limiter_unref(se->ibuf); - - se->ibuf = i; - - use_limiter = TRUE; - } - } - if (meta_se) { - free_metastrip_imbufs( - &seq->seqbase, seq->start + se->nr, 0); - } - - if (use_limiter) { - input_preprocess(seq, se, cfra); - } - } else if(seq->type & SEQ_EFFECT) { - /* should the effect be recalculated? */ - - if (!build_proxy_run && se->ibuf == 0) { - se->ibuf = seq_proxy_fetch(seq, cfra); - } - - if(se->ibuf == 0) { - /* if 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(cfra, seq, se); - } - } 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_convertstringcode(name, G.sce); - BLI_convertstringframe(name, G.scene->r.cfra); - if (!build_proxy_run) { - se->ibuf = seq_proxy_fetch(seq, cfra); - } - copy_from_ibuf_still(seq, se); - - if (!se->ibuf) { - se->ibuf= IMB_loadiffname( - name, IB_rect); - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(seq, se, cfra); - } - } - } else if(seq->type == SEQ_MOVIE) { - if(se->ok == STRIPELEM_OK && se->ibuf==0) { - if(!build_proxy_run) { - se->ibuf = seq_proxy_fetch(seq, cfra); - } - copy_from_ibuf_still(seq, se); - - if (se->ibuf == 0) { - if(seq->anim==0) { - BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); - BLI_convertstringcode(name, G.sce); - BLI_convertstringframe(name, G.scene->r.cfra); - - 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); - } - copy_to_ibuf_still(seq, se); - } - - if(se->ibuf == 0) { - se->ok = STRIPELEM_FAILED; - } else if (!build_proxy_run) { - input_preprocess(seq, se, cfra); - } - } - } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions - int oldcfra = CFRA; - Sequence * oldseq = get_last_seq(); - Scene *sce= seq->scene, *oldsce= G.scene; - Render *re; - RenderResult rres; - int doseq, rendering= G.rendering; - char scenename[64]; - int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ); - - if (se->ibuf == NULL && sce_valid && !build_proxy_run) { - se->ibuf = seq_proxy_fetch(seq, cfra); - if (se->ibuf) { - input_preprocess(seq, se, cfra); - } - } - - if (se->ibuf == NULL && sce_valid) { - copy_from_ibuf_still(seq, se); - if (se->ibuf) { - input_preprocess(seq, se, cfra); - } - } - - if (!sce_valid) { - se->ok = STRIPELEM_FAILED; - } else if (se->ibuf==NULL && sce_valid) { - waitcursor(1); - - /* Hack! This function can be called from do_render_seq(), in that case - the seq->scene can already have a Render initialized with same name, - so we have to use a default name. (compositor uses G.scene name to - find render). - However, when called from within the UI (image preview in sequencer) - we do want to use scene Render, that way the render result is defined - for display in render/imagewindow */ - if(rendering) { - BLI_strncpy(scenename, sce->id.name+2, 64); - strcpy(sce->id.name+2, " do_build_seq_ibuf"); - } - re= RE_NewRender(sce->id.name); - - /* prevent eternal loop */ - doseq= G.scene->r.scemode & R_DOSEQ; - G.scene->r.scemode &= ~R_DOSEQ; - - BIF_init_render_callbacks(re, 0); /* 0= no display callbacks */ - - /* hrms, set_scene still needed? work on that... */ - if(sce!=oldsce) set_scene_bg(sce); - RE_BlenderFrame(re, sce, - seq->sfra+se->nr+seq->anim_startofs); - if(sce!=oldsce) set_scene_bg(oldsce); - - /* UGLY WARNING, it is set to zero in RE_BlenderFrame */ - G.rendering= rendering; - if(rendering) - BLI_strncpy(sce->id.name+2, scenename, 64); - - RE_GetResultImage(re, &rres); - - if(rres.rectf) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); - memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); - if(rres.rectz) { - addzbuffloatImBuf(se->ibuf); - memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); - } - } else if (rres.rect32) { - se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); - memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); - } - - BIF_end_render_callbacks(); - - /* restore */ - G.scene->r.scemode |= doseq; - - if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */ - waitcursor(0); - CFRA = oldcfra; - set_last_seq(oldseq); - - copy_to_ibuf_still(seq, se); - - if (!build_proxy_run) { - if(se->ibuf == NULL) { - se->ok = STRIPELEM_FAILED; - } else { - input_preprocess(seq, se, cfra); - } - } - - } - } - 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); - } - } -} - -static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra); - -static void do_effect_seq_recursively(Sequence * seq, TStripElem *se, int cfra) -{ - float fac, facf; - struct SeqEffectHandle sh = get_sequence_effect(seq); - int early_out; - - se->se1 = 0; - se->se2 = 0; - se->se3 = 0; - - if(seq->ipo && seq->ipo->curve.first) { - do_seq_ipo(seq, cfra); - fac= seq->facf0; - facf= seq->facf1; - } else { - sh.get_default_fac(seq, cfra, &fac, &facf); - } - - if( G.scene->r.mode & R_FIELDS ); else facf= fac; - - early_out = sh.early_out(seq, fac, facf); - switch (early_out) { - case -1: - /* no input needed */ - break; - case 0: - se->se1 = do_build_seq_recursively(seq->seq1, cfra); - se->se2 = do_build_seq_recursively(seq->seq2, cfra); - if (seq->seq3) { - se->se3 = do_build_seq_recursively(seq->seq3, cfra); - } - break; - case 1: - se->se1 = do_build_seq_recursively(seq->seq1, cfra); - break; - case 2: - se->se2 = do_build_seq_recursively(seq->seq2, cfra); - break; - } - - - do_build_seq_ibuf(seq, se, cfra, FALSE); - - /* children are not needed anymore ... */ - - if (se->se1 && se->se1->ibuf) { - IMB_cache_limiter_unref(se->se1->ibuf); - } - if (se->se2 && se->se2->ibuf) { - IMB_cache_limiter_unref(se->se2->ibuf); - } - if (se->se3 && se->se3->ibuf) { - IMB_cache_limiter_unref(se->se3->ibuf); - } -} - -static TStripElem* do_build_seq_recursively_impl(Sequence * seq, int cfra) -{ - TStripElem *se; - - se = give_tstripelem(seq, cfra); - - if(se) { - if (seq->type & SEQ_EFFECT) { - do_effect_seq_recursively(seq, se, cfra); - } else { - do_build_seq_ibuf(seq, se, cfra, FALSE); - } - } - return se; -} - -/* FIXME: - -If cfra was float throughout blender (especially in the render -pipeline) one could even _render_ with subframe precision -instead of faking using the blend code below... - -*/ - -static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra) -{ - SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; - int nr = cfra - seq->start; - float f_cfra; - int cfra_left; - int cfra_right; - TStripElem * se = 0; - TStripElem * se1 = 0; - TStripElem * se2 = 0; - - sequence_effect_speed_rebuild_map(seq, 0); - - f_cfra = seq->start + s->frameMap[nr]; - - cfra_left = (int) floor(f_cfra); - cfra_right = (int) ceil(f_cfra); - - se = give_tstripelem(seq, cfra); - - if (!se) { - return se; - } - - if (cfra_left == cfra_right || - (s->flags & SEQ_SPEED_BLEND) == 0) { - test_and_auto_discard_ibuf(se); - - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl( - seq->seq1, cfra_left); - - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - if (se1 == 0 || se1->ibuf == 0) { - make_black_ibuf(se->ibuf); - } else { - if (se->ibuf != se1->ibuf) { - if (se->ibuf) { - IMB_freeImBuf(se->ibuf); - } - - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } - } - } - } else { - struct SeqEffectHandle sh; - - if(se->ibuf) { - if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty - || !(se->ibuf->rect || se->ibuf->rect_float)) { - IMB_freeImBuf(se->ibuf); - se->ibuf= 0; - } - } - - if (se->ibuf == NULL) { - se1 = do_build_seq_recursively_impl( - seq->seq1, cfra_left); - se2 = do_build_seq_recursively_impl( - seq->seq1, cfra_right); - - if((se1 && se1->ibuf && se1->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - - if (!se1 || !se2) { - make_black_ibuf(se->ibuf); - } else { - sh = get_sequence_effect(seq); - - sh.execute(seq, cfra, - f_cfra - (float) cfra_left, - f_cfra - (float) cfra_left, - se->ibuf->x, se->ibuf->y, - se1->ibuf, se2->ibuf, 0, se->ibuf); - } - } - - } - - /* caller expects this to be referenced, so do it! */ - if (se->ibuf) { - IMB_cache_limiter_insert(se->ibuf); - IMB_cache_limiter_ref(se->ibuf); - IMB_cache_limiter_touch(se->ibuf); - } - - /* children are no longer needed */ - if (se1 && se1->ibuf) - IMB_cache_limiter_unref(se1->ibuf); - if (se2 && se2->ibuf) - IMB_cache_limiter_unref(se2->ibuf); - - return se; -} - -/* - * 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 - * - */ - -static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra) -{ - if (seq->type == SEQ_SPEED) { - return do_handle_speed_effect(seq, cfra); - } else { - return do_build_seq_recursively_impl(seq, cfra); - } -} - -static TStripElem* do_build_seq_array_recursively( - ListBase *seqbasep, int cfra, int chanshown) -{ - Sequence* seq_arr[MAXSEQ+1]; - int count; - int i; - TStripElem* se = 0; - - count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr); - - if (!count) { - return 0; - } - - se = give_tstripelem(seq_arr[count - 1], cfra); - - if (!se) { - return 0; - } - - test_and_auto_discard_ibuf(se); - - if (se->ibuf_comp != 0) { - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - return se; - } - - - if(count == 1) { - se = do_build_seq_recursively(seq_arr[0], cfra); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } - return se; - } - - - for (i = count - 1; i >= 0; i--) { - int early_out; - Sequence * seq = seq_arr[i]; - struct SeqEffectHandle sh; - - se = give_tstripelem(seq, cfra); - - test_and_auto_discard_ibuf(se); - - if (se->ibuf_comp != 0) { - break; - } - if (seq->blend_mode == SEQ_BLEND_REPLACE) { - do_build_seq_recursively(seq, cfra); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - } - break; - } - - sh = get_sequence_blend(seq); - - seq->facf0 = seq->facf1 = 1.0; - - if(seq->ipo && seq->ipo->curve.first) { - do_seq_ipo(seq, cfra); - } - - if( G.scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1; - - seq->facf0 *= seq->blend_opacity / 100.0; - seq->facf1 *= seq->blend_opacity / 100.0; - - early_out = sh.early_out(seq, seq->facf0, seq->facf1); - - switch (early_out) { - case -1: - case 2: - do_build_seq_recursively(seq, cfra); - if (se->ibuf) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } else { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - } - break; - case 1: - if (i == 0) { - se->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - IMB_cache_limiter_insert(se->ibuf_comp); - IMB_cache_limiter_ref(se->ibuf_comp); - IMB_cache_limiter_touch(se->ibuf_comp); - } - break; - case 0: - do_build_seq_recursively(seq, cfra); - if (!se->ibuf) { - se->ibuf = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - } - if (i == 0) { - se->ibuf_comp = se->ibuf; - IMB_refImBuf(se->ibuf_comp); - } - break; - } - - if (se->ibuf_comp) { - break; - } - } - - 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); - - int early_out = sh.early_out(seq, seq->facf0, seq->facf1); - switch (early_out) { - case 0: { - int x= se2->ibuf->x; - int y= se2->ibuf->y; - int swap_input = FALSE; - - if (se1->ibuf_comp->rect_float || - se2->ibuf->rect_float) { - se2->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rectfloat, 0); - } else { - se2->ibuf_comp = IMB_allocImBuf( - (short)seqrectx, (short)seqrecty, - 32, IB_rect, 0); - } - - - if (!se1->ibuf_comp->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se1->ibuf_comp); - } - if (!se2->ibuf->rect_float && - se2->ibuf_comp->rect_float) { - IMB_float_from_rect(se2->ibuf); - } - - if (!se1->ibuf_comp->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se1->ibuf_comp); - } - if (!se2->ibuf->rect && - !se2->ibuf_comp->rect_float) { - IMB_rect_from_float(se2->ibuf); - } - - /* bad hack, to fix crazy input ordering of - those two effects */ - - if (seq->blend_mode == SEQ_ALPHAOVER || - seq->blend_mode == SEQ_ALPHAUNDER || - seq->blend_mode == SEQ_OVERDROP) { - swap_input = TRUE; - } - - if (swap_input) { - sh.execute(seq, cfra, - seq->facf0, seq->facf1, x, y, - se2->ibuf, se1->ibuf_comp, 0, - se2->ibuf_comp); - } else { - sh.execute(seq, cfra, - seq->facf0, seq->facf1, x, y, - se1->ibuf_comp, se2->ibuf, 0, - se2->ibuf_comp); - } - - IMB_cache_limiter_insert(se2->ibuf_comp); - IMB_cache_limiter_ref(se2->ibuf_comp); - IMB_cache_limiter_touch(se2->ibuf_comp); - - IMB_cache_limiter_unref(se1->ibuf_comp); - IMB_cache_limiter_unref(se2->ibuf); - - break; - } - case 1: { - se2->ibuf_comp = se1->ibuf; - IMB_refImBuf(se2->ibuf_comp); - - break; - } - } - se = se2; - } - - return se; -} - -/* - * returned ImBuf is refed! - * you have to unref after usage! - */ - -static ImBuf *give_ibuf_seq_impl(int rectx, int recty, int cfra, int chanshown) -{ - Editing *ed; - int count; - ListBase *seqbasep; - TStripElem *se; - - ed= G.scene->ed; - if(ed==0) return 0; - - count = BLI_countlist(&ed->metastack); - if((chanshown < 0) && (count > 0)) { - count = MAX2(count + chanshown, 0); - seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep; - } else { - seqbasep= ed->seqbasep; - } - - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_array_recursively(seqbasep, cfra, chanshown); - - if(!se) { - return 0; - } - - return se->ibuf_comp; -} - -ImBuf *give_ibuf_seq_direct(int rectx, int recty, int cfra, - Sequence * seq) -{ - TStripElem* se; - - seqrectx= rectx; /* bad bad global! */ - seqrecty= recty; - - se = do_build_seq_recursively(seq, cfra); - - if(!se) { - return 0; - } - - if (se->ibuf) { - IMB_cache_limiter_unref(se->ibuf); - } - - return se->ibuf; -} - -ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) -{ - ImBuf* i = give_ibuf_seq_impl(rectx, recty, cfra, chanshown); - - if (i) { - IMB_cache_limiter_unref(i); - } - return i; -} - -/* check used when we need to change seq->blend_mode but not to effect or audio strips */ -int seq_can_blend(Sequence *seq) -{ - if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { - return 1; - } else { - return 0; - } -} - -/* threading api */ - -static ListBase running_threads; -static ListBase prefetch_wait; -static ListBase prefetch_done; - -static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t wakeup_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; - -static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t prefetch_ready_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_last_given_monoton_cfra = 0; -static int monoton_cfra = 0; - -typedef struct PrefetchThread { - struct PrefetchThread *next, *prev; - struct PrefetchQueueElem *current; - pthread_t pthread; - int running; -} PrefetchThread; - -typedef struct PrefetchQueueElem { - struct PrefetchQueueElem *next, *prev; - - int rectx; - int recty; - int cfra; - int chanshown; - - int monoton_cfra; - - struct ImBuf * ibuf; -} PrefetchQueueElem; - -static void * seq_prefetch_thread(void * This_) -{ - PrefetchThread * This = This_; - - while (!seq_thread_shutdown) { - PrefetchQueueElem * e; - int s_last; - - pthread_mutex_lock(&queue_lock); - e = prefetch_wait.first; - if (e) { - BLI_remlink(&prefetch_wait, e); - } - s_last = seq_last_given_monoton_cfra; - - This->current = e; - - pthread_mutex_unlock(&queue_lock); - - if (!e) { - pthread_mutex_lock(&prefetch_ready_lock); - - This->running = FALSE; - - pthread_cond_signal(&prefetch_ready_cond); - pthread_mutex_unlock(&prefetch_ready_lock); - - pthread_mutex_lock(&wakeup_lock); - if (!seq_thread_shutdown) { - pthread_cond_wait(&wakeup_cond, &wakeup_lock); - } - pthread_mutex_unlock(&wakeup_lock); - continue; - } - - This->running = TRUE; - - if (e->cfra >= s_last) { - e->ibuf = give_ibuf_seq_impl( - e->rectx, e->recty, e->cfra, e->chanshown); - } - - pthread_mutex_lock(&queue_lock); - - BLI_addtail(&prefetch_done, e); - - for (e = prefetch_wait.first; e; e = e->next) { - if (s_last > e->monoton_cfra) { - BLI_remlink(&prefetch_wait, e); - MEM_freeN(e); - } - } - - for (e = prefetch_done.first; e; e = e->next) { - if (s_last > e->monoton_cfra) { - if (e->ibuf) { - IMB_cache_limiter_unref(e->ibuf); - } - BLI_remlink(&prefetch_done, e); - MEM_freeN(e); - } - } - - pthread_mutex_unlock(&queue_lock); - - pthread_mutex_lock(&frame_done_lock); - pthread_cond_signal(&frame_done_cond); - pthread_mutex_unlock(&frame_done_lock); - } - return 0; -} - -void seq_start_threads() -{ - int i; - - running_threads.first = running_threads.last = NULL; - prefetch_wait.first = prefetch_wait.last = NULL; - prefetch_done.first = prefetch_done.last = NULL; - - seq_thread_shutdown = FALSE; - seq_last_given_monoton_cfra = monoton_cfra = 0; - - /* since global structures are modified during the processing - of one frame, only one render thread is currently possible... - - (but we code, in the hope, that we can remove this restriction - soon...) - */ - - fprintf(stderr, "SEQ-THREAD: seq_start_threads\n"); - - for (i = 0; i < 1; i++) { - PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), - "prefetch_thread"); - t->running = TRUE; - BLI_addtail(&running_threads, t); - - pthread_create(&t->pthread, NULL, seq_prefetch_thread, t); - } - - /* init malloc mutex */ - BLI_init_threads(0, 0, 0); -} - -void seq_stop_threads() -{ - PrefetchThread *tslot; - PrefetchQueueElem * e; - - fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n"); - - if (seq_thread_shutdown) { - fprintf(stderr, "SEQ-THREAD: ... already stopped\n"); - return; - } - - pthread_mutex_lock(&wakeup_lock); - - seq_thread_shutdown = TRUE; - - pthread_cond_broadcast(&wakeup_cond); - pthread_mutex_unlock(&wakeup_lock); - - for(tslot = running_threads.first; tslot; tslot= tslot->next) { - pthread_join(tslot->pthread, NULL); - } - - - for (e = prefetch_wait.first; e; e = e->next) { - BLI_remlink(&prefetch_wait, e); - MEM_freeN(e); - } - - for (e = prefetch_done.first; e; e = e->next) { - if (e->ibuf) { - IMB_cache_limiter_unref(e->ibuf); - } - BLI_remlink(&prefetch_done, e); - MEM_freeN(e); - } - - BLI_freelistN(&running_threads); - - /* deinit malloc mutex */ - BLI_end_threads(0); -} - -void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown) -{ - PrefetchQueueElem * e; - if (seq_thread_shutdown) { - return; - } - - e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem"); - e->rectx = rectx; - e->recty = recty; - e->cfra = cfra; - e->chanshown = chanshown; - e->monoton_cfra = monoton_cfra++; - - pthread_mutex_lock(&queue_lock); - BLI_addtail(&prefetch_wait, e); - pthread_mutex_unlock(&queue_lock); - - pthread_mutex_lock(&wakeup_lock); - pthread_cond_signal(&wakeup_cond); - pthread_mutex_unlock(&wakeup_lock); -} - -void seq_wait_for_prefetch_ready() -{ - PrefetchThread *tslot; - - if (seq_thread_shutdown) { - return; - } - - fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n"); - - pthread_mutex_lock(&prefetch_ready_lock); - - for(;;) { - for(tslot = running_threads.first; tslot; tslot= tslot->next) { - if (tslot->running) { - break; - } - } - if (!tslot) { - break; - } - pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock); - } - - pthread_mutex_unlock(&prefetch_ready_lock); - - fprintf(stderr, "SEQ-THREAD: prefetch done\n"); -} - -ImBuf * give_ibuf_seq_threaded(int rectx, int recty, int cfra, int chanshown) -{ - PrefetchQueueElem * e = 0; - int found_something = FALSE; - - if (seq_thread_shutdown) { - return give_ibuf_seq(rectx, recty, cfra, chanshown); - } - - while (!e) { - int success = FALSE; - pthread_mutex_lock(&queue_lock); - - for (e = prefetch_done.first; e; e = e->next) { - if (cfra == e->cfra && - chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty) { - success = TRUE; - found_something = TRUE; - break; - } - } - - if (!e) { - for (e = prefetch_wait.first; e; e = e->next) { - if (cfra == e->cfra && - chanshown == e->chanshown && - rectx == e->rectx && - recty == e->recty) { - found_something = TRUE; - break; - } - } - } - - if (!e) { - PrefetchThread *tslot; - - for(tslot = running_threads.first; - tslot; tslot= tslot->next) { - if (tslot->current && - cfra == tslot->current->cfra && - chanshown == tslot->current->chanshown && - rectx == tslot->current->rectx && - recty == tslot->current->recty) { - found_something = TRUE; - break; - } - } - } - - /* e->ibuf is unrefed by render thread on next round. */ - - if (e) { - seq_last_given_monoton_cfra = e->monoton_cfra; - } - - pthread_mutex_unlock(&queue_lock); - - if (!success) { - e = NULL; - - if (!found_something) { - fprintf(stderr, - "SEQ-THREAD: Requested frame " - "not in queue ???\n"); - break; - } - pthread_mutex_lock(&frame_done_lock); - pthread_cond_wait(&frame_done_cond, &frame_done_lock); - pthread_mutex_unlock(&frame_done_lock); - } - } - - return e ? e->ibuf : 0; -} - -/* 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) { - IMB_free_anim(seq->anim); - seq->anim = 0; - } -} - -void free_imbuf_seq_except(int cfra) -{ - Editing *ed= G.scene->ed; - Sequence *seq; - TStripElem *se; - int a; - - if(ed==0) return; - - WHILE_SEQ(&ed->seqbase) { - 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); - } - } - END_SEQ -} - -void free_imbuf_seq() -{ - Editing *ed= G.scene->ed; - Sequence *seq; - TStripElem *se; - int a; - - if(ed==0) return; - - WHILE_SEQ(&ed->seqbase) { - 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) - free_anim_seq(seq); - if(seq->type==SEQ_SPEED) { - sequence_effect_speed_rebuild_map(seq, 1); - } - } - } - END_SEQ -} - -void free_imbuf_seq_with_ipo(struct Ipo *ipo) -{ - /* force update of all sequences with this ipo, on ipo changes */ - Editing *ed= G.scene->ed; - Sequence *seq; - - if(ed==0) return; - - WHILE_SEQ(&ed->seqbase) { - if(seq->ipo == ipo) { - update_changed_seq_and_deps(seq, 0, 1); - if(seq->type == SEQ_SPEED) { - sequence_effect_speed_rebuild_map(seq, 1); - } - } - } - END_SEQ -} - -static int update_changed_seq_recurs(Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) -{ - Sequence *subseq; - int a, free_imbuf = 0; - TStripElem *se; - - /* recurs downwards to see if this seq depends on the changed seq */ - - if(seq == NULL) - return 0; - - if(seq == changed_seq) - free_imbuf = 1; - - for(subseq=seq->seqbase.first; subseq; subseq=subseq->next) - if(update_changed_seq_recurs(subseq, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - - if(seq->seq1) - if(update_changed_seq_recurs(seq->seq1, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - if(seq->seq2 && (seq->seq2 != seq->seq1)) - if(update_changed_seq_recurs(seq->seq2, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) - if(update_changed_seq_recurs(seq->seq3, changed_seq, len_change, ibuf_change)) - free_imbuf = TRUE; - - if(free_imbuf) { - if(ibuf_change) { - se= seq->strip->tstripdata; - if (se) { - for(a=0; a<seq->len; a++, se++) - free_imbuf_strip_elem(se); - } - - if(seq->type == SEQ_MOVIE) - free_anim_seq(seq); - if(seq->type == SEQ_SPEED) { - sequence_effect_speed_rebuild_map(seq, 1); - } - } - - if(len_change) - calc_sequence(seq); - } - - return free_imbuf; -} - -void update_changed_seq_and_deps(Sequence *changed_seq, int len_change, int ibuf_change) -{ - Editing *ed= G.scene->ed; - Sequence *seq; - - if (!ed) return; - - for (seq=ed->seqbase.first; seq; seq=seq->next) - update_changed_seq_recurs(seq, changed_seq, len_change, ibuf_change); -} - -/* bad levell call... */ -void do_render_seq(RenderResult *rr, int cfra) -{ - ImBuf *ibuf; - - G.f |= G_PLAYANIM; /* waitcursor patch */ - - ibuf= give_ibuf_seq(rr->rectx, rr->recty, cfra, 0); - - if(ibuf) { - if(ibuf->rect_float) { - if (!rr->rectf) - rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); - - memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); - - /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 - can hang around when sequence render has rendered a 32 bits one before */ - if(rr->rect32) { - MEM_freeN(rr->rect32); - rr->rect32= NULL; - } - } - else if(ibuf->rect) { - if (!rr->rect32) - rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); - - memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty); - - /* if (ibuf->zbuf) { */ - /* if (R.rectz) freeN(R.rectz); */ - /* R.rectz = BLI_dupallocN(ibuf->zbuf); */ - /* } */ - } - - /* Let the cache limitor take care of this (schlaile) */ - /* While render let's keep all memory available for render - (ton) - At least if free memory is tight... - This can make a big difference in encoding speed - (it is around 4 times(!) faster, if we do not waste time - on freeing _all_ buffers every time on long timelines...) - (schlaile) - */ - { - uintptr_t mem_in_use; - uintptr_t mmap_in_use; - uintptr_t max; - - mem_in_use= MEM_get_memory_in_use(); - mmap_in_use= MEM_get_mapped_memory_in_use(); - max = MEM_CacheLimiter_get_maximum(); - - if (max != 0 && mem_in_use + mmap_in_use > max) { - fprintf(stderr, "Memory in use > maximum memory\n"); - fprintf(stderr, "Cleaning up, please wait...\n" - "If this happens very often,\n" - "consider " - "raising the memcache limit in the " - "user preferences.\n"); - free_imbuf_seq(); - } - } - } - else { - /* render result is delivered empty in most cases, nevertheless we handle all cases */ - if (rr->rectf) - memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty); - else if (rr->rect32) - memset(rr->rect32, 0, 4*rr->rectx*rr->recty); - else - rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); - } - - G.f &= ~G_PLAYANIM; - -} |