2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2011-10-10 09:38:02 +00:00
|
|
|
* $Id$
|
2009-01-12 19:02:08 +00:00
|
|
|
*
|
|
|
|
* ***** 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-01-12 19:02:08 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* - Blender Foundation, 2003-2009
|
|
|
|
* - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2011-02-27 20:40:57 +00:00
|
|
|
/** \file blender/blenkernel/intern/sequencer.c
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-11-19 03:21:37 +00:00
|
|
|
#include <stddef.h>
|
2008-12-15 05:21:44 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2009-01-12 19:02:08 +00:00
|
|
|
#include <math.h>
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
2009-08-02 23:02:59 +00:00
|
|
|
#include "MEM_CacheLimiterC-Api.h"
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
#include "DNA_sequence_types.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2009-11-22 20:22:35 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2010-03-08 21:33:51 +00:00
|
|
|
#include "DNA_object_types.h"
|
2010-08-04 04:01:27 +00:00
|
|
|
#include "DNA_sound_types.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_math.h"
|
|
|
|
#include "BLI_fileops.h"
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
#include "BLI_path_util.h"
|
|
|
|
#include "BLI_string.h"
|
|
|
|
#include "BLI_threads.h"
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
2010-07-07 16:17:18 +00:00
|
|
|
#include "BKE_animsys.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_image.h"
|
|
|
|
#include "BKE_main.h"
|
2009-12-13 14:56:45 +00:00
|
|
|
#include "BKE_sequencer.h"
|
2009-11-22 20:22:35 +00:00
|
|
|
#include "BKE_fcurve.h"
|
2010-03-08 21:33:51 +00:00
|
|
|
#include "BKE_scene.h"
|
2009-11-22 20:22:35 +00:00
|
|
|
#include "RNA_access.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
2009-11-22 20:49:13 +00:00
|
|
|
#include "RE_pipeline.h"
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2009-12-13 17:46:30 +00:00
|
|
|
#include <pthread.h>
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
#include "IMB_imbuf.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
#include "IMB_imbuf_types.h"
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2009-08-09 21:16:39 +00:00
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_sound.h"
|
2011-06-23 09:27:56 +00:00
|
|
|
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
# include "AUD_C-API.h"
|
|
|
|
#endif
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2011-05-16 17:14:47 +00:00
|
|
|
static ImBuf* seq_render_strip_stack(
|
|
|
|
SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
|
|
|
|
|
|
|
|
static ImBuf * seq_render_strip(
|
|
|
|
SeqRenderData context, Sequence * seq, float cfra);
|
|
|
|
|
|
|
|
static void seq_free_animdata(Scene *scene, Sequence *seq);
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* **** XXX ******** */
|
2009-12-17 23:29:11 +00:00
|
|
|
#define SELECT 1
|
2009-12-17 16:28:45 +00:00
|
|
|
ListBase seqbase_clipboard;
|
|
|
|
int seqbase_clipboard_frame;
|
2010-03-09 07:41:04 +00:00
|
|
|
SequencerDrawView sequencer_view3d_cb= NULL; /* NULL in background mode */
|
2010-03-08 20:08:04 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2009-10-19 10:07:19 +00:00
|
|
|
void printf_strip(Sequence *seq)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), (startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n",
|
|
|
|
seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine, seq->startdisp, seq->enddisp);
|
|
|
|
fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0));
|
|
|
|
}
|
|
|
|
|
2010-07-06 16:44:05 +00:00
|
|
|
int seqbase_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg)
|
2009-12-18 13:28:03 +00:00
|
|
|
{
|
|
|
|
Sequence *iseq;
|
|
|
|
for(iseq= seqbase->first; iseq; iseq= iseq->next) {
|
2010-07-06 16:44:05 +00:00
|
|
|
if(seq_recursive_apply(iseq, apply_func, arg) == -1)
|
|
|
|
return -1; /* bail out */
|
2009-12-18 13:28:03 +00:00
|
|
|
}
|
2010-07-06 16:44:05 +00:00
|
|
|
return 1;
|
2009-12-18 13:28:03 +00:00
|
|
|
}
|
|
|
|
|
2010-07-06 16:44:05 +00:00
|
|
|
int seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg)
|
2009-12-18 13:28:03 +00:00
|
|
|
{
|
2010-07-06 16:44:05 +00:00
|
|
|
int ret= apply_func(seq, arg);
|
|
|
|
|
|
|
|
if(ret == -1)
|
|
|
|
return -1; /* bail out */
|
|
|
|
|
|
|
|
if(ret && seq->seqbase.first)
|
|
|
|
ret = seqbase_recursive_apply(&seq->seqbase, apply_func, arg);
|
|
|
|
|
|
|
|
return ret;
|
2009-12-18 13:28:03 +00:00
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
/* **********************************************************************
|
|
|
|
alloc / free functions
|
|
|
|
********************************************************************** */
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
void new_tstripdata(Sequence *seq)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
if(seq->strip) {
|
|
|
|
seq->strip->len= seq->len;
|
|
|
|
}
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
/* free */
|
|
|
|
|
2009-09-14 16:52:06 +00:00
|
|
|
static void free_proxy_seq(Sequence *seq)
|
2009-06-08 20:08:19 +00:00
|
|
|
{
|
|
|
|
if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) {
|
|
|
|
IMB_free_anim(seq->strip->proxy->anim);
|
2011-02-13 10:52:18 +00:00
|
|
|
seq->strip->proxy->anim = NULL;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
void seq_free_strip(Strip *strip)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
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) {
|
2009-06-08 20:08:19 +00:00
|
|
|
if (strip->proxy->anim) {
|
|
|
|
IMB_free_anim(strip->proxy->anim);
|
|
|
|
}
|
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(strip);
|
|
|
|
}
|
|
|
|
|
2009-08-09 21:16:39 +00:00
|
|
|
void seq_free_sequence(Scene *scene, Sequence *seq)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
if(seq->strip) seq_free_strip(seq->strip);
|
|
|
|
|
|
|
|
if(seq->anim) IMB_free_anim(seq->anim);
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2009-07-08 17:41:45 +00:00
|
|
|
if (seq->type & SEQ_EFFECT) {
|
2008-12-15 05:21:44 +00:00
|
|
|
struct SeqEffectHandle sh = get_sequence_effect(seq);
|
|
|
|
|
|
|
|
sh.free(seq);
|
2009-07-08 17:41:45 +00:00
|
|
|
}
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2011-05-16 17:14:47 +00:00
|
|
|
if(seq->sound) {
|
|
|
|
((ID *)seq->sound)->us--;
|
|
|
|
}
|
|
|
|
|
2009-12-17 16:28:45 +00:00
|
|
|
/* clipboard has no scene and will never have a sound handle or be active */
|
|
|
|
if(scene) {
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
|
|
|
|
if (ed->act_seq==seq)
|
|
|
|
ed->act_seq= NULL;
|
|
|
|
|
2011-02-22 16:32:05 +00:00
|
|
|
if(seq->scene_sound && ELEM(seq->type, SEQ_SOUND, SEQ_SCENE))
|
2010-02-07 23:41:17 +00:00
|
|
|
sound_remove_scene_sound(scene, seq->scene_sound);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2010-07-13 09:31:28 +00:00
|
|
|
seq_free_animdata(scene, seq);
|
|
|
|
}
|
2010-07-03 21:13:08 +00:00
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
MEM_freeN(seq);
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
|
|
|
|
{
|
|
|
|
Sequence *iseq;
|
|
|
|
|
|
|
|
for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
|
|
|
|
seq_free_sequence_recurse(scene, iseq);
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_free_sequence(scene, seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-28 22:36:34 +00:00
|
|
|
Editing *seq_give_editing(Scene *scene, int alloc)
|
|
|
|
{
|
|
|
|
if (scene->ed == NULL && alloc) {
|
|
|
|
Editing *ed;
|
|
|
|
|
|
|
|
ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq");
|
|
|
|
ed->seqbasep= &ed->seqbase;
|
|
|
|
}
|
|
|
|
return scene->ed;
|
|
|
|
}
|
|
|
|
|
2011-04-01 09:00:16 +00:00
|
|
|
static void seq_free_clipboard_recursive(Sequence *seq_parent)
|
|
|
|
{
|
|
|
|
Sequence *seq, *nseq;
|
|
|
|
|
|
|
|
for(seq= seq_parent->seqbase.first; seq; seq= nseq) {
|
|
|
|
nseq= seq->next;
|
|
|
|
seq_free_clipboard_recursive(seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
seq_free_sequence(NULL, seq_parent);
|
|
|
|
}
|
|
|
|
|
2009-12-17 16:28:45 +00:00
|
|
|
void seq_free_clipboard(void)
|
2009-12-17 14:45:47 +00:00
|
|
|
{
|
|
|
|
Sequence *seq, *nseq;
|
|
|
|
|
2009-12-17 16:28:45 +00:00
|
|
|
for(seq= seqbase_clipboard.first; seq; seq= nseq) {
|
2009-12-17 14:45:47 +00:00
|
|
|
nseq= seq->next;
|
2011-04-01 09:00:16 +00:00
|
|
|
seq_free_clipboard_recursive(seq);
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
2009-12-17 16:28:45 +00:00
|
|
|
seqbase_clipboard.first= seqbase_clipboard.last= NULL;
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
|
|
|
|
2009-08-09 21:16:39 +00:00
|
|
|
void seq_free_editing(Scene *scene)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
2009-08-09 21:16:39 +00:00
|
|
|
Editing *ed = scene->ed;
|
2008-12-15 05:21:44 +00:00
|
|
|
MetaStack *ms;
|
2009-12-18 13:28:03 +00:00
|
|
|
Sequence *seq;
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
if(ed==NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SEQ_BEGIN(ed, seq) {
|
2009-08-09 21:16:39 +00:00
|
|
|
seq_free_sequence(scene, seq);
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
SEQ_END
|
|
|
|
|
|
|
|
while((ms= ed->metastack.first)) {
|
|
|
|
BLI_remlink(&ed->metastack, ms);
|
|
|
|
MEM_freeN(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(ed);
|
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
/* **********************************************************************
|
|
|
|
* sequencer pipeline functions
|
|
|
|
********************************************************************** */
|
|
|
|
|
|
|
|
SeqRenderData seq_new_render_data(
|
|
|
|
struct Main * bmain, struct Scene * scene,
|
|
|
|
int rectx, int recty, int preview_render_size)
|
|
|
|
{
|
|
|
|
SeqRenderData rval;
|
|
|
|
|
|
|
|
rval.bmain = bmain;
|
|
|
|
rval.scene = scene;
|
|
|
|
rval.rectx = rectx;
|
|
|
|
rval.recty = recty;
|
|
|
|
rval.preview_render_size = preview_render_size;
|
|
|
|
rval.motion_blur_samples = 0;
|
|
|
|
rval.motion_blur_shutter = 0;
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
int seq_cmp_render_data(const SeqRenderData * a, const SeqRenderData * b)
|
2010-11-21 20:00:31 +00:00
|
|
|
{
|
|
|
|
if (a->preview_render_size < b->preview_render_size) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->preview_render_size > b->preview_render_size) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->rectx < b->rectx) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->rectx > b->rectx) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->recty < b->recty) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->recty > b->recty) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->bmain < b->bmain) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->bmain > b->bmain) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->scene < b->scene) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->scene > b->scene) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->motion_blur_shutter < b->motion_blur_shutter) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->motion_blur_shutter > b->motion_blur_shutter) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->motion_blur_samples < b->motion_blur_samples) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->motion_blur_samples > b->motion_blur_samples) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
unsigned int seq_hash_render_data(const SeqRenderData * a)
|
2010-11-21 20:00:31 +00:00
|
|
|
{
|
|
|
|
unsigned int rval = a->rectx + a->recty;
|
|
|
|
|
|
|
|
rval ^= a->preview_render_size;
|
|
|
|
rval ^= ((intptr_t) a->bmain) << 6;
|
|
|
|
rval ^= ((intptr_t) a->scene) << 6;
|
2011-03-30 16:11:16 +00:00
|
|
|
rval ^= (int) (a->motion_blur_shutter * 100.0f) << 10;
|
2010-11-21 20:00:31 +00:00
|
|
|
rval ^= a->motion_blur_samples << 24;
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
|
2011-01-02 19:00:32 +00:00
|
|
|
/* ************************* iterator ************************** */
|
2009-01-12 19:02:08 +00:00
|
|
|
/* *************** (replaces old WHILE_SEQ) ********************* */
|
|
|
|
/* **************** use now SEQ_BEGIN() SEQ_END ***************** */
|
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
/* sequence strip iterator:
|
|
|
|
* - builds a full array, recursively into meta strips */
|
|
|
|
|
|
|
|
static void seq_count(ListBase *seqbase, int *tot)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
for(seq=seqbase->first; seq; seq=seq->next) {
|
|
|
|
(*tot)++;
|
|
|
|
|
|
|
|
if(seq->seqbase.first)
|
|
|
|
seq_count(&seq->seqbase, tot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
for(seq=seqbase->first; seq; seq=seq->next) {
|
|
|
|
seq->depth= depth;
|
|
|
|
|
|
|
|
if(seq->seqbase.first)
|
|
|
|
seq_build_array(&seq->seqbase, array, depth+1);
|
|
|
|
|
|
|
|
**array= seq;
|
|
|
|
(*array)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
Sequence **array;
|
|
|
|
|
|
|
|
*seqarray= NULL;
|
|
|
|
*tot= 0;
|
|
|
|
|
|
|
|
if(ed == NULL)
|
|
|
|
return;
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if(use_pointer)
|
|
|
|
seq_count(ed->seqbasep, tot);
|
|
|
|
else
|
|
|
|
seq_count(&ed->seqbase, tot);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
if(*tot == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray");
|
2009-01-12 19:02:08 +00:00
|
|
|
if(use_pointer)
|
|
|
|
seq_build_array(ed->seqbasep, &array, 0);
|
|
|
|
else
|
|
|
|
seq_build_array(&ed->seqbase, &array, 0);
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
memset(iter, 0, sizeof(*iter));
|
2009-01-12 19:02:08 +00:00
|
|
|
seq_array(ed, &iter->array, &iter->tot, use_pointer);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
if(iter->tot) {
|
|
|
|
iter->cur= 0;
|
|
|
|
iter->seq= iter->array[iter->cur];
|
|
|
|
iter->valid= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_next(SeqIterator *iter)
|
|
|
|
{
|
|
|
|
if(++iter->cur < iter->tot)
|
|
|
|
iter->seq= iter->array[iter->cur];
|
|
|
|
else
|
|
|
|
iter->valid= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_end(SeqIterator *iter)
|
|
|
|
{
|
|
|
|
if(iter->array)
|
|
|
|
MEM_freeN(iter->array);
|
|
|
|
|
|
|
|
iter->valid= 0;
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
/*
|
|
|
|
**********************************************************************
|
|
|
|
* build_seqar
|
|
|
|
**********************************************************************
|
|
|
|
* Build a complete array of _all_ sequencies (including those
|
|
|
|
* in metastrips!)
|
|
|
|
**********************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void do_seq_count_cb(ListBase *seqbase, int *totseq,
|
2010-03-22 09:30:00 +00:00
|
|
|
int (*test_func)(Sequence * seq))
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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,
|
2010-03-22 09:30:00 +00:00
|
|
|
int (*test_func)(Sequence * seq))
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
seq= seqbase->first;
|
|
|
|
while(seq) {
|
|
|
|
int test = test_func(seq);
|
|
|
|
seq->depth= depth;
|
|
|
|
|
|
|
|
if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
|
2010-10-30 21:55:17 +00:00
|
|
|
do_build_seqar_cb(&seq->seqbase, seqar, depth+1, test_func);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
if (test & BUILD_SEQAR_COUNT_CURRENT) {
|
|
|
|
**seqar= seq;
|
|
|
|
(*seqar)++;
|
|
|
|
}
|
|
|
|
seq= seq->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq,
|
2010-03-22 09:30:00 +00:00
|
|
|
int (*test_func)(Sequence * seq))
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence **tseqar;
|
|
|
|
|
|
|
|
*totseq= 0;
|
|
|
|
do_seq_count_cb(seqbase, totseq, test_func);
|
|
|
|
|
|
|
|
if(*totseq==0) {
|
2010-10-30 21:55:17 +00:00
|
|
|
*seqar= NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
*seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
|
|
|
|
tseqar= *seqar;
|
|
|
|
|
|
|
|
do_build_seqar_cb(seqbase, seqar, 0, test_func);
|
|
|
|
*seqar= tseqar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
void calc_sequence_disp(Scene *scene, Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2011-07-26 13:56:31 +00:00
|
|
|
seq_update_sound_bounds(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-13 15:19:15 +00:00
|
|
|
static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
/* for sound we go over full meta tree to update bounds of the sound strips,
|
|
|
|
since sound is played outside of evaluating the imbufs, */
|
|
|
|
for(seq=metaseq->seqbase.first; seq; seq=seq->next) {
|
|
|
|
if(seq->type == SEQ_META) {
|
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
|
2010-07-13 15:19:15 +00:00
|
|
|
if(seq->scene_sound) {
|
|
|
|
int startofs = seq->startofs;
|
|
|
|
int endofs = seq->endofs;
|
|
|
|
if(seq->startofs + seq->start < metaseq->start + metaseq->startofs)
|
|
|
|
startofs = metaseq->start + metaseq->startofs - seq->start;
|
|
|
|
|
|
|
|
if(seq->start + seq->len - seq->endofs > metaseq->start + metaseq->len - metaseq->endofs)
|
|
|
|
endofs = seq->start + seq->len - metaseq->start - metaseq->len + metaseq->endofs;
|
|
|
|
sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, seq->start+seq->len - endofs, startofs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
void calc_sequence(Scene *scene, Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seqm;
|
|
|
|
int min, max;
|
|
|
|
|
|
|
|
/* check all metas recursively */
|
|
|
|
seqm= seq->seqbase.first;
|
|
|
|
while(seqm) {
|
2010-02-07 23:41:17 +00:00
|
|
|
if(seqm->seqbase.first) calc_sequence(scene, seqm);
|
2009-01-12 19:02:08 +00:00
|
|
|
seqm= seqm->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* effects and meta: automatic start and end */
|
|
|
|
|
|
|
|
if(seq->type & SEQ_EFFECT) {
|
|
|
|
/* pointers */
|
2010-10-30 21:55:17 +00:00
|
|
|
if(seq->seq2==NULL) seq->seq2= seq->seq1;
|
|
|
|
if(seq->seq3==NULL) seq->seq3= seq->seq1;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* 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);
|
2011-06-04 10:39:04 +00:00
|
|
|
/* we cant help if strips don't overlap, it wont give useful results.
|
|
|
|
* but at least ensure 'len' is never negative which causes bad bugs elsewhere. */
|
|
|
|
if(seq->enddisp < seq->startdisp) {
|
|
|
|
/* simple start/end swap */
|
|
|
|
seq->start= seq->enddisp;
|
|
|
|
seq->enddisp = seq->startdisp;
|
|
|
|
seq->startdisp= seq->start;
|
2011-06-07 18:34:33 +00:00
|
|
|
seq->flag |= SEQ_INVALID_EFFECT;
|
2011-06-04 10:39:04 +00:00
|
|
|
}
|
2011-06-07 18:34:33 +00:00
|
|
|
else {
|
|
|
|
seq->flag &= ~SEQ_INVALID_EFFECT;
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
seq->len= seq->enddisp - seq->startdisp;
|
2011-06-04 10:39:04 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->strip && seq->len!=seq->strip->len) {
|
|
|
|
new_tstripdata(seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(seq->type==SEQ_META) {
|
|
|
|
seqm= seq->seqbase.first;
|
|
|
|
if(seqm) {
|
2010-07-04 10:51:10 +00:00
|
|
|
min= MAXFRAME * 2;
|
|
|
|
max= -MAXFRAME * 2;
|
2009-01-12 19:02:08 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2010-07-13 15:19:15 +00:00
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-10 15:41:01 +00:00
|
|
|
/* note: caller should run calc_sequence(scene, seq) after */
|
2010-10-16 08:03:28 +00:00
|
|
|
void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
char str[FILE_MAXDIR+FILE_MAXFILE];
|
2010-12-29 12:27:03 +00:00
|
|
|
int prev_startdisp=0, prev_enddisp=0;
|
2010-05-08 16:36:28 +00:00
|
|
|
/* note: dont rename the strip, will break animation curves */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ELEM5(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META)==0) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-05-08 16:36:28 +00:00
|
|
|
if(lock_range) {
|
|
|
|
/* keep so we dont have to move the actual start and end points (only the data) */
|
|
|
|
calc_sequence_disp(scene, seq);
|
|
|
|
prev_startdisp= seq->startdisp;
|
|
|
|
prev_enddisp= seq->enddisp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
new_tstripdata(seq);
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ELEM3(seq->type, SEQ_SCENE, SEQ_META, SEQ_IMAGE)==0) {
|
2011-02-13 03:21:27 +00:00
|
|
|
BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name);
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_abs(str, G.main->name);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
switch(seq->type) {
|
|
|
|
case SEQ_IMAGE:
|
|
|
|
{
|
2009-01-12 19:02:08 +00:00
|
|
|
/* Hack? */
|
2010-04-29 21:46:25 +00:00
|
|
|
size_t olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
|
2010-05-08 16:36:28 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
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;
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SEQ_MOVIE:
|
2009-01-12 19:02:08 +00:00
|
|
|
if(seq->anim) IMB_free_anim(seq->anim);
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (!seq->anim) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
seq->len = IMB_anim_get_duration(seq->anim,
|
|
|
|
seq->strip->proxy ?
|
|
|
|
seq->strip->proxy->tc :
|
|
|
|
IMB_TC_RECORD_RUN);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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;
|
2011-08-14 14:43:11 +00:00
|
|
|
break;
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_SOUND:
|
2011-06-23 09:27:56 +00:00
|
|
|
#ifdef WITH_AUDASPACE
|
2010-11-09 11:26:00 +00:00
|
|
|
if(!seq->sound)
|
|
|
|
return;
|
2010-02-21 18:01:41 +00:00
|
|
|
seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS);
|
2009-01-12 19:02:08 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
seq->strip->len = seq->len;
|
2011-06-23 09:27:56 +00:00
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
|
|
|
case SEQ_SCENE:
|
|
|
|
{
|
2010-05-08 16:36:28 +00:00
|
|
|
/* 'seq->scenenr' should be replaced with something more reliable */
|
2010-10-16 08:03:28 +00:00
|
|
|
Scene * sce = G.main->scene.first;
|
2009-01-12 19:02:08 +00:00
|
|
|
int nr = 1;
|
|
|
|
|
|
|
|
while(sce) {
|
|
|
|
if(nr == seq->scenenr) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
sce= sce->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sce) {
|
|
|
|
seq->scene = sce;
|
|
|
|
}
|
2011-01-11 07:40:31 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
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;
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
free_proxy_seq(seq);
|
|
|
|
|
2010-05-08 16:36:28 +00:00
|
|
|
if(lock_range) {
|
|
|
|
seq_tx_set_final_left(seq, prev_startdisp);
|
|
|
|
seq_tx_set_final_right(seq, prev_enddisp);
|
|
|
|
seq_single_fix(seq);
|
|
|
|
}
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void sort_seq(Scene *scene)
|
|
|
|
{
|
|
|
|
/* all strips together per kind, and in order of y location ("machine") */
|
|
|
|
ListBase seqbase, effbase;
|
2009-01-28 22:36:34 +00:00
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
2009-01-12 19:02:08 +00:00
|
|
|
Sequence *seq, *seqt;
|
|
|
|
|
2009-01-28 22:36:34 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if(ed==NULL) return;
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
seqbase.first= seqbase.last= NULL;
|
|
|
|
effbase.first= effbase.last= NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2011-02-13 10:52:18 +00:00
|
|
|
if(seqt==NULL) BLI_addtail(&effbase, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
seqt= seqbase.first;
|
|
|
|
while(seqt) {
|
|
|
|
if(seqt->machine>=seq->machine) {
|
|
|
|
BLI_insertlinkbefore(&seqbase, seqt, seq);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
seqt= seqt->next;
|
|
|
|
}
|
2011-02-13 10:52:18 +00:00
|
|
|
if(seqt==NULL) BLI_addtail(&seqbase, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
BLI_movelisttolist(&seqbase, &effbase);
|
2009-01-12 19:02:08 +00:00
|
|
|
*(ed->seqbasep)= seqbase;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-18 13:28:03 +00:00
|
|
|
static int clear_scene_in_allseqs_cb(Sequence *seq, void *arg_pt)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2009-12-18 13:28:03 +00:00
|
|
|
if(seq->scene==(Scene *)arg_pt)
|
|
|
|
seq->scene= NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-08-13 14:23:44 +00:00
|
|
|
void clear_scene_in_allseqs(Main *bmain, Scene *scene)
|
2009-12-18 13:28:03 +00:00
|
|
|
{
|
|
|
|
Scene *scene_iter;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2009-12-18 13:28:03 +00:00
|
|
|
/* when a scene is deleted: test all seqs */
|
2010-08-13 14:23:44 +00:00
|
|
|
for(scene_iter= bmain->scene.first; scene_iter; scene_iter= scene_iter->id.next) {
|
2009-12-18 13:28:03 +00:00
|
|
|
if(scene_iter != scene && scene_iter->ed) {
|
|
|
|
seqbase_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-16 17:58:50 +00:00
|
|
|
typedef struct SeqUniqueInfo {
|
|
|
|
Sequence *seq;
|
|
|
|
char name_src[32];
|
|
|
|
char name_dest[32];
|
|
|
|
int count;
|
|
|
|
int match;
|
|
|
|
} SeqUniqueInfo;
|
|
|
|
|
|
|
|
/*
|
|
|
|
static void seqbase_unique_name(ListBase *seqbasep, Sequence *seq)
|
|
|
|
{
|
2011-04-21 15:53:30 +00:00
|
|
|
BLI_uniquename(seqbasep, seq, "Sequence", '.', offsetof(Sequence, name), SEQ_NAME_MAXSTR);
|
2010-02-16 17:58:50 +00:00
|
|
|
}*/
|
|
|
|
|
|
|
|
static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
for(seq=seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if (sui->seq != seq && strcmp(sui->name_dest, seq->name+2)==0) {
|
2010-07-14 12:16:23 +00:00
|
|
|
sprintf(sui->name_dest, "%.17s.%03d", sui->name_src, sui->count++); /*24 - 2 for prefix, -1 for \0 */
|
2010-02-16 17:58:50 +00:00
|
|
|
sui->match= 1; /* be sure to re-scan */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int seqbase_unique_name_recursive_cb(Sequence *seq, void *arg_pt)
|
|
|
|
{
|
|
|
|
if(seq->seqbase.first)
|
|
|
|
seqbase_unique_name(&seq->seqbase, (SeqUniqueInfo *)arg_pt);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq)
|
|
|
|
{
|
|
|
|
SeqUniqueInfo sui;
|
|
|
|
char *dot;
|
|
|
|
sui.seq= seq;
|
|
|
|
strcpy(sui.name_src, seq->name+2);
|
|
|
|
strcpy(sui.name_dest, seq->name+2);
|
|
|
|
|
2010-07-14 12:16:23 +00:00
|
|
|
sui.count= 1;
|
|
|
|
sui.match= 1; /* assume the worst to start the loop */
|
|
|
|
|
2010-02-16 17:58:50 +00:00
|
|
|
/* Strip off the suffix */
|
2010-07-14 12:16:23 +00:00
|
|
|
if ((dot=strrchr(sui.name_src, '.'))) {
|
2010-02-16 17:58:50 +00:00
|
|
|
*dot= '\0';
|
2010-07-14 12:16:23 +00:00
|
|
|
dot++;
|
2010-02-16 17:58:50 +00:00
|
|
|
|
2010-07-14 12:16:23 +00:00
|
|
|
if(*dot)
|
|
|
|
sui.count= atoi(dot) + 1;
|
|
|
|
}
|
2010-02-16 17:58:50 +00:00
|
|
|
|
|
|
|
while(sui.match) {
|
|
|
|
sui.match= 0;
|
|
|
|
seqbase_unique_name(seqbasep, &sui);
|
|
|
|
seqbase_recursive_apply(seqbasep, seqbase_unique_name_recursive_cb, &sui);
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(seq->name+2, sui.name_dest);
|
|
|
|
}
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
static const char *give_seqname_by_type(int type)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
case SEQ_META: return "Meta";
|
|
|
|
case SEQ_IMAGE: return "Image";
|
|
|
|
case SEQ_SCENE: return "Scene";
|
|
|
|
case SEQ_MOVIE: return "Movie";
|
2009-08-09 21:16:39 +00:00
|
|
|
case SEQ_SOUND: return "Audio";
|
2009-01-12 19:02:08 +00:00
|
|
|
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";
|
2010-04-25 15:39:04 +00:00
|
|
|
case SEQ_MULTICAM: return "Multicam";
|
2011-05-16 17:14:47 +00:00
|
|
|
case SEQ_ADJUSTMENT: return "Adjustment";
|
2009-01-12 19:02:08 +00:00
|
|
|
case SEQ_SPEED: return "Speed";
|
|
|
|
default:
|
2010-10-30 21:55:17 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-03 17:05:21 +00:00
|
|
|
const char *give_seqname(Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-12-03 17:05:21 +00:00
|
|
|
const char *name = give_seqname_by_type(seq->type);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) return;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
mul= (int)(256.0f * fmul);
|
2009-01-12 19:02:08 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static float give_stripelem_index(Sequence *seq, float cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-07-23 16:57:11 +00:00
|
|
|
float nr;
|
2010-10-30 21:55:17 +00:00
|
|
|
int sta = seq->start;
|
|
|
|
int end = seq->start+seq->len-1;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-05-17 18:37:44 +00:00
|
|
|
if (seq->type & SEQ_EFFECT) {
|
|
|
|
end = seq->enddisp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(end < sta) {
|
|
|
|
return -1;
|
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if(seq->flag&SEQ_REVERSE_FRAMES) {
|
|
|
|
/*reverse frame in this sequence */
|
2011-05-17 18:37:44 +00:00
|
|
|
if(cfra <= sta) nr= end - sta;
|
2010-10-30 21:55:17 +00:00
|
|
|
else if(cfra >= end) nr= 0;
|
|
|
|
else nr= end - cfra;
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
2010-10-30 21:55:17 +00:00
|
|
|
if(cfra <= sta) nr= 0;
|
2011-05-17 18:37:44 +00:00
|
|
|
else if(cfra >= end) nr= end - sta;
|
2010-10-30 21:55:17 +00:00
|
|
|
else nr= cfra - sta;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if (seq->strobe < 1.0f) seq->strobe = 1.0f;
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if (seq->strobe > 1.0f) {
|
2011-04-02 02:08:33 +00:00
|
|
|
nr -= fmodf((double)nr, (double)seq->strobe);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nr;
|
|
|
|
}
|
|
|
|
|
|
|
|
StripElem *give_stripelem(Sequence *seq, int cfra)
|
|
|
|
{
|
2010-01-18 11:22:32 +00:00
|
|
|
StripElem *se= seq->strip->stripdata;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-05-16 17:54:55 +00:00
|
|
|
if(seq->type == SEQ_IMAGE) { /* only
|
|
|
|
IMAGE strips use the whole array,
|
|
|
|
MOVIE strips use only
|
|
|
|
the first element, all other strips
|
|
|
|
don't use this... */
|
2010-07-23 16:57:11 +00:00
|
|
|
int nr = (int) give_stripelem_index(seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
if (nr == -1 || se == NULL) return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-01-18 11:22:32 +00:00
|
|
|
se += nr + seq->anim_startofs;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
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(Scene *scene, int cfra)
|
|
|
|
{
|
2009-01-28 22:36:34 +00:00
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
|
|
|
Sequence *seq_arr[MAXSEQ+1];
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2009-01-28 22:36:34 +00:00
|
|
|
if(ed==NULL) return 0;
|
|
|
|
return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int video_seq_is_rendered(Sequence * seq)
|
|
|
|
{
|
2010-10-30 21:55:17 +00:00
|
|
|
return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_SOUND);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)) {
|
2011-05-16 17:14:47 +00:00
|
|
|
if (b == 0) {
|
|
|
|
b = MAXSEQ;
|
|
|
|
}
|
|
|
|
for (; b > 0; b--) {
|
|
|
|
if (video_seq_is_rendered(seq_arr[b])) {
|
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
chanshown = b;
|
|
|
|
|
|
|
|
for (;b > 0; b--) {
|
|
|
|
if (video_seq_is_rendered(seq_arr[b])) {
|
|
|
|
if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-12 10:30:29 +00:00
|
|
|
for (;b <= chanshown && b >= 0; b++) {
|
2009-01-12 19:02:08 +00:00
|
|
|
if (video_seq_is_rendered(seq_arr[b])) {
|
|
|
|
seq_arr_out[cnt++] = seq_arr[b];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cnt;
|
|
|
|
}
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* **********************************************************************
|
|
|
|
proxy management
|
|
|
|
********************************************************************** */
|
|
|
|
|
|
|
|
#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
static IMB_Proxy_Size seq_rendersize_to_proxysize(int size)
|
|
|
|
{
|
|
|
|
if (size >= 100) {
|
|
|
|
return IMB_PROXY_NONE;
|
|
|
|
}
|
|
|
|
if (size >= 99) {
|
|
|
|
return IMB_PROXY_100;
|
|
|
|
}
|
|
|
|
if (size >= 75) {
|
|
|
|
return IMB_PROXY_75;
|
|
|
|
}
|
|
|
|
if (size >= 50) {
|
|
|
|
return IMB_PROXY_50;
|
|
|
|
}
|
|
|
|
return IMB_PROXY_25;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_open_anim_file(Sequence * seq)
|
|
|
|
{
|
|
|
|
char name[FILE_MAXDIR+FILE_MAXFILE];
|
|
|
|
StripProxy * proxy;
|
|
|
|
|
|
|
|
if(seq->anim != NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_join_dirfile(name, sizeof(name),
|
|
|
|
seq->strip->dir, seq->strip->stripdata->name);
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
|
|
|
|
seq->anim = openanim(name, IB_rect |
|
|
|
|
((seq->flag & SEQ_FILTERY) ?
|
|
|
|
IB_animdeinterlace : 0), seq->streamindex);
|
|
|
|
|
|
|
|
if (seq->anim == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
proxy = seq->strip->proxy;
|
|
|
|
|
|
|
|
if (proxy == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
|
|
|
|
IMB_anim_set_index_dir(seq->anim, seq->strip->proxy->dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static int seq_proxy_get_fname(SeqRenderData context, Sequence * seq, int cfra, char * name)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
int frameno;
|
2011-08-30 10:07:50 +00:00
|
|
|
char dir[PROXY_MAXFILE];
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
int render_size = context.preview_render_size;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (!seq->strip->proxy) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
/* MOVIE tracks (only exception: custom files) are now handled
|
|
|
|
internally by ImBuf module for various reasons: proper time code
|
|
|
|
support, quicker index build, using one file instead
|
|
|
|
of a full directory of jpeg files, etc. Trying to support old
|
|
|
|
and new method at once could lead to funny effects, if people
|
|
|
|
have both, a directory full of jpeg files and proxy avis, so
|
|
|
|
sorry folks, please rebuild your proxies... */
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR|SEQ_USE_PROXY_CUSTOM_FILE)) {
|
2009-01-12 19:02:08 +00:00
|
|
|
strcpy(dir, seq->strip->proxy->dir);
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
} else if (seq->type == SEQ_IMAGE) {
|
2011-08-30 10:07:50 +00:00
|
|
|
BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
return FALSE;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
BLI_join_dirfile(name, PROXY_MAXFILE,
|
|
|
|
dir, seq->strip->proxy->file);
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_abs(name, G.main->name);
|
2009-06-08 20:08:19 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
/* dirty hack to distinguish 100% render size from PROXY_100 */
|
|
|
|
if (render_size == 99) {
|
|
|
|
render_size = 100;
|
|
|
|
}
|
|
|
|
|
2009-11-02 17:25:15 +00:00
|
|
|
/* generate a separate proxy directory for each preview size */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (seq->type == SEQ_IMAGE) {
|
2011-08-30 10:07:50 +00:00
|
|
|
BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir,
|
2010-11-21 20:00:31 +00:00
|
|
|
context.preview_render_size,
|
|
|
|
give_stripelem(seq, cfra)->name);
|
2009-01-12 19:02:08 +00:00
|
|
|
frameno = 1;
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
} else {
|
|
|
|
frameno = (int) give_stripelem_index(seq, cfra)
|
|
|
|
+ seq->anim_startofs;
|
2011-08-30 10:07:50 +00:00
|
|
|
BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
|
2010-11-21 20:00:31 +00:00
|
|
|
context.preview_render_size);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_abs(name, G.main->name);
|
2010-03-09 17:36:23 +00:00
|
|
|
BLI_path_frame(name, frameno, 0);
|
2010-01-30 22:33:47 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
strcat(name, ".jpg");
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static struct ImBuf * seq_proxy_fetch(SeqRenderData context, Sequence * seq, int cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
char name[PROXY_MAXFILE];
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
IMB_Proxy_Size psize = seq_rendersize_to_proxysize(
|
|
|
|
context.preview_render_size);
|
|
|
|
int size_flags;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (!(seq->flag & SEQ_USE_PROXY)) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
size_flags = seq->strip->proxy->build_size_flags;
|
|
|
|
|
|
|
|
/* only use proxies, if they are enabled (even if present!) */
|
2011-09-11 21:46:24 +00:00
|
|
|
if (psize == IMB_PROXY_NONE || ((size_flags & psize) != psize)) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
|
2010-10-30 21:55:17 +00:00
|
|
|
int frameno = (int) give_stripelem_index(seq, cfra) + seq->anim_startofs;
|
|
|
|
if (seq->strip->proxy->anim == NULL) {
|
2010-11-21 20:00:31 +00:00
|
|
|
if (seq_proxy_get_fname(context, seq, cfra, name)==0) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
seq->strip->proxy->anim = openanim(name, IB_rect, 0);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
if (seq->strip->proxy->anim==NULL) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
seq_open_anim_file(seq);
|
|
|
|
|
|
|
|
frameno = IMB_anim_index_get_frame_index(
|
|
|
|
seq->anim, seq->strip->proxy->tc, frameno);
|
|
|
|
|
|
|
|
return IMB_anim_absolute(seq->strip->proxy->anim, frameno,
|
|
|
|
IMB_TC_NONE, IMB_PROXY_NONE);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
if (seq_proxy_get_fname(context, seq, cfra, name) == 0) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (BLI_exists(name)) {
|
|
|
|
return IMB_loadiffname(name, IB_rect);
|
|
|
|
} else {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
static void seq_proxy_build_frame(SeqRenderData context,
|
|
|
|
Sequence* seq, int cfra,
|
|
|
|
int proxy_render_size)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
char name[PROXY_MAXFILE];
|
|
|
|
int quality;
|
|
|
|
int rectx, recty;
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
int ok;
|
2009-01-12 19:02:08 +00:00
|
|
|
struct ImBuf * ibuf;
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (!seq_proxy_get_fname(context, seq, cfra, name)) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
ibuf = seq_render_strip(context, seq, cfra);
|
2009-06-08 20:08:19 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
rectx = (proxy_render_size * context.scene->r.xsch) / 100;
|
|
|
|
recty = (proxy_render_size * context.scene->r.ysch) / 100;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (ibuf->x != rectx || ibuf->y != recty) {
|
|
|
|
IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
/* depth = 32 is intentionally left in, otherwise ALPHA channels
|
2009-01-12 19:02:08 +00:00
|
|
|
won't work... */
|
2009-06-14 18:54:35 +00:00
|
|
|
quality = seq->strip->proxy->quality;
|
2009-01-12 19:02:08 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
void seq_proxy_rebuild(struct Main * bmain, Scene *scene, Sequence * seq,
|
|
|
|
short *stop, short *do_update, float *progress)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
SeqRenderData context;
|
2009-01-12 19:02:08 +00:00
|
|
|
int cfra;
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
int tc_flags;
|
|
|
|
int size_flags;
|
|
|
|
int quality;
|
|
|
|
|
|
|
|
if (!seq->strip || !seq->strip->proxy) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(seq->flag & SEQ_USE_PROXY)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
tc_flags = seq->strip->proxy->build_tc_flags;
|
|
|
|
size_flags = seq->strip->proxy->build_size_flags;
|
|
|
|
quality = seq->strip->proxy->quality;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (seq->type == SEQ_MOVIE) {
|
|
|
|
seq_open_anim_file(seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (seq->anim) {
|
|
|
|
IMB_anim_index_rebuild(
|
|
|
|
seq->anim, tc_flags, size_flags, quality,
|
|
|
|
stop, do_update, progress);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (!(seq->flag & SEQ_USE_PROXY)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
/* that's why it is called custom... */
|
|
|
|
if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
|
|
|
|
return;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
/* fail safe code */
|
2009-06-14 18:54:35 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
context = seq_new_render_data(
|
|
|
|
bmain, scene,
|
|
|
|
(scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
|
|
|
|
(scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f,
|
|
|
|
100);
|
|
|
|
|
|
|
|
for (cfra = seq->startdisp + seq->startstill;
|
|
|
|
cfra < seq->enddisp - seq->endstill; cfra++) {
|
|
|
|
if (size_flags & IMB_PROXY_25) {
|
|
|
|
seq_proxy_build_frame(context, seq, cfra, 25);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (size_flags & IMB_PROXY_50) {
|
|
|
|
seq_proxy_build_frame(context, seq, cfra, 50);
|
|
|
|
}
|
|
|
|
if (size_flags & IMB_PROXY_75) {
|
|
|
|
seq_proxy_build_frame(context, seq, cfra, 75);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
if (size_flags & IMB_PROXY_100) {
|
|
|
|
seq_proxy_build_frame(context, seq, cfra, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
*progress= (float)cfra/(seq->enddisp - seq->endstill
|
|
|
|
- seq->startdisp + seq->startstill);
|
|
|
|
*do_update= 1;
|
|
|
|
|
|
|
|
if(*stop || G.afbreek)
|
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* **********************************************************************
|
|
|
|
color balance
|
|
|
|
********************************************************************** */
|
|
|
|
|
|
|
|
static StripColorBalance calc_cb(StripColorBalance * cb_)
|
|
|
|
{
|
|
|
|
StripColorBalance cb = *cb_;
|
|
|
|
int c;
|
|
|
|
|
2010-07-05 09:56:06 +00:00
|
|
|
for (c = 0; c < 3; c++) {
|
2010-07-06 10:21:28 +00:00
|
|
|
cb.lift[c] = 2.0f - cb.lift[c];
|
2010-07-05 09:56:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
|
2010-07-05 14:53:11 +00:00
|
|
|
for (c = 0; c < 3; c++) {
|
2010-07-12 16:20:51 +00:00
|
|
|
/* tweak to give more subtle results
|
|
|
|
* values above 1.0 are scaled */
|
|
|
|
if(cb.lift[c] > 1.0f)
|
2011-03-30 16:11:16 +00:00
|
|
|
cb.lift[c] = pow(cb.lift[c] - 1.0f, 2.0) + 1.0;
|
2010-07-12 16:20:51 +00:00
|
|
|
|
2010-07-05 14:53:11 +00:00
|
|
|
cb.lift[c] = 2.0f - cb.lift[c];
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-05 09:56:06 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
|
|
|
|
for (c = 0; c < 3; c++) {
|
2011-03-30 16:11:16 +00:00
|
|
|
if (cb.gain[c] != 0.0f) {
|
|
|
|
cb.gain[c] = 1.0f / cb.gain[c];
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
|
|
|
cb.gain[c] = 1000000; /* should be enough :) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
|
|
|
|
for (c = 0; c < 3; c++) {
|
2011-03-30 16:11:16 +00:00
|
|
|
if (cb.gamma[c] != 0.0f) {
|
|
|
|
cb.gamma[c] = 1.0f/cb.gamma[c];
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
|
|
|
cb.gamma[c] = 1000000; /* should be enough :) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cb;
|
|
|
|
}
|
|
|
|
|
2010-07-06 10:21:28 +00:00
|
|
|
/* note: lift is actually 2-lift */
|
2010-07-07 15:06:57 +00:00
|
|
|
MINLINE float color_balance_fl(float in, const float lift, const float gain, const float gamma, const float mul)
|
2010-07-05 09:56:06 +00:00
|
|
|
{
|
2010-07-07 15:06:57 +00:00
|
|
|
float x= (((in - 1.0f) * lift) + 1.0f) * gain;
|
|
|
|
|
|
|
|
/* prevent NaN */
|
|
|
|
if (x < 0.f) x = 0.f;
|
|
|
|
|
|
|
|
return powf(x, gamma) * mul;
|
2010-07-05 09:56:06 +00:00
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
static void make_cb_table_byte(float lift, float gain, float gamma,
|
2010-03-22 09:30:00 +00:00
|
|
|
unsigned char * table, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
int y;
|
|
|
|
|
|
|
|
for (y = 0; y < 256; y++) {
|
2011-03-30 16:11:16 +00:00
|
|
|
float v= color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
|
2010-07-04 20:59:10 +00:00
|
|
|
CLAMP(v, 0.0f, 1.0f);
|
2009-01-12 19:02:08 +00:00
|
|
|
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++) {
|
2011-03-30 16:11:16 +00:00
|
|
|
float v= color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
table[y] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static void color_balance_byte_byte(Sequence * seq, ImBuf* ibuf, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
unsigned char cb_tab[3][256];
|
|
|
|
int c;
|
2010-07-23 16:57:11 +00:00
|
|
|
unsigned char * p = (unsigned char*) ibuf->rect;
|
|
|
|
unsigned char * e = p + ibuf->x * 4 * ibuf->y;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
float cb_tab[4][256];
|
|
|
|
int c,i;
|
2010-07-23 16:57:11 +00:00
|
|
|
unsigned char * p = (unsigned char*) ibuf->rect;
|
|
|
|
unsigned char * e = p + ibuf->x * 4 * ibuf->y;
|
2009-01-12 19:02:08 +00:00
|
|
|
float * o;
|
|
|
|
StripColorBalance cb;
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
imb_addrectfloatImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
o = ibuf->rect_float;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
cb = calc_cb(seq->strip->color_balance);
|
|
|
|
|
|
|
|
for (c = 0; c < 3; c++) {
|
2010-10-30 21:55:17 +00:00
|
|
|
make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static void color_balance_float_float(Sequence * seq, ImBuf* ibuf, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-07-23 16:57:11 +00:00
|
|
|
float * p = ibuf->rect_float;
|
|
|
|
float * e = ibuf->rect_float + ibuf->x * 4* ibuf->y;
|
2009-01-12 19:02:08 +00:00
|
|
|
StripColorBalance cb = calc_cb(seq->strip->color_balance);
|
|
|
|
|
|
|
|
while (p < e) {
|
|
|
|
int c;
|
|
|
|
for (c = 0; c < 3; c++) {
|
2010-07-05 09:56:06 +00:00
|
|
|
p[c]= color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
p += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static void color_balance(Sequence * seq, ImBuf* ibuf, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-07-23 16:57:11 +00:00
|
|
|
if (ibuf->rect_float) {
|
|
|
|
color_balance_float_float(seq, ibuf, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else if(seq->flag & SEQ_MAKE_FLOAT) {
|
2010-07-23 16:57:11 +00:00
|
|
|
color_balance_byte_float(seq, ibuf, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
2010-07-23 16:57:11 +00:00
|
|
|
color_balance_byte_byte(seq, ibuf, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
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
|
2010-03-22 09:30:00 +00:00
|
|
|
(future: half -> float should also work fine!)
|
|
|
|
case, if done on load, since we can use lookup tables)
|
2009-01-12 19:02:08 +00:00
|
|
|
- Premultiply
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2010-07-25 17:19:55 +00:00
|
|
|
int input_have_to_preprocess(
|
2010-11-22 05:36:49 +00:00
|
|
|
SeqRenderData UNUSED(context), Sequence * seq, float UNUSED(cfra))
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
float mul;
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (seq->flag & (SEQ_FILTERY|SEQ_USE_CROP|SEQ_USE_TRANSFORM|SEQ_FLIPX|
|
2010-11-21 20:00:31 +00:00
|
|
|
SEQ_FLIPY|SEQ_USE_COLOR_BALANCE|SEQ_MAKE_PREMUL)) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
mul = seq->mul;
|
|
|
|
|
2010-08-08 14:21:20 +00:00
|
|
|
if(seq->blend_mode == SEQ_BLEND_REPLACE) {
|
2011-03-30 16:11:16 +00:00
|
|
|
mul *= seq->blend_opacity / 100.0f;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if (mul != 1.0f) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if (seq->sat != 1.0f) {
|
2010-07-23 16:57:11 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static ImBuf * input_preprocess(
|
2010-11-21 20:00:31 +00:00
|
|
|
SeqRenderData context, Sequence *seq, float UNUSED(cfra), ImBuf * ibuf)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
float mul;
|
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
ibuf = IMB_makeSingleUser(ibuf);
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
|
2010-07-23 16:57:11 +00:00
|
|
|
IMB_filtery(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if(seq->flag & (SEQ_USE_CROP|SEQ_USE_TRANSFORM)) {
|
2010-10-31 15:39:37 +00:00
|
|
|
StripCrop c= {0};
|
|
|
|
StripTransform t= {0};
|
2009-01-12 19:02:08 +00:00
|
|
|
int sx,sy,dx,dy;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
sx = ibuf->x - c.left - c.right;
|
|
|
|
sy = ibuf->y - c.top - c.bottom;
|
2009-01-12 19:02:08 +00:00
|
|
|
dx = sx;
|
|
|
|
dy = sy;
|
|
|
|
|
|
|
|
if (seq->flag & SEQ_USE_TRANSFORM) {
|
2010-11-21 20:00:31 +00:00
|
|
|
dx = context.scene->r.xsch;
|
|
|
|
dy = context.scene->r.ysch;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (c.top + c.bottom >= ibuf->y || c.left + c.right >= ibuf->x ||
|
|
|
|
t.xofs >= dx || t.yofs >= dy) {
|
2010-07-23 16:57:11 +00:00
|
|
|
make_black_ibuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
2010-10-30 21:55:17 +00:00
|
|
|
ImBuf * i = IMB_allocImBuf(dx, dy,32, ibuf->rect_float ? IB_rectfloat : IB_rect);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
ibuf = i;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->flag & SEQ_FLIPX) {
|
2010-07-23 16:57:11 +00:00
|
|
|
IMB_flipx(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-16 15:45:35 +00:00
|
|
|
|
|
|
|
if(seq->flag & SEQ_FLIPY) {
|
2010-07-23 16:57:11 +00:00
|
|
|
IMB_flipy(ibuf);
|
2010-07-16 15:45:35 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-13 09:28:01 +00:00
|
|
|
if(seq->sat != 1.0f) {
|
|
|
|
/* inline for now, could become an imbuf function */
|
|
|
|
int i;
|
2010-12-20 03:59:22 +00:00
|
|
|
unsigned char *rct= (unsigned char *)ibuf->rect;
|
2010-07-23 16:57:11 +00:00
|
|
|
float *rctf= ibuf->rect_float;
|
2010-07-13 09:28:01 +00:00
|
|
|
const float sat= seq->sat;
|
|
|
|
float hsv[3];
|
|
|
|
|
|
|
|
if(rct) {
|
|
|
|
float rgb[3];
|
2010-07-23 16:57:11 +00:00
|
|
|
for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
|
2010-07-13 09:28:01 +00:00
|
|
|
rgb_byte_to_float(rct, rgb);
|
|
|
|
rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
|
|
|
|
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2);
|
|
|
|
rgb_float_to_byte(rgb, rct);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rctf) {
|
2010-07-23 16:57:11 +00:00
|
|
|
for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
|
2010-07-13 09:28:01 +00:00
|
|
|
rgb_to_hsv(rctf[0], rctf[1], rctf[2], hsv, hsv+1, hsv+2);
|
|
|
|
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf+1, rctf+2);
|
|
|
|
}
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mul = seq->mul;
|
|
|
|
|
|
|
|
if(seq->blend_mode == SEQ_BLEND_REPLACE) {
|
2011-03-30 16:11:16 +00:00
|
|
|
mul *= seq->blend_opacity / 100.0f;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
|
2010-07-23 16:57:11 +00:00
|
|
|
color_balance(seq, ibuf, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
mul = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->flag & SEQ_MAKE_FLOAT) {
|
2010-07-23 16:57:11 +00:00
|
|
|
if (!ibuf->rect_float)
|
|
|
|
IMB_float_from_rect_simple(ibuf);
|
2010-04-01 03:58:20 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if (ibuf->rect) {
|
|
|
|
imb_freerectImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if(mul != 1.0f) {
|
2010-07-23 16:57:11 +00:00
|
|
|
multibuf(ibuf, mul);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->flag & SEQ_MAKE_PREMUL) {
|
2011-02-13 10:52:18 +00:00
|
|
|
if(ibuf->depth == 32 && ibuf->zbuf == NULL) {
|
2010-07-23 16:57:11 +00:00
|
|
|
IMB_premultiply_alpha(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
if(ibuf->x != context.rectx || ibuf->y != context.recty ) {
|
|
|
|
if(context.scene->r.mode & R_OSA) {
|
|
|
|
IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
2010-11-21 20:00:31 +00:00
|
|
|
IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
return ibuf;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static ImBuf * copy_from_ibuf_still(SeqRenderData context, Sequence * seq,
|
|
|
|
float nr)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
ImBuf * rval = NULL;
|
|
|
|
ImBuf * ibuf = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if (nr == 0) {
|
|
|
|
ibuf = seq_stripelem_cache_get(
|
2010-11-21 20:00:31 +00:00
|
|
|
context, seq, seq->start,
|
2010-07-23 16:57:11 +00:00
|
|
|
SEQ_STRIPELEM_IBUF_STARTSTILL);
|
2010-12-17 08:08:35 +00:00
|
|
|
} else if (nr == seq->len - 1) {
|
2010-07-23 16:57:11 +00:00
|
|
|
ibuf = seq_stripelem_cache_get(
|
2010-11-21 20:00:31 +00:00
|
|
|
context, seq, seq->start,
|
2010-07-23 16:57:11 +00:00
|
|
|
SEQ_STRIPELEM_IBUF_ENDSTILL);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if (ibuf) {
|
|
|
|
rval = IMB_dupImBuf(ibuf);
|
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
return rval;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static void copy_to_ibuf_still(SeqRenderData context, Sequence * seq, float nr,
|
2010-07-23 16:57:11 +00:00
|
|
|
ImBuf * ibuf)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2011-04-17 10:05:27 +00:00
|
|
|
if (nr == 0 || nr == seq->len - 1) {
|
|
|
|
/* we have to store a copy, since the passed ibuf
|
|
|
|
could be preprocessed afterwards (thereby silently
|
|
|
|
changing the cached image... */
|
|
|
|
ibuf = IMB_dupImBuf(ibuf);
|
|
|
|
|
|
|
|
if (nr == 0) {
|
|
|
|
seq_stripelem_cache_put(
|
|
|
|
context, seq, seq->start,
|
|
|
|
SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nr == seq->len - 1) {
|
|
|
|
seq_stripelem_cache_put(
|
|
|
|
context, seq, seq->start,
|
|
|
|
SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
|
|
|
|
}
|
2010-12-17 08:08:35 +00:00
|
|
|
|
2011-04-17 10:05:27 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
/* **********************************************************************
|
|
|
|
strip rendering functions
|
|
|
|
********************************************************************** */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static ImBuf* seq_render_strip_stack(
|
|
|
|
SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static ImBuf * seq_render_strip(
|
|
|
|
SeqRenderData context, Sequence * seq, float cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static ImBuf* seq_render_effect_strip_impl(
|
|
|
|
SeqRenderData context, Sequence *seq, float cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-07-23 16:57:11 +00:00
|
|
|
float fac, facf;
|
|
|
|
int early_out;
|
|
|
|
int i;
|
|
|
|
struct SeqEffectHandle sh = get_sequence_effect(seq);
|
|
|
|
FCurve *fcu= NULL;
|
|
|
|
ImBuf * ibuf[3];
|
2010-10-30 21:55:17 +00:00
|
|
|
Sequence *input[3];
|
|
|
|
ImBuf * out = NULL;
|
|
|
|
|
|
|
|
ibuf[0] = ibuf[1] = ibuf[2] = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3;
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
if (!sh.execute) { /* effect not supported in this version... */
|
2010-11-21 20:00:31 +00:00
|
|
|
out = IMB_allocImBuf((short)context.rectx,
|
|
|
|
(short)context.recty, 32, IB_rect);
|
2010-10-30 21:55:17 +00:00
|
|
|
return out;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
|
2010-07-23 16:57:11 +00:00
|
|
|
sh.get_default_fac(seq, cfra, &fac, &facf);
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
if ((context.scene->r.mode & R_FIELDS)==0)
|
2010-10-30 21:55:17 +00:00
|
|
|
facf= fac;
|
|
|
|
}
|
|
|
|
else {
|
3D Audio GSoC:
Implemented basic audio animation.
* AnimatableProperty: Propper cache writing and spline interpolation for reading (the solution for stair steps in audio animation)
* Animatable properties so far are: volume, pitch, panning
* Users note: Changing the pitch of a sound results in wrong seeking, due to the resulting playback length difference.
* Users note: Panning only works for mono sources, values are in the range [-2..2], this basically controls the angle of the sound, 0 is front, -1 left, 1 right and 2 and -2 are back. Typical stereo panning only supports [-1..1].
* Disabled animation of audio related ffmpeg output parameters.
* Scene Audio Panel: 3D Listener settings also for Renderer, new Volume property (animatable!), Update/Bake buttons for animation problems, moved sampling rate and channel count here
2011-07-28 13:58:59 +00:00
|
|
|
fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL);
|
2010-07-23 16:57:11 +00:00
|
|
|
if (fcu) {
|
|
|
|
fac = facf = evaluate_fcurve(fcu, cfra);
|
2010-11-21 20:00:31 +00:00
|
|
|
if( context.scene->r.mode & R_FIELDS ) {
|
2011-03-30 16:11:16 +00:00
|
|
|
facf = evaluate_fcurve(fcu, cfra + 0.5f);
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fac = facf = seq->effect_fader;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
early_out = sh.early_out(seq, fac, facf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
switch (early_out) {
|
|
|
|
case EARLY_NO_INPUT:
|
2010-11-21 20:00:31 +00:00
|
|
|
out = sh.execute(context, seq, cfra, fac, facf,
|
|
|
|
NULL, NULL, NULL);
|
2010-12-17 08:53:49 +00:00
|
|
|
break;
|
2010-10-30 21:55:17 +00:00
|
|
|
case EARLY_DO_EFFECT:
|
|
|
|
for(i=0; i<3; i++) {
|
|
|
|
if(input[i])
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf[i] = seq_render_strip(
|
|
|
|
context, input[i], cfra);
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ibuf[0] && ibuf[1]) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = sh.execute(context, seq, cfra, fac, facf,
|
|
|
|
ibuf[0], ibuf[1], ibuf[2]);
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
break;
|
2010-10-30 21:55:17 +00:00
|
|
|
case EARLY_USE_INPUT_1:
|
|
|
|
if (input[0]) {
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf[0] = seq_render_strip(context, input[0], cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
if (ibuf[0]) {
|
2010-11-21 20:00:31 +00:00
|
|
|
if (input_have_to_preprocess(context, seq, cfra)) {
|
2010-07-23 16:57:11 +00:00
|
|
|
out = IMB_dupImBuf(ibuf[0]);
|
|
|
|
} else {
|
|
|
|
out = ibuf[0];
|
|
|
|
IMB_refImBuf(out);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
|
|
|
case EARLY_USE_INPUT_2:
|
|
|
|
if (input[1]) {
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf[1] = seq_render_strip(context, input[1], cfra);
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
|
|
|
if (ibuf[1]) {
|
2010-11-21 20:00:31 +00:00
|
|
|
if (input_have_to_preprocess(context, seq, cfra)) {
|
2010-07-23 16:57:11 +00:00
|
|
|
out = IMB_dupImBuf(ibuf[1]);
|
|
|
|
} else {
|
|
|
|
out = ibuf[1];
|
|
|
|
IMB_refImBuf(out);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
IMB_freeImBuf(ibuf[i]);
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (out == NULL) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
return out;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static ImBuf * seq_render_scene_strip_impl(
|
2010-11-21 20:00:31 +00:00
|
|
|
SeqRenderData context, Sequence * seq, float nr)
|
2010-07-23 16:57:11 +00:00
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
ImBuf * ibuf = NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
float frame= seq->sfra + nr + seq->anim_startofs;
|
2010-07-30 11:40:23 +00:00
|
|
|
float oldcfra;
|
2011-04-30 05:42:37 +00:00
|
|
|
Object *camera;
|
2010-07-23 16:57:11 +00:00
|
|
|
ListBase oldmarkers;
|
|
|
|
|
2010-10-21 17:00:38 +00:00
|
|
|
/* Old info:
|
|
|
|
Hack! This function can be called from do_render_seq(), in that case
|
2010-07-23 16:57:11 +00:00
|
|
|
the seq->scene can already have a Render initialized with same name,
|
|
|
|
so we have to use a default name. (compositor uses scene name to
|
|
|
|
find render).
|
|
|
|
However, when called from within the UI (image preview in sequencer)
|
|
|
|
we do want to use scene Render, that way the render result is defined
|
|
|
|
for display in render/imagewindow
|
|
|
|
|
|
|
|
Hmm, don't see, why we can't do that all the time,
|
|
|
|
and since G.rendering is uhm, gone... (Peter)
|
|
|
|
*/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-21 17:00:38 +00:00
|
|
|
/* New info:
|
|
|
|
Using the same name for the renders works just fine as the do_render_seq()
|
|
|
|
render is not used while the scene strips are rendered.
|
|
|
|
|
|
|
|
However rendering from UI (through sequencer_preview_area_draw) can crash in
|
|
|
|
very many cases since other renders (material preview, an actual render etc.)
|
|
|
|
can be started while this sequence preview render is running. The only proper
|
|
|
|
solution is to make the sequencer preview render a proper job, which can be
|
|
|
|
stopped when needed. This would also give a nice progress bar for the preview
|
|
|
|
space so that users know there's something happening.
|
|
|
|
|
|
|
|
As a result the active scene now only uses OpenGL rendering for the sequencer
|
|
|
|
preview. This is far from nice, but is the only way to prevent crashes at this
|
|
|
|
time.
|
|
|
|
|
|
|
|
-jahka
|
|
|
|
*/
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
int rendering = G.rendering;
|
|
|
|
int doseq;
|
2010-10-21 17:00:38 +00:00
|
|
|
int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : /*(scene->r.seq_flag & R_SEQ_GL_PREV)*/ 1;
|
2010-07-23 16:57:11 +00:00
|
|
|
int have_seq= FALSE;
|
2011-04-30 06:22:02 +00:00
|
|
|
Scene *scene;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
/* dont refer to seq->scene above this point!, it can be NULL */
|
|
|
|
if(seq->scene == NULL) {
|
|
|
|
return NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
scene= seq->scene;
|
2010-07-30 11:40:23 +00:00
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
have_seq= (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;
|
|
|
|
|
|
|
|
oldcfra= scene->r.cfra;
|
|
|
|
scene->r.cfra= frame;
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if(seq->scene_camera)
|
2011-04-30 05:42:37 +00:00
|
|
|
camera= seq->scene_camera;
|
|
|
|
else {
|
2011-04-30 06:22:02 +00:00
|
|
|
scene_camera_switch_update(scene);
|
|
|
|
camera= scene->camera;
|
2011-04-30 05:42:37 +00:00
|
|
|
}
|
2011-04-30 06:22:02 +00:00
|
|
|
|
2011-05-01 10:14:09 +00:00
|
|
|
if(have_seq==FALSE && camera==NULL) {
|
2011-04-30 06:22:02 +00:00
|
|
|
scene->r.cfra= oldcfra;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* prevent eternal loop */
|
|
|
|
doseq= context.scene->r.scemode & R_DOSEQ;
|
|
|
|
context.scene->r.scemode &= ~R_DOSEQ;
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
#ifdef DURIAN_CAMERA_SWITCH
|
|
|
|
/* stooping to new low's in hackyness :( */
|
2011-04-30 06:22:02 +00:00
|
|
|
oldmarkers= scene->markers;
|
|
|
|
scene->markers.first= scene->markers.last= NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
#endif
|
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (scene == context.scene || have_seq==0) && camera) {
|
2011-03-06 23:12:12 +00:00
|
|
|
char err_out[256]= "unknown";
|
2010-10-21 17:00:38 +00:00
|
|
|
/* for old scened this can be uninitialized, should probably be added to do_versions at some point if the functionality stays */
|
2010-11-21 20:00:31 +00:00
|
|
|
if(context.scene->r.seq_prev_type==0)
|
|
|
|
context.scene->r.seq_prev_type = 3 /* ==OB_SOLID */;
|
2010-10-21 17:00:38 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
/* opengl offscreen render */
|
2011-04-30 06:22:02 +00:00
|
|
|
scene_update_for_newframe(context.bmain, scene, scene->lay);
|
|
|
|
ibuf= sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect, context.scene->r.seq_prev_type, err_out);
|
2011-03-06 23:12:12 +00:00
|
|
|
if(ibuf == NULL) {
|
|
|
|
fprintf(stderr, "seq_render_scene_strip_impl failed to get opengl buffer: %s\n", err_out);
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-04-30 06:22:02 +00:00
|
|
|
Render *re = RE_GetRender(scene->id.name);
|
2010-07-23 16:57:11 +00:00
|
|
|
RenderResult rres;
|
2010-10-21 17:00:38 +00:00
|
|
|
|
|
|
|
/* XXX: this if can be removed when sequence preview rendering uses the job system */
|
2011-04-30 06:22:02 +00:00
|
|
|
if(rendering || context.scene != scene) {
|
2010-10-21 17:00:38 +00:00
|
|
|
if(re==NULL)
|
2011-04-30 06:22:02 +00:00
|
|
|
re= RE_NewRender(scene->id.name);
|
2010-10-21 17:00:38 +00:00
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE);
|
2010-10-21 17:00:38 +00:00
|
|
|
|
|
|
|
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
|
|
|
|
G.rendering = rendering;
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
RE_AcquireResultImage(re, &rres);
|
|
|
|
|
|
|
|
if(rres.rectf) {
|
2010-10-16 14:32:17 +00:00
|
|
|
ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
|
2010-07-23 16:57:11 +00:00
|
|
|
memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
|
|
|
|
if(rres.rectz) {
|
|
|
|
addzbuffloatImBuf(ibuf);
|
|
|
|
memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-30 11:55:41 +00:00
|
|
|
|
|
|
|
/* float buffers in the sequencer are not linear */
|
|
|
|
ibuf->profile= IB_PROFILE_LINEAR_RGB;
|
|
|
|
IMB_convert_profile(ibuf, IB_PROFILE_SRGB);
|
|
|
|
}
|
|
|
|
else if (rres.rect32) {
|
2010-10-16 14:32:17 +00:00
|
|
|
ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
|
2010-07-23 16:57:11 +00:00
|
|
|
memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
RE_ReleaseResultImage(re);
|
|
|
|
|
|
|
|
// BIF_end_render_callbacks();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore */
|
2010-11-21 20:00:31 +00:00
|
|
|
context.scene->r.scemode |= doseq;
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2011-04-30 06:22:02 +00:00
|
|
|
scene->r.cfra = oldcfra;
|
2011-04-30 05:42:37 +00:00
|
|
|
|
2011-01-28 13:14:01 +00:00
|
|
|
if(frame != oldcfra)
|
2011-04-30 06:22:02 +00:00
|
|
|
scene_update_for_newframe(context.bmain, scene, scene->lay);
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2010-03-10 08:17:18 +00:00
|
|
|
#ifdef DURIAN_CAMERA_SWITCH
|
2010-07-23 16:57:11 +00:00
|
|
|
/* stooping to new low's in hackyness :( */
|
2011-04-30 06:22:02 +00:00
|
|
|
scene->markers= oldmarkers;
|
2010-03-10 08:17:18 +00:00
|
|
|
#endif
|
2010-03-08 21:33:51 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
return ibuf;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
static ImBuf * seq_render_strip(SeqRenderData context, Sequence * seq, float cfra)
|
2010-07-23 16:57:11 +00:00
|
|
|
{
|
2010-10-30 21:55:17 +00:00
|
|
|
ImBuf * ibuf = NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
char name[FILE_MAXDIR+FILE_MAXFILE];
|
2010-11-21 20:00:31 +00:00
|
|
|
int use_preprocess = input_have_to_preprocess(context, seq, cfra);
|
2010-07-23 16:57:11 +00:00
|
|
|
float nr = give_stripelem_index(seq, cfra);
|
2010-10-30 21:55:17 +00:00
|
|
|
/* all effects are handled similarly with the exception of speed effect */
|
|
|
|
int type = (seq->type & SEQ_EFFECT && seq->type != SEQ_SPEED) ? SEQ_EFFECT : seq->type;
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf = seq_stripelem_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
|
2010-03-10 08:17:18 +00:00
|
|
|
|
2010-12-17 08:08:35 +00:00
|
|
|
/* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
|
|
|
|
but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ibuf)
|
2010-07-23 16:57:11 +00:00
|
|
|
use_preprocess = FALSE;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-12-17 08:08:35 +00:00
|
|
|
if (ibuf == NULL)
|
|
|
|
ibuf = copy_from_ibuf_still(context, seq, nr);
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ibuf == NULL)
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf = seq_proxy_fetch(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if(ibuf == NULL) switch(type) {
|
|
|
|
case SEQ_META:
|
|
|
|
{
|
|
|
|
ImBuf * meta_ibuf = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if(seq->seqbase.first)
|
2010-11-21 20:00:31 +00:00
|
|
|
meta_ibuf = seq_render_strip_stack(
|
|
|
|
context, &seq->seqbase,
|
|
|
|
seq->start + nr, 0);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if(meta_ibuf) {
|
|
|
|
ibuf = meta_ibuf;
|
|
|
|
if(ibuf && use_preprocess) {
|
|
|
|
struct ImBuf * i = IMB_dupImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
ibuf = i;
|
|
|
|
}
|
2009-11-29 18:14:16 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2009-11-22 20:22:35 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_SPEED:
|
|
|
|
{
|
|
|
|
ImBuf * child_ibuf = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
float f_cfra;
|
2010-10-30 21:55:17 +00:00
|
|
|
SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
sequence_effect_speed_rebuild_map(context.scene,seq, 0);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
/* weeek! */
|
|
|
|
f_cfra = seq->start + s->frameMap[(int) nr];
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
child_ibuf = seq_render_strip(context,seq->seq1,f_cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (child_ibuf) {
|
|
|
|
ibuf = child_ibuf;
|
|
|
|
if(ibuf && use_preprocess) {
|
|
|
|
struct ImBuf * i = IMB_dupImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
ibuf = i;
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_EFFECT:
|
2011-05-17 18:37:44 +00:00
|
|
|
{
|
|
|
|
ibuf = seq_render_effect_strip_impl(
|
|
|
|
context, seq, seq->start + nr);
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_IMAGE:
|
|
|
|
{
|
|
|
|
StripElem * s_elem = give_stripelem(seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (s_elem) {
|
2011-02-13 03:21:27 +00:00
|
|
|
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
|
2010-10-30 21:55:17 +00:00
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
|
|
|
|
/* we don't need both (speed reasons)! */
|
|
|
|
if (ibuf->rect_float && ibuf->rect)
|
|
|
|
imb_freerectImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
|
|
|
|
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
|
|
|
|
IMB_convert_profile(ibuf, IB_PROFILE_NONE);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
2010-11-28 18:23:21 +00:00
|
|
|
|
|
|
|
s_elem->orig_width = ibuf->x;
|
|
|
|
s_elem->orig_height = ibuf->y;
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_MOVIE:
|
|
|
|
{
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
seq_open_anim_file(seq);
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if(seq->anim) {
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
IMB_anim_set_preseek(seq->anim,
|
|
|
|
seq->anim_preseek);
|
|
|
|
|
|
|
|
ibuf = IMB_anim_absolute(
|
|
|
|
seq->anim, nr + seq->anim_startofs,
|
|
|
|
seq->strip->proxy ?
|
|
|
|
seq->strip->proxy->tc
|
|
|
|
: IMB_TC_RECORD_RUN,
|
|
|
|
seq_rendersize_to_proxysize(
|
|
|
|
context.preview_render_size));
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
/* we don't need both (speed reasons)! */
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ibuf && ibuf->rect_float && ibuf->rect)
|
2010-07-23 16:57:11 +00:00
|
|
|
imb_freerectImBuf(ibuf);
|
2010-11-28 18:23:21 +00:00
|
|
|
if (ibuf) {
|
|
|
|
seq->strip->stripdata->orig_width = ibuf->x;
|
|
|
|
seq->strip->stripdata->orig_height = ibuf->y;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-11-21 20:00:31 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
case SEQ_SCENE:
|
|
|
|
{ // scene can be NULL after deletions
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf = seq_render_scene_strip_impl(context, seq, nr);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-12-03 12:08:59 +00:00
|
|
|
/* Scene strips update all animation, so we need to restore original state.*/
|
== RNA Property Updates get called by Animation System now ==
This fixes bug #26764 and several others like it, where modifier
properties (and others, but most visibly modifiers) would not do
anything when animated or driven, as modifier properties require the
RNA update calls to tag the modifiers to get recalculated.
While just adding a call to RNA_property_update() could have gotten
this working (as per the Campbell's patch attached in the report, and
also my own attempt #25881). However, on production rigs, the
performance cost of this is untenatable (on my own tests, without
these updates, I was getting ~5fps on such a rig, but only 0.9fps or
possibly even worse with the updates added).
Hence, this commit adds a property-update caching system to the RNA
level, which aims to reduce to the number of times that the update
functions end up needing to get called.
While this is much faster than without the caching, I also added an
optimisation for pose bones (which are numerous in production rigs) so
that their property updates are skipped, since they are useless to the
animsys (they only tag the depsgraph for updating). This gets things
moving at a more acceptable framerate.
2011-07-24 04:34:46 +00:00
|
|
|
BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
|
2010-12-03 12:08:59 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
2010-10-30 21:55:17 +00:00
|
|
|
break;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ibuf == NULL)
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
if (ibuf->x != context.rectx || ibuf->y != context.recty)
|
2010-07-24 19:42:29 +00:00
|
|
|
use_preprocess = TRUE;
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (use_preprocess)
|
2010-11-21 20:00:31 +00:00
|
|
|
ibuf = input_preprocess(context, seq, cfra, ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
seq_stripelem_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
|
2009-02-13 06:24:15 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
return ibuf;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2009-02-13 06:24:15 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
/* **********************************************************************
|
|
|
|
strip stack rendering functions
|
|
|
|
********************************************************************** */
|
|
|
|
|
2010-03-14 16:36:41 +00:00
|
|
|
static int seq_must_swap_input_in_blend_mode(Sequence * seq)
|
|
|
|
{
|
|
|
|
int swap_input = FALSE;
|
|
|
|
|
|
|
|
/* bad hack, to fix crazy input ordering of
|
|
|
|
those two effects */
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ELEM3(seq->blend_mode, SEQ_ALPHAOVER, SEQ_ALPHAUNDER, SEQ_OVERDROP)) {
|
2010-03-14 16:36:41 +00:00
|
|
|
swap_input = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return swap_input;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int seq_get_early_out_for_blend_mode(Sequence * seq)
|
|
|
|
{
|
|
|
|
struct SeqEffectHandle sh = get_sequence_blend(seq);
|
2011-03-30 16:11:16 +00:00
|
|
|
float facf = seq->blend_opacity / 100.0f;
|
2010-03-14 16:36:41 +00:00
|
|
|
int early_out = sh.early_out(seq, facf, facf);
|
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (ELEM(early_out, EARLY_DO_EFFECT, EARLY_NO_INPUT)) {
|
2010-03-14 16:36:41 +00:00
|
|
|
return early_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq_must_swap_input_in_blend_mode(seq)) {
|
2010-10-30 21:55:17 +00:00
|
|
|
if (early_out == EARLY_USE_INPUT_2) {
|
|
|
|
return EARLY_USE_INPUT_1;
|
|
|
|
} else if (early_out == EARLY_USE_INPUT_1) {
|
|
|
|
return EARLY_USE_INPUT_2;
|
2010-03-14 16:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return early_out;
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
static ImBuf* seq_render_strip_stack(
|
2010-11-21 20:00:31 +00:00
|
|
|
SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence* seq_arr[MAXSEQ+1];
|
|
|
|
int count;
|
|
|
|
int i;
|
2010-10-30 21:55:17 +00:00
|
|
|
ImBuf* out = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (count == 0) {
|
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-10 19:17:52 +00:00
|
|
|
#if 0 /* commentind since this breaks keyframing, since it resets the value on draw */
|
|
|
|
if(scene->r.cfra != cfra) {
|
|
|
|
// XXX for prefetch and overlay offset!..., very bad!!!
|
|
|
|
AnimData *adt= BKE_animdata_from_id(&scene->id);
|
== RNA Property Updates get called by Animation System now ==
This fixes bug #26764 and several others like it, where modifier
properties (and others, but most visibly modifiers) would not do
anything when animated or driven, as modifier properties require the
RNA update calls to tag the modifiers to get recalculated.
While just adding a call to RNA_property_update() could have gotten
this working (as per the Campbell's patch attached in the report, and
also my own attempt #25881). However, on production rigs, the
performance cost of this is untenatable (on my own tests, without
these updates, I was getting ~5fps on such a rig, but only 0.9fps or
possibly even worse with the updates added).
Hence, this commit adds a property-update caching system to the RNA
level, which aims to reduce to the number of times that the update
functions end up needing to get called.
While this is much faster than without the caching, I also added an
optimisation for pose bones (which are numerous in production rigs) so
that their property updates are skipped, since they are useless to the
animsys (they only tag the depsgraph for updating). This gets things
moving at a more acceptable framerate.
2011-07-24 04:34:46 +00:00
|
|
|
BKE_animsys_evaluate_animdata(scene, &scene->id, adt, cfra, ADT_RECALC_ANIM);
|
2010-07-10 19:17:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_stripelem_cache_get(context, seq_arr[count - 1],
|
|
|
|
cfra, SEQ_STRIPELEM_IBUF_COMP);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if (out) {
|
|
|
|
return out;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(count == 1) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_render_strip(context, seq_arr[0], cfra);
|
|
|
|
seq_stripelem_cache_put(context, seq_arr[0], cfra,
|
|
|
|
SEQ_STRIPELEM_IBUF_COMP, out);
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
return out;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (i = count - 1; i >= 0; i--) {
|
|
|
|
int early_out;
|
2010-10-30 21:55:17 +00:00
|
|
|
Sequence *seq = seq_arr[i];
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_stripelem_cache_get(
|
|
|
|
context, seq, cfra, SEQ_STRIPELEM_IBUF_COMP);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
if (out) {
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-03-14 16:36:41 +00:00
|
|
|
early_out = seq_get_early_out_for_blend_mode(seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
switch (early_out) {
|
2010-10-30 21:55:17 +00:00
|
|
|
case EARLY_NO_INPUT:
|
|
|
|
case EARLY_USE_INPUT_2:
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
2010-10-30 21:55:17 +00:00
|
|
|
case EARLY_USE_INPUT_1:
|
2009-01-12 19:02:08 +00:00
|
|
|
if (i == 0) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-10-30 21:55:17 +00:00
|
|
|
case EARLY_DO_EFFECT:
|
2009-01-12 19:02:08 +00:00
|
|
|
if (i == 0) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
if (out) {
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
seq_stripelem_cache_put(context, seq_arr[i], cfra,
|
|
|
|
SEQ_STRIPELEM_IBUF_COMP, out);
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
i++;
|
|
|
|
|
|
|
|
for (; i < count; i++) {
|
|
|
|
Sequence * seq = seq_arr[i];
|
2009-11-22 20:22:35 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (seq_get_early_out_for_blend_mode(seq) == EARLY_DO_EFFECT) {
|
2010-07-23 16:57:11 +00:00
|
|
|
struct SeqEffectHandle sh = get_sequence_blend(seq);
|
|
|
|
ImBuf * ibuf1 = out;
|
2010-11-21 20:00:31 +00:00
|
|
|
ImBuf * ibuf2 = seq_render_strip(context, seq, cfra);
|
2010-02-10 17:28:46 +00:00
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
float facf = seq->blend_opacity / 100.0f;
|
2010-10-30 21:55:17 +00:00
|
|
|
int swap_input = seq_must_swap_input_in_blend_mode(seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (swap_input) {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = sh.execute(context, seq, cfra,
|
|
|
|
facf, facf,
|
2011-02-13 10:52:18 +00:00
|
|
|
ibuf2, ibuf1, NULL);
|
2009-01-12 19:02:08 +00:00
|
|
|
} else {
|
2010-11-21 20:00:31 +00:00
|
|
|
out = sh.execute(context, seq, cfra,
|
|
|
|
facf, facf,
|
2011-02-13 10:52:18 +00:00
|
|
|
ibuf1, ibuf2, NULL);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf1);
|
|
|
|
IMB_freeImBuf(ibuf2);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
seq_stripelem_cache_put(context, seq_arr[i], cfra,
|
|
|
|
SEQ_STRIPELEM_IBUF_COMP, out);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
return out;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* returned ImBuf is refed!
|
2010-07-23 16:57:11 +00:00
|
|
|
* you have to free after usage!
|
2009-01-12 19:02:08 +00:00
|
|
|
*/
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
ImBuf *give_ibuf_seq(SeqRenderData context, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-11-21 20:00:31 +00:00
|
|
|
Editing *ed= seq_give_editing(context.scene, FALSE);
|
2009-01-12 19:02:08 +00:00
|
|
|
int count;
|
|
|
|
ListBase *seqbasep;
|
2009-01-28 22:36:34 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
if(ed==NULL) return NULL;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
ImBuf *give_ibuf_seqbase(SeqRenderData context, float cfra, int chanshown, ListBase *seqbasep)
|
== Sequencer ==
This adds MULTICAM-editing support for blender. (Well, the beginning of.)
There is now a new effect track, named MULTICAM, which just selects
one of the lower tracks.
Doesn't sound that exciting, but if you combine this with A/B-Trim (moving
split points of two directly connected tracks around, while magically
resizing both strips, something to be added), you just do:
* add several tracks for your camera angles
* (optionally) sync those tracks
* add one multicam track on top
Use that multicam-track to edit your movie. (Either using fcurves on the
multicam source selector or using knife-tool and A/B-Trim.)
Compare that to:
* add several tracks
* add cross fades between them
* do some python scripting to add several fcurves to make that beast
somewhat work.
* cry out loud, using it, if you have to move cut points around
Alternatively, even harder:
* just edit the old way and put strip after strip
You might think, that this isn't really helpfull for animators, but
consider using scene-strips (in OpenGL-mode) for input, that are set for
different camera angles and can now be intercut a lot more easily...
Also: small fix on the way: the speed effect can now be used in cascade.
(Don't know, if anyone used it that way, but now it works.)
2010-04-25 12:53:39 +00:00
|
|
|
{
|
2010-11-21 20:00:31 +00:00
|
|
|
return seq_render_strip_stack(context, seqbasep, cfra, chanshown);
|
== Sequencer ==
This adds MULTICAM-editing support for blender. (Well, the beginning of.)
There is now a new effect track, named MULTICAM, which just selects
one of the lower tracks.
Doesn't sound that exciting, but if you combine this with A/B-Trim (moving
split points of two directly connected tracks around, while magically
resizing both strips, something to be added), you just do:
* add several tracks for your camera angles
* (optionally) sync those tracks
* add one multicam track on top
Use that multicam-track to edit your movie. (Either using fcurves on the
multicam source selector or using knife-tool and A/B-Trim.)
Compare that to:
* add several tracks
* add cross fades between them
* do some python scripting to add several fcurves to make that beast
somewhat work.
* cry out loud, using it, if you have to move cut points around
Alternatively, even harder:
* just edit the old way and put strip after strip
You might think, that this isn't really helpfull for animators, but
consider using scene-strips (in OpenGL-mode) for input, that are set for
different camera angles and can now be intercut a lot more easily...
Also: small fix on the way: the speed effect can now be used in cascade.
(Don't know, if anyone used it that way, but now it works.)
2010-04-25 12:53:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2010-11-21 20:00:31 +00:00
|
|
|
return seq_render_strip(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2009-11-11 09:59:51 +00:00
|
|
|
#if 0
|
2009-01-12 19:02:08 +00:00
|
|
|
/* check used when we need to change seq->blend_mode but not to effect or audio strips */
|
2009-09-14 16:52:06 +00:00
|
|
|
static int seq_can_blend(Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2009-11-11 09:59:51 +00:00
|
|
|
#endif
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* *********************** 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;
|
|
|
|
|
2009-11-11 09:59:51 +00:00
|
|
|
//static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
//static pthread_cond_t prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER;
|
|
|
|
|
2010-05-01 11:51:56 +00:00
|
|
|
static volatile int seq_thread_shutdown = TRUE;
|
2009-01-12 19:02:08 +00:00
|
|
|
static volatile int seq_last_given_monoton_cfra = 0;
|
|
|
|
static int monoton_cfra = 0;
|
|
|
|
|
|
|
|
typedef struct PrefetchThread {
|
|
|
|
struct PrefetchThread *next, *prev;
|
|
|
|
|
|
|
|
Scene *scene;
|
|
|
|
struct PrefetchQueueElem *current;
|
|
|
|
pthread_t pthread;
|
|
|
|
int running;
|
|
|
|
|
|
|
|
} PrefetchThread;
|
|
|
|
|
|
|
|
typedef struct PrefetchQueueElem {
|
|
|
|
struct PrefetchQueueElem *next, *prev;
|
|
|
|
|
|
|
|
int rectx;
|
|
|
|
int recty;
|
2010-11-21 20:00:31 +00:00
|
|
|
float cfra;
|
2009-01-12 19:02:08 +00:00
|
|
|
int chanshown;
|
2010-11-01 18:55:12 +00:00
|
|
|
int preview_render_size;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
int monoton_cfra;
|
|
|
|
|
|
|
|
struct ImBuf * ibuf;
|
|
|
|
} PrefetchQueueElem;
|
|
|
|
|
2009-11-11 09:59:51 +00:00
|
|
|
#if 0
|
2009-01-12 19:02:08 +00:00
|
|
|
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(This->scene,
|
2009-06-08 20:08:19 +00:00
|
|
|
e->rectx, e->recty, e->cfra, e->chanshown,
|
2010-11-01 18:55:12 +00:00
|
|
|
e->preview_render_size);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-09-14 16:52:06 +00:00
|
|
|
static void seq_start_threads(Scene *scene)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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->scene= scene;
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-09-14 16:52:06 +00:00
|
|
|
static void seq_stop_threads()
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2010-03-22 09:30:00 +00:00
|
|
|
pthread_cond_broadcast(&wakeup_cond);
|
|
|
|
pthread_mutex_unlock(&wakeup_lock);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2009-11-11 09:59:51 +00:00
|
|
|
#endif
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
void give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
PrefetchQueueElem *e;
|
|
|
|
if (seq_thread_shutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
|
2010-11-21 20:00:31 +00:00
|
|
|
e->rectx = context.rectx;
|
|
|
|
e->recty = context.recty;
|
2009-01-12 19:02:08 +00:00
|
|
|
e->cfra = cfra;
|
|
|
|
e->chanshown = chanshown;
|
2010-11-21 20:00:31 +00:00
|
|
|
e->preview_render_size = context.preview_render_size;
|
2009-01-12 19:02:08 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-11-11 09:59:51 +00:00
|
|
|
#if 0
|
2009-09-14 16:52:06 +00:00
|
|
|
static void seq_wait_for_prefetch_ready()
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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");
|
|
|
|
}
|
2009-11-11 09:59:51 +00:00
|
|
|
#endif
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-11-21 20:00:31 +00:00
|
|
|
ImBuf *give_ibuf_seq_threaded(SeqRenderData context, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
PrefetchQueueElem *e = NULL;
|
|
|
|
int found_something = FALSE;
|
|
|
|
|
|
|
|
if (seq_thread_shutdown) {
|
2010-11-21 20:00:31 +00:00
|
|
|
return give_ibuf_seq(context, cfra, chanshown);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (!e) {
|
|
|
|
int success = FALSE;
|
|
|
|
pthread_mutex_lock(&queue_lock);
|
|
|
|
|
|
|
|
for (e = prefetch_done.first; e; e = e->next) {
|
|
|
|
if (cfra == e->cfra &&
|
2010-03-22 09:30:00 +00:00
|
|
|
chanshown == e->chanshown &&
|
2010-11-21 20:00:31 +00:00
|
|
|
context.rectx == e->rectx &&
|
|
|
|
context.recty == e->recty &&
|
|
|
|
context.preview_render_size == e->preview_render_size) {
|
2009-01-12 19:02:08 +00:00
|
|
|
success = TRUE;
|
|
|
|
found_something = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
for (e = prefetch_wait.first; e; e = e->next) {
|
|
|
|
if (cfra == e->cfra &&
|
2010-03-22 09:30:00 +00:00
|
|
|
chanshown == e->chanshown &&
|
2010-11-21 20:00:31 +00:00
|
|
|
context.rectx == e->rectx &&
|
|
|
|
context.recty == e->recty &&
|
|
|
|
context.preview_render_size == e->preview_render_size) {
|
2009-01-12 19:02:08 +00:00
|
|
|
found_something = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
PrefetchThread *tslot;
|
|
|
|
|
|
|
|
for(tslot = running_threads.first;
|
2010-03-22 09:30:00 +00:00
|
|
|
tslot; tslot= tslot->next) {
|
2009-01-12 19:02:08 +00:00
|
|
|
if (tslot->current &&
|
2010-03-22 09:30:00 +00:00
|
|
|
cfra == tslot->current->cfra &&
|
|
|
|
chanshown == tslot->current->chanshown &&
|
2010-11-21 20:00:31 +00:00
|
|
|
context.rectx == tslot->current->rectx &&
|
|
|
|
context.recty == tslot->current->recty &&
|
|
|
|
context.preview_render_size== tslot->current->preview_render_size){
|
2009-01-12 19:02:08 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
return e ? e->ibuf : NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Functions to free imbuf and anim data on changes */
|
|
|
|
|
|
|
|
static void free_anim_seq(Sequence *seq)
|
|
|
|
{
|
|
|
|
if(seq->anim) {
|
|
|
|
IMB_free_anim(seq->anim);
|
2011-02-13 10:52:18 +00:00
|
|
|
seq->anim = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-19 20:01:18 +00:00
|
|
|
void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
|
|
|
|
int keep_file_handles)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
2009-08-02 23:02:59 +00:00
|
|
|
|
|
|
|
if (check_mem_usage) {
|
|
|
|
/* 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) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
seq_stripelem_cache_cleanup();
|
2009-01-25 14:53:41 +00:00
|
|
|
|
|
|
|
for(seq= seqbase->first; seq; seq= seq->next) {
|
2009-01-12 19:02:08 +00:00
|
|
|
if(seq->strip) {
|
2010-07-19 20:01:18 +00:00
|
|
|
if(seq->type==SEQ_MOVIE && !keep_file_handles)
|
2009-01-12 19:02:08 +00:00
|
|
|
free_anim_seq(seq);
|
|
|
|
if(seq->type==SEQ_SPEED) {
|
2009-11-14 14:58:19 +00:00
|
|
|
sequence_effect_speed_rebuild_map(scene, seq, 1);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-25 14:53:41 +00:00
|
|
|
if(seq->type==SEQ_META) {
|
2010-10-30 21:55:17 +00:00
|
|
|
free_imbuf_seq(scene, &seq->seqbase, FALSE, keep_file_handles);
|
2009-08-02 23:02:59 +00:00
|
|
|
}
|
|
|
|
if(seq->type==SEQ_SCENE) {
|
|
|
|
/* FIXME: recurs downwards,
|
|
|
|
but do recurs protection somehow! */
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
|
|
|
|
{
|
|
|
|
Sequence *subseq;
|
2010-07-23 16:57:11 +00:00
|
|
|
int free_imbuf = 0;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* 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(scene, subseq, changed_seq, len_change, ibuf_change))
|
|
|
|
free_imbuf = TRUE;
|
|
|
|
|
|
|
|
if(seq->seq1)
|
|
|
|
if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change))
|
|
|
|
free_imbuf = TRUE;
|
|
|
|
if(seq->seq2 && (seq->seq2 != seq->seq1))
|
|
|
|
if(update_changed_seq_recurs(scene, 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(scene, seq->seq3, changed_seq, len_change, ibuf_change))
|
|
|
|
free_imbuf = TRUE;
|
|
|
|
|
|
|
|
if(free_imbuf) {
|
|
|
|
if(ibuf_change) {
|
|
|
|
if(seq->type == SEQ_MOVIE)
|
|
|
|
free_anim_seq(seq);
|
|
|
|
if(seq->type == SEQ_SPEED) {
|
2009-11-14 14:58:19 +00:00
|
|
|
sequence_effect_speed_rebuild_map(scene, seq, 1);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(len_change)
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return free_imbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change)
|
|
|
|
{
|
2009-01-28 22:36:34 +00:00
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
2009-01-12 19:02:08 +00:00
|
|
|
Sequence *seq;
|
|
|
|
|
2009-01-28 22:36:34 +00:00
|
|
|
if (ed==NULL) return;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
for (seq=ed->seqbase.first; seq; seq=seq->next)
|
|
|
|
update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
|
|
|
|
}
|
|
|
|
|
2009-01-21 07:01:20 +00:00
|
|
|
/* seq funcs's for transforming internally
|
|
|
|
notice the difference between start/end and left/right.
|
|
|
|
|
|
|
|
left and right are the bounds at which the sequence is rendered,
|
|
|
|
start and end are from the start and fixed length of the sequence.
|
|
|
|
*/
|
2011-09-28 05:53:40 +00:00
|
|
|
int seq_tx_get_start(Sequence *seq)
|
|
|
|
{
|
2009-01-21 07:01:20 +00:00
|
|
|
return seq->start;
|
|
|
|
}
|
|
|
|
int seq_tx_get_end(Sequence *seq)
|
|
|
|
{
|
|
|
|
return seq->start+seq->len;
|
|
|
|
}
|
|
|
|
|
|
|
|
int seq_tx_get_final_left(Sequence *seq, int metaclip)
|
|
|
|
{
|
|
|
|
if (metaclip && seq->tmp) {
|
|
|
|
/* return the range clipped by the parents range */
|
|
|
|
return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) );
|
|
|
|
} else {
|
|
|
|
return (seq->start - seq->startstill) + seq->startofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
int seq_tx_get_final_right(Sequence *seq, int metaclip)
|
|
|
|
{
|
|
|
|
if (metaclip && seq->tmp) {
|
|
|
|
/* return the range clipped by the parents range */
|
|
|
|
return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) );
|
|
|
|
} else {
|
|
|
|
return ((seq->start+seq->len) + seq->endstill) - seq->endofs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_tx_set_final_left(Sequence *seq, int val)
|
|
|
|
{
|
|
|
|
if (val < (seq)->start) {
|
|
|
|
seq->startstill = abs(val - (seq)->start);
|
2009-10-19 10:07:19 +00:00
|
|
|
seq->startofs = 0;
|
2009-01-21 07:01:20 +00:00
|
|
|
} else {
|
|
|
|
seq->startofs = abs(val - (seq)->start);
|
|
|
|
seq->startstill = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_tx_set_final_right(Sequence *seq, int val)
|
|
|
|
{
|
|
|
|
if (val > (seq)->start + (seq)->len) {
|
|
|
|
seq->endstill = abs(val - (seq->start + (seq)->len));
|
2009-10-19 10:07:19 +00:00
|
|
|
seq->endofs = 0;
|
2009-01-21 07:01:20 +00:00
|
|
|
} else {
|
|
|
|
seq->endofs = abs(val - ((seq)->start + (seq)->len));
|
|
|
|
seq->endstill = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* used so we can do a quick check for single image seq
|
|
|
|
since they work a bit differently to normal image seq's (during transform) */
|
2009-12-15 11:27:46 +00:00
|
|
|
int seq_single_check(Sequence *seq)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
2011-05-16 17:14:47 +00:00
|
|
|
return (seq->len==1 && (
|
|
|
|
seq->type == SEQ_IMAGE
|
|
|
|
|| ((seq->type & SEQ_EFFECT) &&
|
|
|
|
get_sequence_effect_num_inputs(seq->type) == 0)));
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
2009-12-17 23:29:11 +00:00
|
|
|
/* check if the selected seq's reference unselected seq's */
|
|
|
|
int seqbase_isolated_sel_check(ListBase *seqbase)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
/* is there more than 1 select */
|
|
|
|
int ok= FALSE;
|
|
|
|
|
|
|
|
for(seq= seqbase->first; seq; seq= seq->next) {
|
|
|
|
if(seq->flag & SELECT) {
|
|
|
|
ok= TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok == FALSE)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* test relationships */
|
|
|
|
for(seq= seqbase->first; seq; seq= seq->next) {
|
2010-10-30 21:55:17 +00:00
|
|
|
if((seq->type & SEQ_EFFECT)==0)
|
|
|
|
continue;
|
|
|
|
|
2009-12-17 23:29:11 +00:00
|
|
|
if(seq->flag & SELECT) {
|
2010-10-30 21:55:17 +00:00
|
|
|
if( (seq->seq1 && (seq->seq1->flag & SELECT)==0) ||
|
|
|
|
(seq->seq2 && (seq->seq2->flag & SELECT)==0) ||
|
|
|
|
(seq->seq3 && (seq->seq3->flag & SELECT)==0) )
|
|
|
|
return FALSE;
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
else {
|
|
|
|
if( (seq->seq1 && (seq->seq1->flag & SELECT)) ||
|
|
|
|
(seq->seq2 && (seq->seq2->flag & SELECT)) ||
|
|
|
|
(seq->seq3 && (seq->seq3->flag & SELECT)) )
|
|
|
|
return FALSE;
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-01-21 07:01:20 +00:00
|
|
|
/* use to impose limits when dragging/extending - so impossible situations dont happen
|
|
|
|
* Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */
|
|
|
|
void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
|
|
|
|
{
|
|
|
|
if(leftflag) {
|
|
|
|
if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) {
|
|
|
|
seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1);
|
|
|
|
}
|
|
|
|
|
2009-12-15 11:27:46 +00:00
|
|
|
if (seq_single_check(seq)==0) {
|
2009-01-21 07:01:20 +00:00
|
|
|
if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) {
|
|
|
|
seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dosnt work now - TODO */
|
|
|
|
/*
|
|
|
|
if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) {
|
|
|
|
int ofs;
|
|
|
|
ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0);
|
|
|
|
seq->start -= ofs;
|
|
|
|
seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs );
|
|
|
|
}*/
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rightflag) {
|
|
|
|
if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) {
|
|
|
|
seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1);
|
|
|
|
}
|
|
|
|
|
2009-12-15 11:27:46 +00:00
|
|
|
if (seq_single_check(seq)==0) {
|
2009-01-21 07:01:20 +00:00
|
|
|
if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) {
|
|
|
|
seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sounds cannot be extended past their endpoints */
|
2009-08-09 21:16:39 +00:00
|
|
|
if (seq->type == SEQ_SOUND) {
|
2009-01-21 07:01:20 +00:00
|
|
|
seq->startstill= 0;
|
|
|
|
seq->endstill= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-15 11:27:46 +00:00
|
|
|
void seq_single_fix(Sequence *seq)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
int left, start, offset;
|
2009-12-15 11:27:46 +00:00
|
|
|
if (!seq_single_check(seq))
|
2009-01-21 07:01:20 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* make sure the image is always at the start since there is only one,
|
|
|
|
adjusting its start should be ok */
|
|
|
|
left = seq_tx_get_final_left(seq, 0);
|
|
|
|
start = seq->start;
|
|
|
|
if (start != left) {
|
|
|
|
offset = left - start;
|
|
|
|
seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset );
|
|
|
|
seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset );
|
|
|
|
seq->start += offset;
|
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int seq_tx_test(Sequence * seq)
|
|
|
|
{
|
|
|
|
return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0);
|
|
|
|
}
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2009-10-22 14:40:32 +00:00
|
|
|
static int seq_overlap(Sequence *seq1, Sequence *seq2)
|
|
|
|
{
|
2010-10-30 21:55:17 +00:00
|
|
|
return (seq1 != seq2 && seq1->machine == seq2->machine &&
|
|
|
|
((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0);
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
2009-01-25 14:53:41 +00:00
|
|
|
int seq_test_overlap(ListBase * seqbasep, Sequence *test)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
seq= seqbasep->first;
|
|
|
|
while(seq) {
|
2009-10-22 14:40:32 +00:00
|
|
|
if(seq_overlap(test, seq))
|
|
|
|
return 1;
|
|
|
|
|
2009-01-25 14:53:41 +00:00
|
|
|
seq= seq->next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-04 17:02:32 +00:00
|
|
|
void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2009-12-21 16:57:39 +00:00
|
|
|
seq_offset_animdata(evil_scene, seq, delta);
|
2009-01-25 14:53:41 +00:00
|
|
|
seq->start += delta;
|
2009-12-21 16:57:39 +00:00
|
|
|
|
2009-01-25 14:53:41 +00:00
|
|
|
if(seq->type==SEQ_META) {
|
|
|
|
Sequence *seq_child;
|
|
|
|
for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) {
|
2009-12-21 16:57:39 +00:00
|
|
|
seq_translate(evil_scene, seq_child, delta);
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(evil_scene, seq);
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
2011-04-01 08:51:12 +00:00
|
|
|
void seq_sound_init(Scene *scene, Sequence *seq)
|
|
|
|
{
|
|
|
|
if(seq->type==SEQ_META) {
|
|
|
|
Sequence *seq_child;
|
|
|
|
for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) {
|
|
|
|
seq_sound_init(scene, seq_child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(seq->sound) {
|
|
|
|
seq->scene_sound = sound_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
|
|
|
|
}
|
|
|
|
if(seq->scene) {
|
|
|
|
sound_scene_add_scene_sound(scene, seq, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-17 22:34:41 +00:00
|
|
|
Sequence *seq_foreground_frame_get(Scene *scene, int frame)
|
|
|
|
{
|
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
|
|
|
Sequence *seq, *best_seq=NULL;
|
|
|
|
int best_machine = -1;
|
|
|
|
|
|
|
|
if(!ed) return NULL;
|
|
|
|
|
|
|
|
for (seq=ed->seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
|
|
|
|
continue;
|
|
|
|
/* only use elements you can see - not */
|
2011-08-29 15:01:55 +00:00
|
|
|
if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
|
2011-02-17 22:34:41 +00:00
|
|
|
if (seq->machine > best_machine) {
|
|
|
|
best_seq = seq;
|
|
|
|
best_machine = seq->machine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return best_seq;
|
|
|
|
}
|
|
|
|
|
2009-01-25 14:53:41 +00:00
|
|
|
/* return 0 if there werent enough space */
|
2009-12-21 16:57:39 +00:00
|
|
|
int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
|
|
|
int orig_machine= test->machine;
|
|
|
|
test->machine++;
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence(evil_scene, test);
|
2009-01-25 14:53:41 +00:00
|
|
|
while( seq_test_overlap(seqbasep, test) ) {
|
|
|
|
if(test->machine >= MAXSEQ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
test->machine++;
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence(evil_scene, test); // XXX - I dont think this is needed since were only moving vertically, Campbell.
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(test->machine >= MAXSEQ) {
|
|
|
|
/* Blender 2.4x would remove the strip.
|
|
|
|
* nicer to move it to the end */
|
|
|
|
|
|
|
|
Sequence *seq;
|
|
|
|
int new_frame= test->enddisp;
|
|
|
|
|
|
|
|
for(seq= seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if (seq->machine == orig_machine)
|
|
|
|
new_frame = MAX2(new_frame, seq->enddisp);
|
|
|
|
}
|
|
|
|
|
|
|
|
test->machine= orig_machine;
|
|
|
|
new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */
|
2009-12-21 16:57:39 +00:00
|
|
|
seq_translate(evil_scene, test, new_frame - test->start);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence(evil_scene, test);
|
2009-01-25 14:53:41 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2009-10-22 14:40:32 +00:00
|
|
|
static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir)
|
|
|
|
{
|
|
|
|
int offset= 0;
|
|
|
|
Sequence *seq, *seq_other;
|
|
|
|
|
|
|
|
for(seq= seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->tmp) {
|
|
|
|
for(seq_other= seqbasep->first; seq_other; seq_other= seq_other->next) {
|
2009-10-27 02:54:25 +00:00
|
|
|
if(!seq_other->tmp && seq_overlap(seq, seq_other)) {
|
2009-10-22 14:40:32 +00:00
|
|
|
if(dir=='L') {
|
|
|
|
offset= MIN2(offset, seq_other->startdisp - seq->enddisp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset= MAX2(offset, seq_other->enddisp - seq->startdisp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
static int shuffle_seq_time_offset(Scene* scene, ListBase * seqbasep, char dir)
|
2009-10-22 14:40:32 +00:00
|
|
|
{
|
|
|
|
int ofs= 0;
|
|
|
|
int tot_ofs= 0;
|
|
|
|
Sequence *seq;
|
|
|
|
while( (ofs= shuffle_seq_time_offset_test(seqbasep, dir)) ) {
|
|
|
|
for(seq= seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->tmp) {
|
|
|
|
/* seq_test_overlap only tests display values */
|
|
|
|
seq->startdisp += ofs;
|
|
|
|
seq->enddisp += ofs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tot_ofs+= ofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(seq= seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->tmp)
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(scene, seq); /* corrects dummy startdisp/enddisp values */
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return tot_ofs;
|
|
|
|
}
|
|
|
|
|
2009-12-21 16:57:39 +00:00
|
|
|
int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
|
2009-10-22 14:40:32 +00:00
|
|
|
{
|
|
|
|
/* note: seq->tmp is used to tag strips to move */
|
|
|
|
|
|
|
|
Sequence *seq;
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
int offset_l = shuffle_seq_time_offset(evil_scene, seqbasep, 'L');
|
|
|
|
int offset_r = shuffle_seq_time_offset(evil_scene, seqbasep, 'R');
|
2009-10-22 14:40:32 +00:00
|
|
|
int offset = (-offset_l < offset_r) ? offset_l:offset_r;
|
|
|
|
|
|
|
|
if(offset) {
|
|
|
|
for(seq= seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->tmp) {
|
2009-12-21 16:57:39 +00:00
|
|
|
seq_translate(evil_scene, seq, offset);
|
2009-10-22 14:40:32 +00:00
|
|
|
seq->flag &= ~SEQ_OVERLAP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset? 0:1;
|
|
|
|
}
|
|
|
|
|
2011-08-07 11:54:58 +00:00
|
|
|
void seq_update_sound_bounds_all(Scene *scene)
|
|
|
|
{
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
|
2011-08-28 14:21:44 +00:00
|
|
|
if(ed) {
|
2011-08-07 11:54:58 +00:00
|
|
|
Sequence *seq;
|
|
|
|
|
2011-08-28 14:21:44 +00:00
|
|
|
for(seq = ed->seqbase.first; seq; seq = seq->next) {
|
|
|
|
if(seq->type == SEQ_META) {
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
|
|
|
}
|
2011-08-28 14:21:44 +00:00
|
|
|
else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_sound_bounds(scene, seq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-26 13:56:31 +00:00
|
|
|
void seq_update_sound_bounds(Scene* scene, Sequence *seq)
|
2009-08-09 21:16:39 +00:00
|
|
|
{
|
2011-08-28 14:21:44 +00:00
|
|
|
if(seq->scene_sound) {
|
2010-02-07 23:41:17 +00:00
|
|
|
sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
|
2009-12-08 13:57:51 +00:00
|
|
|
/* mute is set in seq_update_muting_recursive */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-07 11:54:58 +00:00
|
|
|
static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute)
|
2009-12-08 13:57:51 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
int seqmute;
|
|
|
|
|
|
|
|
/* for sound we go over full meta tree to update muted state,
|
|
|
|
since sound is played outside of evaluating the imbufs, */
|
|
|
|
for(seq=seqbasep->first; seq; seq=seq->next) {
|
|
|
|
seqmute= (mute || (seq->flag & SEQ_MUTE));
|
|
|
|
|
|
|
|
if(seq->type == SEQ_META) {
|
|
|
|
/* if this is the current meta sequence, unmute because
|
|
|
|
all sequences above this were set to mute */
|
|
|
|
if(seq == metaseq)
|
|
|
|
seqmute= 0;
|
|
|
|
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute);
|
2009-12-08 13:57:51 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
else if(ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) {
|
2010-02-07 23:41:17 +00:00
|
|
|
if(seq->scene_sound) {
|
2011-08-07 11:54:58 +00:00
|
|
|
sound_mute_scene_sound(seq->scene_sound, seqmute);
|
2009-12-08 13:57:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-07 11:54:58 +00:00
|
|
|
void seq_update_muting(Editing *ed)
|
2009-12-08 13:57:51 +00:00
|
|
|
{
|
|
|
|
if(ed) {
|
|
|
|
/* mute all sounds up to current metastack list */
|
|
|
|
MetaStack *ms= ed->metastack.last;
|
|
|
|
|
|
|
|
if(ms)
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1);
|
2009-12-08 13:57:51 +00:00
|
|
|
else
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_muting_recursive(&ed->seqbase, NULL, 0);
|
2009-08-09 21:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2011-07-26 13:56:31 +00:00
|
|
|
static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound *sound)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
for(seq=seqbasep->first; seq; seq=seq->next) {
|
|
|
|
if(seq->type == SEQ_META) {
|
|
|
|
seq_update_sound_recursive(scene, &seq->seqbase, sound);
|
|
|
|
}
|
|
|
|
else if(seq->type == SEQ_SOUND) {
|
|
|
|
if(seq->scene_sound && sound == seq->sound) {
|
|
|
|
sound_update_scene_sound(seq->scene_sound, sound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void seq_update_sound(struct Scene *scene, struct bSound *sound)
|
|
|
|
{
|
|
|
|
if(scene->ed) {
|
|
|
|
seq_update_sound_recursive(scene, &scene->ed->seqbase, sound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-16 16:35:31 +00:00
|
|
|
/* in cases where we done know the sequence's listbase */
|
|
|
|
ListBase *seq_seqbase(ListBase *seqbase, Sequence *seq)
|
|
|
|
{
|
|
|
|
Sequence *iseq;
|
|
|
|
ListBase *lb= NULL;
|
|
|
|
|
|
|
|
for(iseq= seqbase->first; iseq; iseq= iseq->next) {
|
|
|
|
if(seq==iseq) {
|
|
|
|
return seqbase;
|
|
|
|
}
|
|
|
|
else if(iseq->seqbase.first && (lb= seq_seqbase(&iseq->seqbase, seq))) {
|
|
|
|
return lb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-12-09 16:46:41 +00:00
|
|
|
|
2011-05-16 17:14:47 +00:00
|
|
|
Sequence *seq_metastrip(ListBase * seqbase, Sequence * meta, Sequence *seq)
|
|
|
|
{
|
|
|
|
Sequence * iseq;
|
|
|
|
|
|
|
|
for(iseq = seqbase->first; iseq; iseq = iseq->next) {
|
|
|
|
Sequence * rval;
|
|
|
|
|
|
|
|
if (seq == iseq) {
|
|
|
|
return meta;
|
|
|
|
} else if(iseq->seqbase.first &&
|
|
|
|
(rval = seq_metastrip(&iseq->seqbase, iseq, seq))) {
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-28 09:59:34 +00:00
|
|
|
int seq_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str)
|
2010-06-21 17:37:50 +00:00
|
|
|
{
|
2010-07-07 13:14:51 +00:00
|
|
|
char name[sizeof(seq_a->name)];
|
|
|
|
|
2011-07-19 01:36:59 +00:00
|
|
|
if(seq_a->len != seq_b->len) {
|
2011-05-28 09:59:34 +00:00
|
|
|
*error_str= "Strips must be the same length";
|
2010-06-21 17:37:50 +00:00
|
|
|
return 0;
|
2011-07-19 01:36:59 +00:00
|
|
|
}
|
2010-06-21 17:37:50 +00:00
|
|
|
|
|
|
|
/* type checking, could be more advanced but disalow sound vs non-sound copy */
|
|
|
|
if(seq_a->type != seq_b->type) {
|
|
|
|
if(seq_a->type == SEQ_SOUND || seq_b->type == SEQ_SOUND) {
|
2011-05-28 09:59:34 +00:00
|
|
|
*error_str= "Strips were not compatible";
|
2010-06-21 17:37:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-07-07 13:14:51 +00:00
|
|
|
|
|
|
|
/* disallow effects to swap with non-effects strips */
|
|
|
|
if((seq_a->type & SEQ_EFFECT) != (seq_b->type & SEQ_EFFECT)) {
|
2011-05-28 09:59:34 +00:00
|
|
|
*error_str= "Strips were not compatible";
|
2010-07-07 13:14:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((seq_a->type & SEQ_EFFECT) && (seq_b->type & SEQ_EFFECT)) {
|
|
|
|
if(get_sequence_effect_num_inputs(seq_a->type) != get_sequence_effect_num_inputs(seq_b->type)) {
|
2011-05-28 09:59:34 +00:00
|
|
|
*error_str= "Strips must have the same number of inputs";
|
2010-07-07 13:14:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2010-06-21 17:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWAP(Sequence, *seq_a, *seq_b);
|
2010-07-07 13:14:51 +00:00
|
|
|
|
|
|
|
/* swap back names so animation fcurves dont get swapped */
|
|
|
|
strcpy(name, seq_a->name+2);
|
|
|
|
strcpy(seq_a->name+2, seq_b->name+2);
|
|
|
|
strcpy(seq_b->name+2, name);
|
|
|
|
|
|
|
|
/* swap back opacity, and overlay mode */
|
|
|
|
SWAP(int, seq_a->blend_mode, seq_b->blend_mode);
|
|
|
|
SWAP(float, seq_a->blend_opacity, seq_b->blend_opacity);
|
|
|
|
|
|
|
|
|
2010-06-21 17:37:50 +00:00
|
|
|
SWAP(void *, seq_a->prev, seq_b->prev);
|
|
|
|
SWAP(void *, seq_a->next, seq_b->next);
|
|
|
|
SWAP(int, seq_a->start, seq_b->start);
|
|
|
|
SWAP(int, seq_a->startofs, seq_b->startofs);
|
|
|
|
SWAP(int, seq_a->endofs, seq_b->endofs);
|
|
|
|
SWAP(int, seq_a->startstill, seq_b->startstill);
|
|
|
|
SWAP(int, seq_a->endstill, seq_b->endstill);
|
|
|
|
SWAP(int, seq_a->machine, seq_b->machine);
|
2010-06-21 22:05:34 +00:00
|
|
|
SWAP(int, seq_a->startdisp, seq_b->startdisp);
|
|
|
|
SWAP(int, seq_a->enddisp, seq_b->enddisp);
|
2010-06-21 17:37:50 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-12-09 16:46:41 +00:00
|
|
|
/* XXX - hackish function needed for transforming strips! TODO - have some better solution */
|
|
|
|
void seq_offset_animdata(Scene *scene, Sequence *seq, int ofs)
|
|
|
|
{
|
2009-12-09 18:08:14 +00:00
|
|
|
char str[32];
|
|
|
|
FCurve *fcu;
|
|
|
|
|
2010-01-10 19:19:22 +00:00
|
|
|
if(scene->adt==NULL || ofs==0 || scene->adt->action==NULL)
|
2009-12-09 16:46:41 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
sprintf(str, "[\"%s\"]", seq->name+2);
|
|
|
|
|
|
|
|
for (fcu= scene->adt->action->curves.first; fcu; fcu= fcu->next) {
|
|
|
|
if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
|
2010-10-21 08:32:53 +00:00
|
|
|
unsigned int i;
|
2009-12-09 16:46:41 +00:00
|
|
|
for (i = 0; i < fcu->totvert; i++) {
|
|
|
|
BezTriple *bezt= &fcu->bezt[i];
|
|
|
|
bezt->vec[0][0] += ofs;
|
|
|
|
bezt->vec[1][0] += ofs;
|
|
|
|
bezt->vec[2][0] += ofs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-07 16:17:18 +00:00
|
|
|
void seq_dupe_animdata(Scene *scene, char *name_from, char *name_to)
|
|
|
|
{
|
|
|
|
char str_from[32];
|
|
|
|
FCurve *fcu;
|
|
|
|
FCurve *fcu_last;
|
|
|
|
FCurve *fcu_cpy;
|
|
|
|
ListBase lb= {NULL, NULL};
|
|
|
|
|
|
|
|
if(scene->adt==NULL || scene->adt->action==NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sprintf(str_from, "[\"%s\"]", name_from);
|
|
|
|
|
|
|
|
fcu_last= scene->adt->action->curves.last;
|
|
|
|
|
|
|
|
for (fcu= scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu= fcu->next) {
|
|
|
|
if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str_from)) {
|
|
|
|
fcu_cpy= copy_fcurve(fcu);
|
|
|
|
BLI_addtail(&lb, fcu_cpy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* notice validate is 0, keep this because the seq may not be added to the scene yet */
|
|
|
|
BKE_animdata_fix_paths_rename(&scene->id, scene->adt, "sequence_editor.sequences_all", name_from, name_to, 0, 0, 0);
|
|
|
|
|
|
|
|
/* add the original fcurves back */
|
2010-12-21 14:49:34 +00:00
|
|
|
BLI_movelisttolist(&scene->adt->action->curves, &lb);
|
2010-07-07 16:17:18 +00:00
|
|
|
}
|
|
|
|
|
2010-07-03 21:13:08 +00:00
|
|
|
/* XXX - hackish function needed to remove all fcurves belonging to a sequencer strip */
|
|
|
|
static void seq_free_animdata(Scene *scene, Sequence *seq)
|
|
|
|
{
|
|
|
|
char str[32];
|
|
|
|
FCurve *fcu;
|
|
|
|
|
|
|
|
if(scene->adt==NULL || scene->adt->action==NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sprintf(str, "[\"%s\"]", seq->name+2);
|
|
|
|
|
|
|
|
fcu= scene->adt->action->curves.first;
|
|
|
|
|
|
|
|
while (fcu) {
|
|
|
|
if(strstr(fcu->rna_path, "sequence_editor.sequences_all[") && strstr(fcu->rna_path, str)) {
|
|
|
|
FCurve *next_fcu = fcu->next;
|
|
|
|
|
|
|
|
BLI_remlink(&scene->adt->action->curves, fcu);
|
|
|
|
free_fcurve(fcu);
|
|
|
|
|
|
|
|
fcu = next_fcu;
|
|
|
|
} else {
|
|
|
|
fcu = fcu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-09 16:46:41 +00:00
|
|
|
|
2009-12-17 11:16:28 +00:00
|
|
|
Sequence *get_seq_by_name(ListBase *seqbase, const char *name, int recursive)
|
2009-12-17 04:55:15 +00:00
|
|
|
{
|
2009-12-17 11:16:28 +00:00
|
|
|
Sequence *iseq=NULL;
|
|
|
|
Sequence *rseq=NULL;
|
|
|
|
|
|
|
|
for (iseq=seqbase->first; iseq; iseq=iseq->next) {
|
|
|
|
if (strcmp(name, iseq->name+2) == 0)
|
|
|
|
return iseq;
|
|
|
|
else if(recursive && (iseq->seqbase.first) && (rseq=get_seq_by_name(&iseq->seqbase, name, 1))) {
|
|
|
|
return rseq;
|
|
|
|
}
|
2009-12-17 04:55:15 +00:00
|
|
|
}
|
2009-12-17 11:16:28 +00:00
|
|
|
|
|
|
|
return NULL;
|
2009-12-17 04:55:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-21 17:37:50 +00:00
|
|
|
Sequence *seq_active_get(Scene *scene)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
|
|
|
if(ed==NULL) return NULL;
|
|
|
|
return ed->act_seq;
|
|
|
|
}
|
|
|
|
|
2010-06-21 17:37:50 +00:00
|
|
|
void seq_active_set(Scene *scene, Sequence *seq)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
|
|
|
if(ed==NULL) return;
|
|
|
|
|
|
|
|
ed->act_seq= seq;
|
|
|
|
}
|
|
|
|
|
2010-06-21 17:37:50 +00:00
|
|
|
int seq_active_pair_get(Scene *scene, Sequence **seq_act, Sequence **seq_other)
|
|
|
|
{
|
|
|
|
Editing *ed= seq_give_editing(scene, FALSE);
|
|
|
|
|
|
|
|
*seq_act= seq_active_get(scene);
|
|
|
|
|
|
|
|
if(*seq_act == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
*seq_other= NULL;
|
|
|
|
|
|
|
|
for(seq= ed->seqbasep->first; seq; seq= seq->next) {
|
|
|
|
if(seq->flag & SELECT && (seq != (*seq_act))) {
|
|
|
|
if(*seq_other) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*seq_other= seq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*seq_other != NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
/* api like funcs for adding */
|
|
|
|
|
|
|
|
void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
|
|
|
|
{
|
|
|
|
if(seq) {
|
2010-07-02 20:09:42 +00:00
|
|
|
BLI_strncpy(seq->name+2, seq_load->name, sizeof(seq->name)-2);
|
2010-02-16 17:58:50 +00:00
|
|
|
seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
if(seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) {
|
|
|
|
seq_load->start_frame += (seq->enddisp - seq->startdisp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(seq_load->flag & SEQ_LOAD_REPLACE_SEL) {
|
2009-12-17 23:29:11 +00:00
|
|
|
seq_load->flag |= SELECT;
|
2010-06-21 17:37:50 +00:00
|
|
|
seq_active_set(scene, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
|
|
|
|
if(seq->sound)
|
2011-08-07 11:54:58 +00:00
|
|
|
sound_cache(seq->sound);
|
2009-11-14 19:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
seq_load->tot_success++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
seq_load->tot_error++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
seq= MEM_callocN( sizeof(Sequence), "addseq");
|
|
|
|
BLI_addtail(lb, seq);
|
|
|
|
|
|
|
|
*( (short *)seq->name )= ID_SEQ;
|
|
|
|
seq->name[2]= 0;
|
|
|
|
|
2009-12-17 23:29:11 +00:00
|
|
|
seq->flag= SELECT;
|
2009-11-14 19:26:58 +00:00
|
|
|
seq->start= cfra;
|
|
|
|
seq->machine= machine;
|
2010-07-13 09:31:28 +00:00
|
|
|
seq->sat= 1.0;
|
2009-11-14 19:26:58 +00:00
|
|
|
seq->mul= 1.0;
|
|
|
|
seq->blend_opacity = 100.0;
|
2010-02-07 23:41:17 +00:00
|
|
|
seq->volume = 1.0f;
|
3D Audio GSoC:
Implemented basic audio animation.
* AnimatableProperty: Propper cache writing and spline interpolation for reading (the solution for stair steps in audio animation)
* Animatable properties so far are: volume, pitch, panning
* Users note: Changing the pitch of a sound results in wrong seeking, due to the resulting playback length difference.
* Users note: Panning only works for mono sources, values are in the range [-2..2], this basically controls the angle of the sound, 0 is front, -1 left, 1 right and 2 and -2 are back. Typical stereo panning only supports [-1..1].
* Disabled animation of audio related ffmpeg output parameters.
* Scene Audio Panel: 3D Listener settings also for Renderer, new Volume property (animatable!), Update/Bake buttons for animation problems, moved sampling rate and channel count here
2011-07-28 13:58:59 +00:00
|
|
|
seq->pitch = 1.0f;
|
2011-02-22 16:32:05 +00:00
|
|
|
seq->scene_sound = NULL;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
return seq;
|
|
|
|
}
|
|
|
|
|
2010-01-28 19:18:35 +00:00
|
|
|
/* NOTE: this function doesn't fill in image names */
|
2009-11-14 19:26:58 +00:00
|
|
|
Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C); /* only for active seq */
|
|
|
|
Sequence *seq;
|
|
|
|
Strip *strip;
|
|
|
|
|
|
|
|
seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
|
|
|
|
seq->type= SEQ_IMAGE;
|
2010-07-04 08:49:54 +00:00
|
|
|
seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
|
2009-11-19 03:21:37 +00:00
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
/* basic defaults */
|
|
|
|
seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
|
|
|
|
|
|
|
|
strip->len = seq->len = seq_load->len ? seq_load->len : 1;
|
|
|
|
strip->us= 1;
|
2011-01-11 07:40:31 +00:00
|
|
|
strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
|
2010-07-02 20:09:42 +00:00
|
|
|
BLI_strncpy(strip->dir, seq_load->path, sizeof(strip->dir));
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
seq_load_apply(scene, seq, seq_load);
|
|
|
|
|
|
|
|
return seq;
|
|
|
|
}
|
|
|
|
|
2011-06-23 09:27:56 +00:00
|
|
|
#ifdef WITH_AUDASPACE
|
2009-11-14 19:26:58 +00:00
|
|
|
Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
|
|
|
{
|
2011-09-05 19:34:27 +00:00
|
|
|
Main *bmain= CTX_data_main(C);
|
2009-11-14 19:26:58 +00:00
|
|
|
Scene *scene= CTX_data_scene(C); /* only for sound */
|
|
|
|
Editing *ed= seq_give_editing(scene, TRUE);
|
|
|
|
bSound *sound;
|
|
|
|
|
|
|
|
Sequence *seq; /* generic strip vars */
|
|
|
|
Strip *strip;
|
|
|
|
StripElem *se;
|
|
|
|
|
|
|
|
AUD_SoundInfo info;
|
|
|
|
|
2010-06-25 12:04:04 +00:00
|
|
|
sound = sound_new_file(CTX_data_main(C), seq_load->path); /* handles relative paths */
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
if (sound==NULL || sound->playback_handle == NULL) {
|
2009-11-14 19:26:58 +00:00
|
|
|
//if(op)
|
|
|
|
// BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
info = AUD_getInfo(sound->playback_handle);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-01-01 05:09:30 +00:00
|
|
|
if (info.specs.channels == AUD_CHANNELS_INVALID) {
|
2011-09-05 19:34:27 +00:00
|
|
|
sound_delete(bmain, sound);
|
2009-11-14 19:26:58 +00:00
|
|
|
//if(op)
|
|
|
|
// BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
|
|
|
|
|
|
|
|
seq->type= SEQ_SOUND;
|
|
|
|
seq->sound= sound;
|
2009-11-19 03:21:37 +00:00
|
|
|
BLI_strncpy(seq->name+2, "Sound", SEQ_NAME_MAXSTR-2);
|
2010-02-16 17:58:50 +00:00
|
|
|
seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
/* basic defaults */
|
|
|
|
seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
|
2010-02-21 18:01:41 +00:00
|
|
|
strip->len = seq->len = ceil(info.length * FPS);
|
2009-11-14 19:26:58 +00:00
|
|
|
strip->us= 1;
|
|
|
|
|
2011-05-16 17:54:55 +00:00
|
|
|
/* we only need 1 element to store the filename */
|
|
|
|
strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-03-08 20:08:04 +00:00
|
|
|
BLI_split_dirfile(seq_load->path, strip->dir, se->name);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + strip->len, 0);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(scene, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
/* last active name */
|
2011-09-26 18:51:10 +00:00
|
|
|
BLI_strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
seq_load_apply(scene, seq, seq_load);
|
|
|
|
|
|
|
|
return seq;
|
|
|
|
}
|
2011-06-23 09:27:56 +00:00
|
|
|
#else // WITH_AUDASPACE
|
|
|
|
Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
|
|
|
{
|
|
|
|
(void)C;
|
|
|
|
(void)seqbasep;
|
|
|
|
(void)seq_load;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif // WITH_AUDASPACE
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C); /* only for sound */
|
2010-06-25 12:04:04 +00:00
|
|
|
char path[sizeof(seq_load->path)];
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2011-01-11 07:40:31 +00:00
|
|
|
Sequence *seq; /* generic strip vars */
|
2009-11-14 19:26:58 +00:00
|
|
|
Strip *strip;
|
|
|
|
StripElem *se;
|
|
|
|
|
|
|
|
struct anim *an;
|
|
|
|
|
2010-06-25 12:04:04 +00:00
|
|
|
BLI_strncpy(path, seq_load->path, sizeof(path));
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_abs(path, G.main->name);
|
2010-06-25 12:04:04 +00:00
|
|
|
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
an = openanim(path, IB_rect, 0);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
if(an==NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel);
|
|
|
|
seq->type= SEQ_MOVIE;
|
2010-07-04 08:49:54 +00:00
|
|
|
seq->blend_mode= SEQ_CROSS; /* so alpha adjustment fade to the strip below */
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
seq->anim= an;
|
|
|
|
seq->anim_preseek = IMB_anim_get_preseek(an);
|
2009-11-19 03:21:37 +00:00
|
|
|
BLI_strncpy(seq->name+2, "Movie", SEQ_NAME_MAXSTR-2);
|
2010-02-16 17:58:50 +00:00
|
|
|
seqbase_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
/* basic defaults */
|
|
|
|
seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
|
== Sequencer ==
This patch adds:
* support for proxy building again (missing feature from Blender 2.49)
additionally to the way, Blender 2.49 worked, you can select several
strips at once and make Blender build proxies in the background (using
the job system)
Also a new thing: movie proxies are now build into AVI files, and
the proxy system is moved into ImBuf-library, so that other parts
of blender can also benefit from it.
* Timecode support: to fix seeking issues with files, that have
a) varying frame rates
b) very large GOP lengths
c) are broken inbetween
d) use different time code tracks
the proxy builder can now also build timecode indices, which are
used (optionally) for seeking.
For the first time, it is possible, to do frame exact seeking on
all file types.
* Support for different video-streams in one video file (can be
selected in sequencer, other parts of blender can also use it,
but UI has to be added accordingly)
* IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since
older versions don't support the pkt_pts field, that is essential
for building timecode indices.
Windows and Mac libs are already updated, Linux-users have to build
their own ffmpeg verions until distros keep up.
2011-08-28 14:46:03 +00:00
|
|
|
strip->len = seq->len = IMB_anim_get_duration( an, IMB_TC_RECORD_RUN );
|
2009-11-14 19:26:58 +00:00
|
|
|
strip->us= 1;
|
|
|
|
|
2011-05-16 17:54:55 +00:00
|
|
|
/* we only need 1 element for MOVIE strips */
|
|
|
|
strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-03-08 20:08:04 +00:00
|
|
|
BLI_split_dirfile(seq_load->path, strip->dir, se->name);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2010-02-07 23:41:17 +00:00
|
|
|
calc_sequence_disp(scene, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
if(seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
|
|
|
|
int start_frame_back= seq_load->start_frame;
|
|
|
|
seq_load->channel++;
|
|
|
|
|
2011-01-11 07:40:31 +00:00
|
|
|
sequencer_add_sound_strip(C, seqbasep, seq_load);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
seq_load->start_frame= start_frame_back;
|
|
|
|
seq_load->channel--;
|
|
|
|
}
|
|
|
|
|
2010-07-02 20:09:42 +00:00
|
|
|
if(seq_load->name[0] == '\0')
|
|
|
|
BLI_strncpy(seq_load->name, se->name, sizeof(seq_load->name));
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
/* can be NULL */
|
|
|
|
seq_load_apply(scene, seq, seq_load);
|
|
|
|
|
|
|
|
return seq;
|
|
|
|
}
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
|
2010-10-04 15:31:04 +00:00
|
|
|
static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag)
|
2010-06-24 10:04:18 +00:00
|
|
|
{
|
2010-10-04 15:31:04 +00:00
|
|
|
Scene *sce_audio= scene_to ? scene_to : scene;
|
2010-06-24 10:04:18 +00:00
|
|
|
Sequence *seqn = MEM_dupallocN(seq);
|
|
|
|
|
|
|
|
seq->tmp = seqn;
|
|
|
|
seqn->strip= MEM_dupallocN(seq->strip);
|
|
|
|
|
|
|
|
// XXX: add F-Curve duplication stuff?
|
|
|
|
|
|
|
|
if (seq->strip->crop) {
|
|
|
|
seqn->strip->crop = MEM_dupallocN(seq->strip->crop);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->strip->transform) {
|
|
|
|
seqn->strip->transform = MEM_dupallocN(seq->strip->transform);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->strip->proxy) {
|
|
|
|
seqn->strip->proxy = MEM_dupallocN(seq->strip->proxy);
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->proxy->anim = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->strip->color_balance) {
|
|
|
|
seqn->strip->color_balance
|
|
|
|
= MEM_dupallocN(seq->strip->color_balance);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(seq->type==SEQ_META) {
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->seqbase.first= seqn->seqbase.last= NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
/* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
|
|
|
|
/* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
|
|
|
|
} else if(seq->type == SEQ_SCENE) {
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
if(seq->scene_sound)
|
2010-10-04 15:31:04 +00:00
|
|
|
seqn->scene_sound = sound_scene_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
|
2010-06-24 10:04:18 +00:00
|
|
|
} else if(seq->type == SEQ_MOVIE) {
|
|
|
|
seqn->strip->stripdata =
|
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->anim= NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
} else if(seq->type == SEQ_SOUND) {
|
|
|
|
seqn->strip->stripdata =
|
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
|
|
|
if(seq->scene_sound)
|
2010-10-04 15:31:04 +00:00
|
|
|
seqn->scene_sound = sound_add_scene_sound(sce_audio, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
seqn->sound->id.us++;
|
|
|
|
} else if(seq->type == SEQ_IMAGE) {
|
|
|
|
seqn->strip->stripdata =
|
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
|
|
|
} else if(seq->type >= SEQ_EFFECT) {
|
|
|
|
if(seq->seq1 && seq->seq1->tmp) seqn->seq1= seq->seq1->tmp;
|
|
|
|
if(seq->seq2 && seq->seq2->tmp) seqn->seq2= seq->seq2->tmp;
|
|
|
|
if(seq->seq3 && seq->seq3->tmp) seqn->seq3= seq->seq3->tmp;
|
|
|
|
|
|
|
|
if (seq->type & SEQ_EFFECT) {
|
|
|
|
struct SeqEffectHandle sh;
|
|
|
|
sh = get_sequence_effect(seq);
|
|
|
|
if(sh.copy)
|
|
|
|
sh.copy(seq, seqn);
|
|
|
|
}
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Aiiiiekkk! sequence type not "
|
|
|
|
"handled in duplicate!\nExpect a crash"
|
|
|
|
" now...\n");
|
|
|
|
}
|
|
|
|
|
2010-07-07 16:37:41 +00:00
|
|
|
if(dupe_flag & SEQ_DUPE_UNIQUE_NAME)
|
2010-06-25 12:04:04 +00:00
|
|
|
seqbase_unique_name_recursive(&scene->ed->seqbase, seqn);
|
2010-07-07 16:17:18 +00:00
|
|
|
|
|
|
|
if(dupe_flag & SEQ_DUPE_ANIM)
|
|
|
|
seq_dupe_animdata(scene, seq->name+2, seqn->name+2);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
return seqn;
|
|
|
|
}
|
|
|
|
|
2010-10-04 15:31:04 +00:00
|
|
|
Sequence * seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence * seq, int dupe_flag)
|
2010-06-24 10:04:18 +00:00
|
|
|
{
|
2010-10-04 15:31:04 +00:00
|
|
|
Sequence * seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
|
2010-06-24 10:04:18 +00:00
|
|
|
if (seq->type == SEQ_META) {
|
2010-06-25 12:04:04 +00:00
|
|
|
Sequence *s;
|
2010-06-24 10:04:18 +00:00
|
|
|
for(s= seq->seqbase.first; s; s = s->next) {
|
2010-10-04 15:31:04 +00:00
|
|
|
Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag);
|
2010-06-24 10:04:18 +00:00
|
|
|
if (n) {
|
|
|
|
BLI_addtail(&seqn->seqbase, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return seqn;
|
|
|
|
}
|
|
|
|
|
2010-10-04 15:31:04 +00:00
|
|
|
void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag)
|
2010-06-24 10:04:18 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
2011-02-13 10:52:18 +00:00
|
|
|
Sequence *seqn = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
Sequence *last_seq = seq_active_get(scene);
|
|
|
|
|
|
|
|
for(seq= seqbase->first; seq; seq= seq->next) {
|
|
|
|
seq->tmp= NULL;
|
2010-07-08 14:30:43 +00:00
|
|
|
if((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) {
|
2010-10-04 15:31:04 +00:00
|
|
|
seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
|
2010-06-24 10:04:18 +00:00
|
|
|
if (seqn) { /*should never fail */
|
2010-06-25 12:04:04 +00:00
|
|
|
if(dupe_flag & SEQ_DUPE_CONTEXT) {
|
2010-06-24 10:04:18 +00:00
|
|
|
seq->flag &= ~SEQ_ALLSEL;
|
|
|
|
seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL+SEQ_LOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_addtail(nseqbase, seqn);
|
|
|
|
if(seq->type==SEQ_META)
|
2010-10-04 15:31:04 +00:00
|
|
|
seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2010-06-25 12:04:04 +00:00
|
|
|
if(dupe_flag & SEQ_DUPE_CONTEXT) {
|
2010-06-24 10:04:18 +00:00
|
|
|
if (seq == last_seq) {
|
|
|
|
seq_active_set(scene, seqn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|