2011-02-23 10:52:22 +00:00
|
|
|
/*
|
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"
|
|
|
|
|
|
|
|
#include "DNA_sequence_types.h"
|
2012-03-21 18:02:29 +00:00
|
|
|
#include "DNA_movieclip_types.h"
|
2012-06-07 18:24:36 +00:00
|
|
|
#include "DNA_mask_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"
|
2013-07-15 11:26:43 +00:00
|
|
|
#include "BLI_string_utf8.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_threads.h"
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
#ifdef WIN32
|
|
|
|
# include "BLI_winstuff.h"
|
|
|
|
#else
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2012-10-26 17:32:50 +00:00
|
|
|
#include "BLF_translation.h"
|
|
|
|
|
2010-07-07 16:17:18 +00:00
|
|
|
#include "BKE_animsys.h"
|
2013-12-26 17:24:42 +06:00
|
|
|
#include "BKE_depsgraph.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"
|
2012-03-21 18:02:29 +00:00
|
|
|
#include "BKE_movieclip.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"
|
2012-06-07 18:24:36 +00:00
|
|
|
#include "BKE_mask.h"
|
2013-07-24 06:51:04 +00:00
|
|
|
#include "BKE_library.h"
|
2015-04-02 21:05:12 +11:00
|
|
|
#include "BKE_idprop.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2011-10-22 01:53:35 +00:00
|
|
|
#include "RNA_access.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"
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
#include "IMB_colormanagement.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
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown);
|
|
|
|
static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra);
|
2011-05-16 17:14:47 +00:00
|
|
|
static void seq_free_animdata(Scene *scene, Sequence *seq);
|
2014-03-20 15:45:20 +06:00
|
|
|
static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr, bool make_float);
|
2015-04-06 10:40:12 -03:00
|
|
|
static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview);
|
|
|
|
static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id);
|
2011-05-16 17:14:47 +00:00
|
|
|
|
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;
|
2012-03-29 22:26:11 +00:00
|
|
|
SequencerDrawView sequencer_view3d_cb = NULL; /* NULL in background mode */
|
2010-03-08 20:08:04 +00:00
|
|
|
|
2012-08-08 11:15:32 +00:00
|
|
|
#if 0 /* unused function */
|
|
|
|
static void printf_strip(Sequence *seq)
|
2009-10-19 10:07:19 +00:00
|
|
|
{
|
2012-08-08 11:15:36 +00:00
|
|
|
fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), "
|
2012-08-08 16:46:42 +00:00
|
|
|
"(startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n",
|
2012-08-08 11:15:36 +00:00
|
|
|
seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine,
|
2012-08-08 16:46:42 +00:00
|
|
|
seq->startdisp, seq->enddisp);
|
2012-08-08 11:15:36 +00:00
|
|
|
|
|
|
|
fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0),
|
2012-08-08 16:46:42 +00:00
|
|
|
seq_tx_get_final_right(seq, 0));
|
2009-10-19 10:07:19 +00:00
|
|
|
}
|
2012-08-08 11:15:32 +00:00
|
|
|
#endif
|
2009-10-19 10:07:19 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
int BKE_sequencer_base_recursive_apply(ListBase *seqbase, int (*apply_func)(Sequence *seq, void *), void *arg)
|
2009-12-18 13:28:03 +00:00
|
|
|
{
|
|
|
|
Sequence *iseq;
|
2012-03-29 22:26:11 +00:00
|
|
|
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequencer_recursive_apply(iseq, apply_func, arg) == -1)
|
2012-03-29 22:26:11 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
int BKE_sequencer_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), void *arg)
|
2009-12-18 13:28:03 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
int ret = apply_func(seq, arg);
|
2010-07-06 16:44:05 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ret == -1)
|
2010-07-06 16:44:05 +00:00
|
|
|
return -1; /* bail out */
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ret && seq->seqbase.first)
|
2012-08-08 11:15:40 +00:00
|
|
|
ret = BKE_sequencer_base_recursive_apply(&seq->seqbase, apply_func, arg);
|
2010-07-06 16:44:05 +00:00
|
|
|
|
|
|
|
return ret;
|
2009-12-18 13:28:03 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** alloc / free functions *************************/
|
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
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:32 +00:00
|
|
|
static void seq_free_strip(Strip *strip)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
strip->us--;
|
2012-08-08 11:15:36 +00:00
|
|
|
if (strip->us > 0)
|
|
|
|
return;
|
2012-03-29 22:26:11 +00:00
|
|
|
if (strip->us < 0) {
|
2008-12-15 05:21:44 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(strip);
|
|
|
|
}
|
|
|
|
|
2012-09-06 09:23:38 +00:00
|
|
|
/* only give option to skip cache locally (static func) */
|
2014-02-03 18:55:59 +11:00
|
|
|
static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const bool do_cache)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
2012-08-08 11:15:36 +00:00
|
|
|
if (seq->strip)
|
|
|
|
seq_free_strip(seq->strip);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_sequence_free_anim(seq);
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type & SEQ_TYPE_EFFECT) {
|
2012-08-08 11:15:40 +00:00
|
|
|
struct SeqEffectHandle sh = BKE_sequence_get_effect(seq);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
sh.free(seq);
|
2009-07-08 17:41:45 +00:00
|
|
|
}
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->sound) {
|
2011-05-16 17:14:47 +00:00
|
|
|
((ID *)seq->sound)->us--;
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (seq->stereo3d_format) {
|
|
|
|
MEM_freeN(seq->stereo3d_format);
|
|
|
|
}
|
|
|
|
|
2012-12-17 08:45:44 +00:00
|
|
|
/* clipboard has no scene and will never have a sound handle or be active
|
|
|
|
* same goes to sequences copy for proxy rebuild job
|
|
|
|
*/
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scene) {
|
2009-12-17 16:28:45 +00:00
|
|
|
Editing *ed = scene->ed;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ed->act_seq == seq)
|
|
|
|
ed->act_seq = NULL;
|
2009-12-17 16:28:45 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE))
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_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
|
|
|
|
2015-04-02 21:05:12 +11:00
|
|
|
if (seq->prop) {
|
|
|
|
IDP_FreeProperty(seq->prop);
|
|
|
|
MEM_freeN(seq->prop);
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
/* free modifiers */
|
2012-08-20 10:15:32 +00:00
|
|
|
BKE_sequence_modifier_clear(seq);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2012-08-27 09:01:36 +00:00
|
|
|
/* free cached data used by this strip,
|
|
|
|
* also invalidate cache for all dependent sequences
|
2012-09-06 04:45:25 +00:00
|
|
|
*
|
|
|
|
* be _very_ careful here, invalidating cache loops over the scene sequences and
|
|
|
|
* assumes the listbase is valid for all strips, this may not be the case if lists are being freed.
|
|
|
|
* this is optional BKE_sequence_invalidate_cache
|
2012-08-27 09:01:36 +00:00
|
|
|
*/
|
2012-09-06 04:45:25 +00:00
|
|
|
if (do_cache) {
|
|
|
|
if (scene) {
|
|
|
|
BKE_sequence_invalidate_cache(scene, seq);
|
|
|
|
}
|
|
|
|
}
|
2012-08-12 18:24:01 +00:00
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
MEM_freeN(seq);
|
|
|
|
}
|
|
|
|
|
2012-09-06 09:23:38 +00:00
|
|
|
void BKE_sequence_free(Scene *scene, Sequence *seq)
|
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_free_ex(scene, seq, true);
|
2012-09-06 09:23:38 +00:00
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* Function to free imbuf and anim data on changes */
|
|
|
|
void BKE_sequence_free_anim(Sequence *seq)
|
|
|
|
{
|
|
|
|
while (seq->anims.last) {
|
|
|
|
StripAnim *sanim = seq->anims.last;
|
|
|
|
|
|
|
|
if (sanim->anim) {
|
|
|
|
IMB_free_anim(sanim->anim);
|
|
|
|
sanim->anim = NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-19 16:15:38 +02:00
|
|
|
BLI_freelinkN(&seq->anims, sanim);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2015-05-19 16:15:38 +02:00
|
|
|
BLI_listbase_clear(&seq->anims);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
2012-09-06 04:45:25 +00:00
|
|
|
/* cache must be freed before calling this function
|
|
|
|
* since it leaves the seqbase in an invalid state */
|
2012-08-08 11:15:32 +00:00
|
|
|
static void seq_free_sequence_recurse(Scene *scene, Sequence *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
|
|
|
{
|
2012-09-06 04:45:25 +00:00
|
|
|
Sequence *iseq, *iseq_next;
|
== 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
|
|
|
|
2012-09-06 04:45:25 +00:00
|
|
|
for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) {
|
|
|
|
iseq_next = iseq->next;
|
== 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_free_sequence_recurse(scene, iseq);
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_free_ex(scene, seq, 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-08 04:00:06 +00:00
|
|
|
Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc)
|
2009-01-28 22:36:34 +00:00
|
|
|
{
|
2012-05-11 10:04:55 +00:00
|
|
|
if (alloc) {
|
|
|
|
BKE_sequencer_editing_ensure(scene);
|
2009-01-28 22:36:34 +00:00
|
|
|
}
|
|
|
|
return scene->ed;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_free_clipboard(void)
|
2009-12-17 14:45:47 +00:00
|
|
|
{
|
|
|
|
Sequence *seq, *nseq;
|
|
|
|
|
2014-10-21 11:36:11 +02:00
|
|
|
BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard);
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase_clipboard.first; seq; seq = nseq) {
|
|
|
|
nseq = seq->next;
|
2014-10-21 11:36:11 +02:00
|
|
|
seq_free_sequence_recurse(NULL, seq);
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&seqbase_clipboard);
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
|
|
|
|
2013-07-24 06:51:04 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Manage pointers in the clipboard.
|
|
|
|
* note that these pointers should _never_ be access in the sequencer,
|
|
|
|
* they are only for storage while in the clipboard
|
|
|
|
* notice 'newid' is used for temp pointer storage here, validate on access.
|
|
|
|
*/
|
|
|
|
#define ID_PT (*id_pt)
|
|
|
|
static void seqclipboard_ptr_free(ID **id_pt)
|
|
|
|
{
|
|
|
|
if (ID_PT) {
|
|
|
|
BLI_assert(ID_PT->newid != NULL);
|
|
|
|
MEM_freeN(ID_PT);
|
|
|
|
ID_PT = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void seqclipboard_ptr_store(ID **id_pt)
|
|
|
|
{
|
|
|
|
if (ID_PT) {
|
|
|
|
ID *id_prev = ID_PT;
|
|
|
|
ID_PT = MEM_dupallocN(ID_PT);
|
|
|
|
ID_PT->newid = id_prev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void seqclipboard_ptr_restore(Main *bmain, ID **id_pt)
|
|
|
|
{
|
|
|
|
if (ID_PT) {
|
|
|
|
const ListBase *lb = which_libbase(bmain, GS(ID_PT->name));
|
|
|
|
void *id_restore;
|
|
|
|
|
|
|
|
BLI_assert(ID_PT->newid != NULL);
|
|
|
|
if (BLI_findindex(lb, (ID_PT)->newid) != -1) {
|
|
|
|
/* the pointer is still valid */
|
|
|
|
id_restore = (ID_PT)->newid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* the pointer of the same name still exists */
|
|
|
|
id_restore = BLI_findstring(lb, (ID_PT)->name + 2, offsetof(ID, name) + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id_restore == NULL) {
|
|
|
|
/* check for a data with the same filename */
|
|
|
|
switch (GS(ID_PT->name)) {
|
|
|
|
case ID_SO:
|
|
|
|
{
|
|
|
|
id_restore = BLI_findstring(lb, ((bSound *)ID_PT)->name, offsetof(bSound, name));
|
|
|
|
if (id_restore == NULL) {
|
2015-03-26 11:35:41 +01:00
|
|
|
id_restore = BKE_sound_new_file(bmain, ((bSound *)ID_PT)->name);
|
2013-07-24 06:51:04 +00:00
|
|
|
(ID_PT)->newid = id_restore; /* reuse next time */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ID_MC:
|
|
|
|
{
|
|
|
|
id_restore = BLI_findstring(lb, ((MovieClip *)ID_PT)->name, offsetof(MovieClip, name));
|
|
|
|
if (id_restore == NULL) {
|
|
|
|
id_restore = BKE_movieclip_file_add(bmain, ((MovieClip *)ID_PT)->name);
|
|
|
|
(ID_PT)->newid = id_restore; /* reuse next time */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ID_PT = id_restore;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef ID_PT
|
|
|
|
|
|
|
|
void BKE_sequence_clipboard_pointers_free(Sequence *seq)
|
|
|
|
{
|
|
|
|
seqclipboard_ptr_free((ID **)&seq->scene);
|
|
|
|
seqclipboard_ptr_free((ID **)&seq->scene_camera);
|
|
|
|
seqclipboard_ptr_free((ID **)&seq->clip);
|
|
|
|
seqclipboard_ptr_free((ID **)&seq->mask);
|
|
|
|
seqclipboard_ptr_free((ID **)&seq->sound);
|
|
|
|
}
|
|
|
|
void BKE_sequence_clipboard_pointers_store(Sequence *seq)
|
|
|
|
{
|
|
|
|
seqclipboard_ptr_store((ID **)&seq->scene);
|
|
|
|
seqclipboard_ptr_store((ID **)&seq->scene_camera);
|
|
|
|
seqclipboard_ptr_store((ID **)&seq->clip);
|
|
|
|
seqclipboard_ptr_store((ID **)&seq->mask);
|
|
|
|
seqclipboard_ptr_store((ID **)&seq->sound);
|
|
|
|
}
|
|
|
|
void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain)
|
|
|
|
{
|
|
|
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->scene);
|
|
|
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->scene_camera);
|
|
|
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->clip);
|
|
|
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->mask);
|
|
|
|
seqclipboard_ptr_restore(bmain, (ID **)&seq->sound);
|
|
|
|
}
|
2014-10-21 11:36:11 +02:00
|
|
|
|
|
|
|
/* recursive versions of funcions above */
|
|
|
|
void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
BKE_sequence_clipboard_pointers_free(seq);
|
|
|
|
BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
BKE_sequence_clipboard_pointers_store(seq);
|
|
|
|
BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
BKE_sequence_clipboard_pointers_restore(seq, bmain);
|
|
|
|
BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-24 06:51:04 +00:00
|
|
|
/* end clipboard pointer mess */
|
|
|
|
|
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
Editing *BKE_sequencer_editing_ensure(Scene *scene)
|
|
|
|
{
|
|
|
|
if (scene->ed == NULL) {
|
|
|
|
Editing *ed;
|
|
|
|
|
|
|
|
ed = scene->ed = MEM_callocN(sizeof(Editing), "addseq");
|
|
|
|
ed->seqbasep = &ed->seqbase;
|
|
|
|
}
|
|
|
|
|
|
|
|
return scene->ed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_editing_free(Scene *scene)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
2009-08-09 21:16:39 +00:00
|
|
|
Editing *ed = scene->ed;
|
2009-12-18 13:28:03 +00:00
|
|
|
Sequence *seq;
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ed == NULL)
|
2008-12-15 05:21:44 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-06 04:45:25 +00:00
|
|
|
/* this may not be the active scene!, could be smarter about this */
|
|
|
|
BKE_sequencer_cache_cleanup();
|
|
|
|
|
2012-04-30 16:22:40 +00:00
|
|
|
SEQ_BEGIN (ed, seq)
|
|
|
|
{
|
2012-09-06 09:23:38 +00:00
|
|
|
/* handle cache freeing above */
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_free_ex(scene, seq, false);
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
SEQ_END
|
|
|
|
|
2012-09-06 04:45:25 +00:00
|
|
|
BLI_freelistN(&ed->metastack);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
MEM_freeN(ed);
|
2012-05-11 14:27:55 +00:00
|
|
|
|
|
|
|
scene->ed = NULL;
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
/*********************** Sequencer color space functions *************************/
|
|
|
|
|
|
|
|
static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
|
|
|
|
{
|
2013-09-02 13:54:12 +00:00
|
|
|
if (ibuf->rect_float) {
|
|
|
|
IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
|
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make_float)
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
{
|
|
|
|
const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
|
|
|
|
const char *to_colorspace = scene->sequencer_colorspace_settings.name;
|
2013-09-02 13:54:12 +00:00
|
|
|
const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
|
|
|
if (!ibuf->rect_float) {
|
2013-09-02 13:54:12 +00:00
|
|
|
if (ibuf->rect) {
|
|
|
|
const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
|
|
|
|
if (make_float || !STREQ(to_colorspace, byte_colorspace)) {
|
|
|
|
/* If byte space is not in sequencer's working space, we deliver float color space,
|
|
|
|
* this is to to prevent data loss.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* when converting byte buffer to float in sequencer we need to make float
|
|
|
|
* buffer be in sequencer's working space, which is currently only doable
|
|
|
|
* from linear space.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
|
|
|
|
*/
|
|
|
|
|
|
|
|
IMB_float_from_rect(ibuf);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from_colorspace && from_colorspace[0] != '\0') {
|
|
|
|
if (ibuf->rect)
|
|
|
|
imb_freerectImBuf(ibuf);
|
|
|
|
|
2013-09-02 13:54:12 +00:00
|
|
|
if (!STREQ(float_colorspace, to_colorspace)) {
|
|
|
|
IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
|
2013-09-05 17:13:43 +00:00
|
|
|
from_colorspace, to_colorspace, true);
|
2013-11-11 12:08:31 +00:00
|
|
|
sequencer_imbuf_assign_spaces(scene, ibuf);
|
2013-09-02 13:54:12 +00:00
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
|
|
|
|
{
|
|
|
|
const char *from_colorspace = scene->sequencer_colorspace_settings.name;
|
|
|
|
const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
|
|
|
|
|
|
|
|
if (!ibuf->rect_float)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (to_colorspace && to_colorspace[0] != '\0') {
|
|
|
|
IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
|
2013-09-05 17:13:43 +00:00
|
|
|
from_colorspace, to_colorspace, true);
|
2014-01-24 14:29:50 +06:00
|
|
|
IMB_colormanagement_assign_float_colorspace(ibuf, to_colorspace);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4])
|
|
|
|
{
|
|
|
|
const char *from_colorspace = scene->sequencer_colorspace_settings.name;
|
|
|
|
const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
|
|
|
|
|
|
|
|
if (to_colorspace && to_colorspace[0] != '\0') {
|
|
|
|
IMB_colormanagement_transform_v4(pixel, from_colorspace, to_colorspace);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* if no color management enables fallback to legacy conversion */
|
|
|
|
srgb_to_linearrgb_v4(pixel, pixel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** sequencer pipeline functions *************************/
|
2010-11-21 20:00:31 +00:00
|
|
|
|
2015-01-04 22:46:54 +11:00
|
|
|
void BKE_sequencer_new_render_data(
|
|
|
|
EvaluationContext *eval_ctx,
|
|
|
|
Main *bmain, Scene *scene, int rectx, int recty,
|
|
|
|
int preview_render_size,
|
|
|
|
SeqRenderData *r_context)
|
2010-11-21 20:00:31 +00:00
|
|
|
{
|
2015-01-04 22:46:54 +11:00
|
|
|
r_context->eval_ctx = eval_ctx;
|
|
|
|
r_context->bmain = bmain;
|
|
|
|
r_context->scene = scene;
|
|
|
|
r_context->rectx = rectx;
|
|
|
|
r_context->recty = recty;
|
|
|
|
r_context->preview_render_size = preview_render_size;
|
|
|
|
r_context->motion_blur_samples = 0;
|
|
|
|
r_context->motion_blur_shutter = 0;
|
|
|
|
r_context->skip_cache = false;
|
|
|
|
r_context->is_proxy_render = false;
|
2015-04-06 10:40:12 -03:00
|
|
|
r_context->view_id = 0;
|
2010-11-21 20:00:31 +00:00
|
|
|
}
|
|
|
|
|
2011-01-02 19:00:32 +00:00
|
|
|
/* ************************* iterator ************************** */
|
2009-01-12 19:02:08 +00:00
|
|
|
/* *************** (replaces old WHILE_SEQ) ********************* */
|
2012-04-28 15:14:16 +00:00
|
|
|
/* **************** use now SEQ_BEGIN () SEQ_END ***************** */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2008-12-15 05:21:44 +00:00
|
|
|
/* sequence strip iterator:
|
2012-08-08 11:15:36 +00:00
|
|
|
* - builds a full array, recursively into meta strips
|
|
|
|
*/
|
2008-12-15 05:21:44 +00:00
|
|
|
|
|
|
|
static void seq_count(ListBase *seqbase, int *tot)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
2008-12-15 05:21:44 +00:00
|
|
|
(*tot)++;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->seqbase.first)
|
2008-12-15 05:21:44 +00:00
|
|
|
seq_count(&seq->seqbase, tot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
seq->depth = depth;
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->seqbase.first)
|
2012-03-29 22:26:11 +00:00
|
|
|
seq_build_array(&seq->seqbase, array, depth + 1);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
**array = seq;
|
2008-12-15 05:21:44 +00:00
|
|
|
(*array)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
static void seq_array(Editing *ed, Sequence ***seqarray, int *tot, bool use_pointer)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
|
|
|
Sequence **array;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
*seqarray = NULL;
|
|
|
|
*tot = 0;
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ed == NULL)
|
2008-12-15 05:21:44 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (use_pointer)
|
2009-01-12 19:02:08 +00:00
|
|
|
seq_count(ed->seqbasep, tot);
|
|
|
|
else
|
|
|
|
seq_count(&ed->seqbase, tot);
|
2008-12-15 05:21:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (*tot == 0)
|
2008-12-15 05:21:44 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
*seqarray = array = MEM_mallocN(sizeof(Sequence *) * (*tot), "SeqArray");
|
2012-03-24 06:18:31 +00:00
|
|
|
if (use_pointer)
|
2009-01-12 19:02:08 +00:00
|
|
|
seq_build_array(ed->seqbasep, &array, 0);
|
|
|
|
else
|
|
|
|
seq_build_array(&ed->seqbase, &array, 0);
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, bool 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
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (iter->tot) {
|
2012-03-29 22:26:11 +00:00
|
|
|
iter->cur = 0;
|
|
|
|
iter->seq = iter->array[iter->cur];
|
|
|
|
iter->valid = 1;
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
void BKE_sequence_iterator_next(SeqIterator *iter)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (++iter->cur < iter->tot)
|
2012-03-29 22:26:11 +00:00
|
|
|
iter->seq = iter->array[iter->cur];
|
2008-12-15 05:21:44 +00:00
|
|
|
else
|
2012-03-29 22:26:11 +00:00
|
|
|
iter->valid = 0;
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
void BKE_sequence_iterator_end(SeqIterator *iter)
|
2008-12-15 05:21:44 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (iter->array)
|
2008-12-15 05:21:44 +00:00
|
|
|
MEM_freeN(iter->array);
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
iter->valid = 0;
|
2008-12-15 05:21:44 +00:00
|
|
|
}
|
|
|
|
|
2012-04-28 13:16:29 +00:00
|
|
|
static int metaseq_start(Sequence *metaseq)
|
|
|
|
{
|
|
|
|
return metaseq->start + metaseq->startofs;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-04-28 13:16:29 +00:00
|
|
|
static int metaseq_end(Sequence *metaseq)
|
|
|
|
{
|
|
|
|
return metaseq->start + metaseq->len - metaseq->endofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metaseq, int start, int end)
|
2012-02-13 17:31:33 +00:00
|
|
|
{
|
2012-02-13 20:54:36 +00:00
|
|
|
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, */
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = metaseq->seqbase.first; seq; seq = seq->next) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2012-10-23 13:28:22 +00:00
|
|
|
seq_update_sound_bounds_recursive_rec(scene, seq, max_ii(start, metaseq_start(seq)),
|
|
|
|
min_ii(end, metaseq_end(seq)));
|
2012-02-13 20:54:36 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene_sound) {
|
2012-02-13 20:54:36 +00:00
|
|
|
int startofs = seq->startofs;
|
|
|
|
int endofs = seq->endofs;
|
2012-04-28 13:16:29 +00:00
|
|
|
if (seq->startofs + seq->start < start)
|
|
|
|
startofs = start - seq->start;
|
2012-02-13 20:54:36 +00:00
|
|
|
|
2012-04-28 13:16:29 +00:00
|
|
|
if (seq->start + seq->len - seq->endofs > end)
|
|
|
|
endofs = seq->start + seq->len - end;
|
2012-08-08 11:15:36 +00:00
|
|
|
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs,
|
2013-09-30 20:53:53 +00:00
|
|
|
seq->start + seq->len - endofs, startofs + seq->anim_startofs);
|
2012-02-13 20:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-13 17:31:33 +00:00
|
|
|
}
|
|
|
|
|
2012-04-28 13:16:29 +00:00
|
|
|
static void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
|
|
|
|
{
|
|
|
|
seq_update_sound_bounds_recursive_rec(scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq));
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_calc_disp(Scene *scene, Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-08-08 11:15:36 +00:00
|
|
|
if (seq->startofs && seq->startstill)
|
|
|
|
seq->startstill = 0;
|
|
|
|
if (seq->endofs && seq->endstill)
|
|
|
|
seq->endstill = 0;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->startdisp = seq->start + seq->startofs - seq->startstill;
|
|
|
|
seq->enddisp = seq->start + seq->len - seq->endofs + seq->endstill;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->handsize = 10.0; /* 10 frames */
|
|
|
|
if (seq->enddisp - seq->startdisp < 10) {
|
|
|
|
seq->handsize = (float)(0.5 * (seq->enddisp - seq->startdisp));
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
else if (seq->enddisp - seq->startdisp > 250) {
|
|
|
|
seq->handsize = (float)((seq->enddisp - seq->startdisp) / 25);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_update_sound_bounds(scene, seq);
|
2012-02-13 20:54:36 +00:00
|
|
|
}
|
2013-09-30 20:53:53 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_META) {
|
2012-02-13 20:54:36 +00:00
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
2013-09-30 20:53:53 +00:00
|
|
|
}
|
2010-07-13 15:19:15 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_calc(Scene *scene, Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seqm;
|
|
|
|
int min, max;
|
|
|
|
|
|
|
|
/* check all metas recursively */
|
2012-03-29 22:26:11 +00:00
|
|
|
seqm = seq->seqbase.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seqm) {
|
2012-08-08 11:15:40 +00:00
|
|
|
if (seqm->seqbase.first) BKE_sequence_calc(scene, seqm);
|
2012-03-29 22:26:11 +00:00
|
|
|
seqm = seqm->next;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* effects and meta: automatic start and end */
|
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type & SEQ_TYPE_EFFECT) {
|
2009-01-12 19:02:08 +00:00
|
|
|
/* pointers */
|
2012-08-08 11:15:36 +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 */
|
|
|
|
|
2012-05-27 19:40:36 +00:00
|
|
|
// seq->start = seq->startdisp = MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
|
|
|
|
// seq->enddisp = MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (seq->seq1) {
|
2011-11-16 20:03:54 +00:00
|
|
|
/* XXX These resets should not be necessary, but users used to be able to
|
2012-04-11 08:15:13 +00:00
|
|
|
* edit effect's length, leading to strange results. See [#29190] */
|
2011-11-16 20:03:54 +00:00
|
|
|
seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
|
2012-12-21 05:07:26 +00:00
|
|
|
seq->start = seq->startdisp = max_iii(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
|
|
|
|
seq->enddisp = min_iii(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. */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->enddisp < seq->startdisp) {
|
2011-06-04 10:39:04 +00:00
|
|
|
/* simple start/end swap */
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->start = seq->enddisp;
|
2011-06-04 10:39:04 +00:00
|
|
|
seq->enddisp = seq->startdisp;
|
2012-03-29 22:26:11 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->len = seq->enddisp - seq->startdisp;
|
2011-06-04 10:39:04 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2012-03-29 22:26:11 +00:00
|
|
|
seqm = seq->seqbase.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seqm) {
|
2012-03-29 22:26:11 +00:00
|
|
|
min = MAXFRAME * 2;
|
|
|
|
max = -MAXFRAME * 2;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seqm) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seqm->startdisp < min) min = seqm->startdisp;
|
|
|
|
if (seqm->enddisp > max) max = seqm->enddisp;
|
|
|
|
seqm = seqm->next;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->start = min + seq->anim_startofs;
|
|
|
|
seq->len = max - min;
|
2009-01-12 19:02:08 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
}
|
2010-07-13 15:19:15 +00:00
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static void seq_multiview_name(Scene *scene, const size_t view_id, const char *prefix,
|
|
|
|
const char *ext, char *r_path, size_t r_size)
|
|
|
|
{
|
|
|
|
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
|
|
|
|
BLI_snprintf(r_path, r_size, "%s%s%s", prefix, suffix, ext);
|
|
|
|
}
|
|
|
|
|
2013-01-02 16:15:45 +00:00
|
|
|
/* note: caller should run BKE_sequence_calc(scene, seq) after */
|
2014-02-03 18:55:59 +11:00
|
|
|
void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_range)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
char path[FILE_MAX];
|
2012-03-29 22:26:11 +00:00
|
|
|
int prev_startdisp = 0, prev_enddisp = 0;
|
2012-03-18 07:38:51 +00:00
|
|
|
/* note: don't rename the strip, will break animation curves */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-07-20 01:30:29 +10:00
|
|
|
if (ELEM(seq->type,
|
2012-06-07 15:49:02 +00:00
|
|
|
SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM,
|
2012-06-07 18:24:36 +00:00
|
|
|
SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0)
|
2012-06-07 15:49:02 +00:00
|
|
|
{
|
2009-01-12 19:02:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (lock_range) {
|
2012-03-18 07:38:51 +00:00
|
|
|
/* keep so we don't have to move the actual start and end points (only the data) */
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(scene, seq);
|
2012-03-29 22:26:11 +00:00
|
|
|
prev_startdisp = seq->startdisp;
|
|
|
|
prev_enddisp = seq->enddisp;
|
2010-05-08 16:36:28 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
switch (seq->type) {
|
2012-06-07 15:49:02 +00:00
|
|
|
case SEQ_TYPE_IMAGE:
|
2012-03-29 22:26:11 +00:00
|
|
|
{
|
|
|
|
/* Hack? */
|
2012-08-08 11:15:38 +00:00
|
|
|
size_t olen = MEM_allocN_len(seq->strip->stripdata) / sizeof(StripElem);
|
2012-03-29 22:26:11 +00:00
|
|
|
|
|
|
|
seq->len = olen;
|
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
case SEQ_TYPE_MOVIE:
|
2015-04-06 10:40:12 -03:00
|
|
|
{
|
|
|
|
StripAnim *sanim;
|
|
|
|
bool is_multiview_loaded = false;
|
|
|
|
const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
|
|
|
|
(scene->r.scemode & R_MULTIVIEW) != 0;
|
|
|
|
|
|
|
|
BLI_join_dirfile(path, sizeof(path), seq->strip->dir,
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->strip->stripdata->name);
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_path_abs(path, G.main->name);
|
|
|
|
|
|
|
|
BKE_sequence_free_anim(seq);
|
|
|
|
|
|
|
|
if (is_multiview && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
|
|
|
char prefix[FILE_MAX];
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *ext = NULL;
|
2015-04-06 10:40:12 -03:00
|
|
|
size_t totfiles = seq_num_files(scene, seq->views_format, true);
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
|
2012-03-21 18:02:29 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (prefix[0] != '\0') {
|
|
|
|
for (i = 0; i < totfiles; i++) {
|
|
|
|
struct anim *anim;
|
|
|
|
char str[FILE_MAX];
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX);
|
|
|
|
anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
2015-04-07 08:46:48 +10:00
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (anim) {
|
2015-04-09 17:23:51 +10:00
|
|
|
seq_anim_add_suffix(scene, anim, i);
|
2015-04-06 10:40:12 -03:00
|
|
|
sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
|
|
|
BLI_addtail(&seq->anims, sanim);
|
|
|
|
sanim->anim = anim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_multiview_loaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_multiview_loaded == false) {
|
|
|
|
struct anim *anim;
|
|
|
|
anim = openanim(path, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
if (anim) {
|
|
|
|
sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
|
|
|
BLI_addtail(&seq->anims, sanim);
|
|
|
|
sanim->anim = anim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* use the first video as reference for everything */
|
|
|
|
sanim = seq->anims.first;
|
|
|
|
|
|
|
|
if ((!sanim) || (!sanim->anim)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
|
|
|
|
|
|
|
|
seq->anim_preseek = IMB_anim_get_preseek(sanim->anim);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
break;
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
case SEQ_TYPE_MOVIECLIP:
|
2012-08-13 17:25:03 +00:00
|
|
|
if (seq->clip == NULL)
|
|
|
|
return;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->len = BKE_movieclip_get_duration(seq->clip);
|
2012-03-27 08:54:37 +00:00
|
|
|
|
2012-06-07 18:24:36 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SEQ_TYPE_MASK:
|
2012-08-13 17:25:03 +00:00
|
|
|
if (seq->mask == NULL)
|
|
|
|
return;
|
2012-06-07 18:24:36 +00:00
|
|
|
seq->len = BKE_mask_get_duration(seq->mask);
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
break;
|
2012-06-07 15:49:02 +00:00
|
|
|
case SEQ_TYPE_SOUND_RAM:
|
2011-06-23 09:27:56 +00:00
|
|
|
#ifdef WITH_AUDASPACE
|
2012-03-29 22:26:11 +00:00
|
|
|
if (!seq->sound)
|
|
|
|
return;
|
2012-11-04 07:18:29 +00:00
|
|
|
seq->len = ceil((double)AUD_getInfo(seq->sound->playback_handle).length * FPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
2011-06-23 09:27:56 +00:00
|
|
|
#else
|
2012-03-29 22:26:11 +00:00
|
|
|
return;
|
2011-06-23 09:27:56 +00:00
|
|
|
#endif
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
2012-06-07 15:49:02 +00:00
|
|
|
case SEQ_TYPE_SCENE:
|
2012-03-29 22:26:11 +00:00
|
|
|
{
|
|
|
|
seq->len = (seq->scene) ? seq->scene->r.efra - seq->scene->r.sfra + 1 : 0;
|
|
|
|
seq->len -= seq->anim_startofs;
|
|
|
|
seq->len -= seq->anim_endofs;
|
|
|
|
if (seq->len < 0) {
|
|
|
|
seq->len = 0;
|
|
|
|
}
|
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-08 20:08:19 +00:00
|
|
|
free_proxy_seq(seq);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (lock_range) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_tx_set_final_left(seq, prev_startdisp);
|
|
|
|
BKE_sequence_tx_set_final_right(seq, prev_enddisp);
|
|
|
|
BKE_sequence_single_fix(seq);
|
2010-05-08 16:36:28 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
void BKE_sequencer_sort(Scene *scene)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
/* all strips together per kind, and in order of y location ("machine") */
|
|
|
|
ListBase seqbase, effbase;
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2009-01-12 19:02:08 +00:00
|
|
|
Sequence *seq, *seqt;
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
if (ed == NULL)
|
|
|
|
return;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&seqbase);
|
|
|
|
BLI_listbase_clear(&effbase);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2013-08-26 23:37:08 +00:00
|
|
|
while ((seq = BLI_pophead(ed->seqbasep))) {
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type & SEQ_TYPE_EFFECT) {
|
2012-03-29 22:26:11 +00:00
|
|
|
seqt = effbase.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seqt) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seqt->machine >= seq->machine) {
|
2009-01-12 19:02:08 +00:00
|
|
|
BLI_insertlinkbefore(&effbase, seqt, seq);
|
|
|
|
break;
|
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
seqt = seqt->next;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-08-08 11:15:36 +00:00
|
|
|
if (seqt == NULL)
|
|
|
|
BLI_addtail(&effbase, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:26:11 +00:00
|
|
|
seqt = seqbase.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seqt) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seqt->machine >= seq->machine) {
|
2009-01-12 19:02:08 +00:00
|
|
|
BLI_insertlinkbefore(&seqbase, seqt, seq);
|
|
|
|
break;
|
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
seqt = seqt->next;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-08-08 11:15:36 +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);
|
2012-03-29 22:26:11 +00:00
|
|
|
*(ed->seqbasep) = seqbase;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seq->scene == (Scene *)arg_pt)
|
|
|
|
seq->scene = NULL;
|
2009-12-18 13:28:03 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_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 */
|
2012-03-29 22:26:11 +00:00
|
|
|
for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scene_iter != scene && scene_iter->ed) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_base_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;
|
2012-01-11 08:51:06 +00:00
|
|
|
char name_src[SEQ_NAME_MAXSTR];
|
|
|
|
char name_dest[SEQ_NAME_MAXSTR];
|
2010-02-16 17:58:50 +00:00
|
|
|
int count;
|
|
|
|
int match;
|
|
|
|
} SeqUniqueInfo;
|
|
|
|
|
|
|
|
static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui)
|
|
|
|
{
|
|
|
|
Sequence *seq;
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2013-03-10 06:18:03 +00:00
|
|
|
if ((sui->seq != seq) && STREQ(sui->name_dest, seq->name + 2)) {
|
2014-04-21 08:30:20 +02:00
|
|
|
/* SEQ_NAME_MAXSTR -4 for the number, -1 for \0, - 2 for prefix */
|
|
|
|
BLI_snprintf(sui->name_dest, sizeof(sui->name_dest), "%.*s.%03d", SEQ_NAME_MAXSTR - 4 - 1 - 2,
|
|
|
|
sui->name_src, sui->count++);
|
2012-03-29 22:26:11 +00:00
|
|
|
sui->match = 1; /* be sure to re-scan */
|
2010-02-16 17:58:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int seqbase_unique_name_recursive_cb(Sequence *seq, void *arg_pt)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->seqbase.first)
|
2010-02-16 17:58:50 +00:00
|
|
|
seqbase_unique_name(&seq->seqbase, (SeqUniqueInfo *)arg_pt);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq)
|
2010-02-16 17:58:50 +00:00
|
|
|
{
|
|
|
|
SeqUniqueInfo sui;
|
|
|
|
char *dot;
|
2012-03-29 22:26:11 +00:00
|
|
|
sui.seq = seq;
|
|
|
|
BLI_strncpy(sui.name_src, seq->name + 2, sizeof(sui.name_src));
|
|
|
|
BLI_strncpy(sui.name_dest, seq->name + 2, sizeof(sui.name_dest));
|
2010-02-16 17:58:50 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
sui.count = 1;
|
|
|
|
sui.match = 1; /* assume the worst to start the loop */
|
2010-07-14 12:16:23 +00:00
|
|
|
|
2010-02-16 17:58:50 +00:00
|
|
|
/* Strip off the suffix */
|
2012-03-29 22:26:11 +00:00
|
|
|
if ((dot = strrchr(sui.name_src, '.'))) {
|
|
|
|
*dot = '\0';
|
2010-07-14 12:16:23 +00:00
|
|
|
dot++;
|
2010-02-16 17:58:50 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (*dot)
|
2012-03-29 22:26:11 +00:00
|
|
|
sui.count = atoi(dot) + 1;
|
2010-07-14 12:16:23 +00:00
|
|
|
}
|
2010-02-16 17:58:50 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (sui.match) {
|
2012-03-29 22:26:11 +00:00
|
|
|
sui.match = 0;
|
2010-02-16 17:58:50 +00:00
|
|
|
seqbase_unique_name(seqbasep, &sui);
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_base_recursive_apply(seqbasep, seqbase_unique_name_recursive_cb, &sui);
|
2010-02-16 17:58:50 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
BLI_strncpy(seq->name + 2, sui.name_dest, sizeof(seq->name) - 2);
|
2010-02-16 17:58:50 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
switch (type) {
|
2014-07-19 22:16:10 +06:00
|
|
|
case SEQ_TYPE_META: return "Meta";
|
|
|
|
case SEQ_TYPE_IMAGE: return "Image";
|
|
|
|
case SEQ_TYPE_SCENE: return "Scene";
|
|
|
|
case SEQ_TYPE_MOVIE: return "Movie";
|
|
|
|
case SEQ_TYPE_MOVIECLIP: return "Clip";
|
|
|
|
case SEQ_TYPE_MASK: return "Mask";
|
|
|
|
case SEQ_TYPE_SOUND_RAM: return "Audio";
|
|
|
|
case SEQ_TYPE_CROSS: return "Cross";
|
|
|
|
case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
|
|
|
|
case SEQ_TYPE_ADD: return "Add";
|
|
|
|
case SEQ_TYPE_SUB: return "Sub";
|
|
|
|
case SEQ_TYPE_MUL: return "Mul";
|
|
|
|
case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
|
|
|
|
case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
|
|
|
|
case SEQ_TYPE_OVERDROP: return "Over Drop";
|
|
|
|
case SEQ_TYPE_WIPE: return "Wipe";
|
|
|
|
case SEQ_TYPE_GLOW: return "Glow";
|
|
|
|
case SEQ_TYPE_TRANSFORM: return "Transform";
|
|
|
|
case SEQ_TYPE_COLOR: return "Color";
|
|
|
|
case SEQ_TYPE_MULTICAM: return "Multicam";
|
|
|
|
case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
|
|
|
|
case SEQ_TYPE_SPEED: return "Speed";
|
|
|
|
case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
|
2012-03-29 22:26:11 +00:00
|
|
|
default:
|
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
const char *BKE_sequence_give_name(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) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type < SEQ_TYPE_EFFECT) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return seq->strip->dir;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-12 19:02:08 +00:00
|
|
|
return "Effect";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** DO THE SEQUENCE *************************/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
static void make_black_ibuf(ImBuf *ibuf)
|
|
|
|
{
|
|
|
|
unsigned int *rect;
|
|
|
|
float *rect_float;
|
|
|
|
int tot;
|
|
|
|
|
2012-03-29 22:35:12 +00:00
|
|
|
if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
|
|
|
|
return;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
tot = ibuf->x * ibuf->y;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
rect = ibuf->rect;
|
2009-01-12 19:02:08 +00:00
|
|
|
rect_float = ibuf->rect_float;
|
|
|
|
|
|
|
|
if (rect) {
|
2012-08-08 11:15:36 +00:00
|
|
|
memset(rect, 0, tot * sizeof(char) * 4);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rect_float) {
|
|
|
|
memset(rect_float, 0, tot * sizeof(float) * 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 12:23:38 +10:00
|
|
|
static void multibuf(ImBuf *ibuf, const float fmul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
char *rt;
|
|
|
|
float *rt_float;
|
|
|
|
|
2015-04-08 12:23:38 +10:00
|
|
|
int a;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
rt = (char *)ibuf->rect;
|
2009-01-12 19:02:08 +00:00
|
|
|
rt_float = ibuf->rect_float;
|
|
|
|
|
|
|
|
if (rt) {
|
2015-04-08 12:23:38 +10:00
|
|
|
const int imul = (int)(256.0f * fmul);
|
2012-03-29 22:26:11 +00:00
|
|
|
a = ibuf->x * ibuf->y;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (a--) {
|
2015-04-08 12:23:38 +10:00
|
|
|
rt[0] = min_ii((imul * rt[0]) >> 8, 255);
|
|
|
|
rt[1] = min_ii((imul * rt[1]) >> 8, 255);
|
|
|
|
rt[2] = min_ii((imul * rt[2]) >> 8, 255);
|
|
|
|
rt[3] = min_ii((imul * rt[3]) >> 8, 255);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
rt += 4;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rt_float) {
|
2012-03-29 22:26:11 +00:00
|
|
|
a = ibuf->x * ibuf->y;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (a--) {
|
2009-01-12 19:02:08 +00:00
|
|
|
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;
|
2012-03-29 22:26:11 +00:00
|
|
|
int end = seq->start + seq->len - 1;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type & SEQ_TYPE_EFFECT) {
|
2011-05-17 18:37:44 +00:00
|
|
|
end = seq->enddisp;
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2011-05-17 18:37:44 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (end < sta) {
|
2011-05-17 18:37:44 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seq->flag & SEQ_REVERSE_FRAMES) {
|
2009-01-12 19:02:08 +00:00
|
|
|
/*reverse frame in this sequence */
|
2012-03-29 22:26:11 +00:00
|
|
|
if (cfra <= sta) nr = end - sta;
|
|
|
|
else if (cfra >= end) nr = 0;
|
|
|
|
else nr = end - cfra;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (cfra <= sta) nr = 0;
|
|
|
|
else if (cfra >= end) nr = end - sta;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
StripElem *se = seq->strip->stripdata;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
if (seq->type == SEQ_TYPE_IMAGE) {
|
|
|
|
/* only IMAGE strips use the whole array, MOVIE strips use only the first element,
|
|
|
|
* all other strips don't use this...
|
|
|
|
*/
|
|
|
|
|
|
|
|
int nr = (int) give_stripelem_index(seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:36 +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;
|
|
|
|
}
|
|
|
|
|
2014-04-14 17:50:47 +06:00
|
|
|
static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
2014-02-21 14:01:12 +06:00
|
|
|
Sequence *effect_inputs[MAXSEQ + 1];
|
|
|
|
int i, totseq = 0, num_effect_inputs = 0;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
memset(seq_arr, 0, sizeof(Sequence *) * (MAXSEQ + 1));
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq = seqbase->first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seq) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seq->startdisp <= cfra && seq->enddisp > cfra) {
|
2015-06-25 18:21:58 +02:00
|
|
|
if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) {
|
2014-02-21 14:01:12 +06:00
|
|
|
if (seq->seq1) {
|
|
|
|
effect_inputs[num_effect_inputs++] = seq->seq1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->seq2) {
|
|
|
|
effect_inputs[num_effect_inputs++] = seq->seq2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->seq3) {
|
|
|
|
effect_inputs[num_effect_inputs++] = seq->seq3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq_arr[seq->machine] = seq;
|
2009-01-12 19:02:08 +00:00
|
|
|
totseq++;
|
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
seq = seq->next;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-02-21 14:01:12 +06:00
|
|
|
/* Drop strips which are used for effect inputs, we don't want
|
2014-04-11 16:26:57 +06:00
|
|
|
* them to blend into render stack in any other way than effect
|
2014-02-21 14:01:12 +06:00
|
|
|
* string rendering.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < num_effect_inputs; i++) {
|
|
|
|
seq = effect_inputs[i];
|
2014-04-11 16:26:57 +06:00
|
|
|
/* It's possible that effetc strip would be placed to the same
|
|
|
|
* 'machine' as it's inputs. We don't want to clear such strips
|
|
|
|
* from the stack.
|
|
|
|
*/
|
|
|
|
if (seq_arr[seq->machine] && seq_arr[seq->machine]->type & SEQ_TYPE_EFFECT) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-04-14 17:50:47 +06:00
|
|
|
/* If we're shown a specified channel, then we want to see the stirps
|
|
|
|
* which belongs to this machine.
|
|
|
|
*/
|
|
|
|
if (chanshown != 0 && chanshown <= seq->machine) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-02-21 14:01:12 +06:00
|
|
|
seq_arr[seq->machine] = NULL;
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
return totseq;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
int BKE_sequencer_evaluate_frame(Scene *scene, int cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq_arr[MAXSEQ + 1];
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
if (ed == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2014-04-14 17:50:47 +06:00
|
|
|
return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra, 0);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-02-05 22:36:15 +11:00
|
|
|
static bool video_seq_is_rendered(Sequence *seq)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-06-07 15:49:02 +00:00
|
|
|
return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_TYPE_SOUND_RAM);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
static int get_shown_sequences(ListBase *seqbasep, int cfra, int chanshown, Sequence **seq_arr_out)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq_arr[MAXSEQ + 1];
|
2009-01-12 19:02:08 +00:00
|
|
|
int b = chanshown;
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
if (b > MAXSEQ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-04-14 17:50:47 +06:00
|
|
|
if (evaluate_seq_frame_gen(seq_arr, seqbasep, cfra, chanshown)) {
|
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;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (; b > 0; b--) {
|
2009-01-12 19:02:08 +00:00
|
|
|
if (video_seq_is_rendered(seq_arr[b])) {
|
|
|
|
if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +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
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** proxy management *************************/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-02-29 12:08:26 +00:00
|
|
|
typedef struct SeqIndexBuildContext {
|
|
|
|
struct IndexBuildContext *index_context;
|
|
|
|
|
|
|
|
int tc_flags;
|
|
|
|
int size_flags;
|
|
|
|
int quality;
|
2015-01-28 17:30:15 +05:00
|
|
|
bool overwrite;
|
2015-04-06 10:40:12 -03:00
|
|
|
size_t view_id;
|
2012-02-29 12:08:26 +00:00
|
|
|
|
|
|
|
Main *bmain;
|
|
|
|
Scene *scene;
|
|
|
|
Sequence *seq, *orig_seq;
|
|
|
|
} SeqIndexBuildContext;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
#define PROXY_MAXFILE (2 * FILE_MAXDIR + FILE_MAXFILE)
|
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 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;
|
|
|
|
}
|
|
|
|
|
2012-03-17 19:31:28 +00:00
|
|
|
static double seq_rendersize_to_scale_factor(int size)
|
|
|
|
{
|
|
|
|
if (size >= 99) {
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
if (size >= 75) {
|
|
|
|
return 0.75;
|
|
|
|
}
|
|
|
|
if (size >= 50) {
|
|
|
|
return 0.50;
|
|
|
|
}
|
|
|
|
return 0.25;
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* the number of files will vary according to the stereo format */
|
|
|
|
static size_t seq_num_files(Scene *scene, char views_format, const bool is_multiview)
|
== 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
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
if (!is_multiview) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if (views_format == R_IMF_VIEWS_STEREO_3D) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* R_IMF_VIEWS_INDIVIDUAL */
|
|
|
|
else {
|
|
|
|
return BKE_scene_multiview_num_views_get(&scene->r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir)
|
|
|
|
{
|
|
|
|
char dir[FILE_MAX];
|
|
|
|
char fname[FILE_MAXFILE];
|
|
|
|
|
|
|
|
IMB_anim_get_fname(anim, fname, FILE_MAXFILE);
|
|
|
|
BLI_strncpy(dir, base_dir, sizeof(dir));
|
|
|
|
BLI_path_append(dir, sizeof(dir), fname);
|
|
|
|
IMB_anim_set_index_dir(anim, dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile)
|
|
|
|
{
|
|
|
|
char dir[FILE_MAX];
|
2011-11-26 04:07:38 +00:00
|
|
|
char name[FILE_MAX];
|
2012-03-29 22:26:11 +00:00
|
|
|
StripProxy *proxy;
|
2015-04-06 10:40:12 -03:00
|
|
|
bool use_proxy;
|
|
|
|
bool is_multiview_loaded = false;
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
const bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 && (scene->r.scemode & R_MULTIVIEW) != 0;
|
== 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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if ((seq->anims.first != NULL) && (((StripAnim *)seq->anims.first)->anim != NULL)) {
|
== 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;
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* reset all the previously created anims */
|
|
|
|
BKE_sequence_free_anim(seq);
|
|
|
|
|
2011-11-11 13:09:14 +00:00
|
|
|
BLI_join_dirfile(name, sizeof(name),
|
|
|
|
seq->strip->dir, seq->strip->stripdata->name);
|
== 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_path_abs(name, G.main->name);
|
|
|
|
|
|
|
|
proxy = seq->strip->proxy;
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
use_proxy = proxy && ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) != 0 ||
|
|
|
|
(ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE));
|
2015-03-26 17:54:16 +01:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (use_proxy) {
|
2015-03-26 17:54:16 +01:00
|
|
|
if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) {
|
|
|
|
if (ed->proxy_dir[0] == 0)
|
2015-03-26 18:25:06 +01:00
|
|
|
BLI_strncpy(dir, "//BL_proxy", sizeof(dir));
|
2015-03-26 17:54:16 +01:00
|
|
|
else
|
|
|
|
BLI_strncpy(dir, ed->proxy_dir, sizeof(dir));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_path_abs(dir, G.main->name);
|
|
|
|
}
|
2015-03-26 17:54:16 +01:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (is_multiview && seq->views_format == R_IMF_VIEWS_INDIVIDUAL) {
|
|
|
|
size_t totfiles = seq_num_files(scene, seq->views_format, true);
|
|
|
|
char prefix[FILE_MAX];
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *ext = NULL;
|
2015-04-06 10:40:12 -03:00
|
|
|
int i;
|
2015-03-25 12:05:34 +01:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
|
|
|
|
|
|
|
|
if (prefix[0] != '\0') {
|
|
|
|
for (i = 0; i < totfiles; i++) {
|
|
|
|
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
|
|
|
|
char str[FILE_MAX];
|
|
|
|
StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
|
|
|
|
|
|
|
BLI_addtail(&seq->anims, sanim);
|
2012-06-28 07:58:34 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_snprintf(str, sizeof(str), "%s%s%s", prefix, suffix, ext);
|
|
|
|
|
|
|
|
if (openfile) {
|
|
|
|
sanim->anim = openanim(
|
|
|
|
str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sanim->anim = openanim_noload(
|
|
|
|
str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
|
2015-04-09 17:09:10 +10:00
|
|
|
if (sanim->anim) {
|
|
|
|
#if 0
|
|
|
|
seq_anim_add_suffix(scene, sanim->anim, i);
|
|
|
|
#else
|
|
|
|
/* we already have the suffix */
|
|
|
|
IMB_suffix_anim(sanim->anim, suffix);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else {
|
2015-04-06 10:40:12 -03:00
|
|
|
if (openfile) {
|
|
|
|
sanim->anim = openanim(
|
|
|
|
name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sanim->anim = openanim_noload(
|
|
|
|
name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no individual view files - monoscopic, stereo 3d or exr multiview */
|
|
|
|
totfiles = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sanim->anim && use_proxy) {
|
|
|
|
seq_proxy_index_dir_set(sanim->anim, dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is_multiview_loaded = 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
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (is_multiview_loaded == false) {
|
|
|
|
StripAnim *sanim;
|
|
|
|
|
|
|
|
sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
|
|
|
BLI_addtail(&seq->anims, sanim);
|
== 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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (openfile) {
|
|
|
|
sanim->anim = openanim(
|
|
|
|
name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sanim->anim = openanim_noload(
|
|
|
|
name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0),
|
|
|
|
seq->streamindex, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sanim->anim && use_proxy) {
|
|
|
|
seq_proxy_index_dir_set(sanim->anim, dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render_size, char *name, const size_t view_id)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
int frameno;
|
2011-08-30 10:07:50 +00:00
|
|
|
char dir[PROXY_MAXFILE];
|
2015-04-06 10:40:12 -03:00
|
|
|
StripAnim *sanim;
|
|
|
|
char suffix[24] = {'\0'};
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-03-24 12:24:30 +01:00
|
|
|
StripProxy *proxy = seq->strip->proxy;
|
|
|
|
if (!proxy) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return false;
|
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
|
|
|
/* MOVIE tracks (only exception: custom files) are now handled
|
2012-03-09 18:28:30 +00:00
|
|
|
* 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... */
|
== 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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
sanim = BLI_findlink(&seq->anims, view_id);
|
|
|
|
|
2015-04-07 12:15:02 +02:00
|
|
|
if (ed->proxy_storage == SEQ_EDIT_PROXY_DIR_STORAGE) {
|
2015-03-26 17:54:16 +01:00
|
|
|
char fname[FILE_MAXFILE];
|
|
|
|
if (ed->proxy_dir[0] == 0)
|
2015-03-26 18:25:06 +01:00
|
|
|
BLI_strncpy(dir, "//BL_proxy", sizeof(dir));
|
2015-03-26 17:54:16 +01:00
|
|
|
else
|
|
|
|
BLI_strncpy(dir, ed->proxy_dir, sizeof(dir));
|
2015-04-07 12:15:02 +02:00
|
|
|
|
|
|
|
if (sanim && sanim->anim) {
|
|
|
|
IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE);
|
|
|
|
}
|
|
|
|
else if (seq->type == SEQ_TYPE_IMAGE) {
|
|
|
|
fname[0] = 0;
|
|
|
|
}
|
2015-03-26 17:54:16 +01:00
|
|
|
BLI_path_append(dir, sizeof(dir), fname);
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
}
|
|
|
|
else if ((proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR) && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE)) {
|
2015-03-25 12:05:34 +01:00
|
|
|
BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
else if (sanim && sanim->anim && (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_DIR)) {
|
2015-03-25 12:05:34 +01:00
|
|
|
char fname[FILE_MAXFILE];
|
2011-10-19 23:10:54 +00:00
|
|
|
BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
|
2015-04-06 10:40:12 -03:00
|
|
|
IMB_anim_get_fname(sanim->anim, fname, FILE_MAXFILE);
|
2015-03-25 12:05:34 +01:00
|
|
|
BLI_path_append(dir, sizeof(dir), fname);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_IMAGE) {
|
2011-08-30 10:07:50 +00:00
|
|
|
BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-03-20 15:45:20 +06:00
|
|
|
return false;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (view_id > 0)
|
|
|
|
BLI_snprintf(suffix, sizeof(suffix), "_%zu", view_id);
|
|
|
|
|
|
|
|
if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE && sanim && sanim->anim &&
|
2015-03-26 17:54:16 +01:00
|
|
|
ed->proxy_storage != SEQ_EDIT_PROXY_DIR_STORAGE)
|
|
|
|
{
|
2011-11-11 13:09:14 +00:00
|
|
|
BLI_join_dirfile(name, PROXY_MAXFILE,
|
2015-03-25 12:05:34 +01:00
|
|
|
dir, proxy->file);
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_abs(name, G.main->name);
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_snprintf(name, PROXY_MAXFILE, "%s_%s", name, suffix);
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_IMAGE) {
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy%s", dir, render_size,
|
|
|
|
BKE_sequencer_give_stripelem(seq, cfra)->name, suffix);
|
2009-01-12 19:02:08 +00:00
|
|
|
frameno = 1;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:35:12 +00:00
|
|
|
frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, render_size, suffix);
|
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");
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
char name[PROXY_MAXFILE];
|
2014-01-19 00:16:19 +06:00
|
|
|
IMB_Proxy_Size psize = seq_rendersize_to_proxysize(context->preview_render_size);
|
== 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 size_flags;
|
2014-01-19 00:16:19 +06:00
|
|
|
int render_size = context->preview_render_size;
|
2015-03-24 12:24:30 +01:00
|
|
|
StripProxy *proxy = seq->strip->proxy;
|
2015-03-26 17:54:16 +01:00
|
|
|
Editing *ed = context->scene->ed;
|
2015-04-06 10:40:12 -03:00
|
|
|
StripAnim *sanim;
|
2012-02-17 07:32:18 +00:00
|
|
|
|
2015-03-25 12:05:34 +01:00
|
|
|
if (!(seq->flag & SEQ_USE_PROXY)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-17 07:32:18 +00:00
|
|
|
/* dirty hack to distinguish 100% render size from PROXY_100 */
|
|
|
|
if (render_size == 99) {
|
|
|
|
render_size = 100;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-03-24 12:24:30 +01:00
|
|
|
size_flags = proxy->build_size_flags;
|
== 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
|
|
|
|
|
|
|
/* 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
|
|
|
}
|
|
|
|
|
2015-03-24 12:24:30 +01:00
|
|
|
if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) {
|
2012-03-29 22:35:12 +00:00
|
|
|
int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
|
2015-03-24 12:24:30 +01:00
|
|
|
if (proxy->anim == NULL) {
|
2015-04-06 10:40:12 -03:00
|
|
|
if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2015-03-24 12:24:30 +01:00
|
|
|
proxy->anim = openanim(name, IB_rect, 0, seq->strip->colorspace_settings.name);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2015-03-24 12:24:30 +01:00
|
|
|
if (proxy->anim == NULL) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
seq_open_anim_file(context->scene, seq, true);
|
|
|
|
sanim = seq->anims.first;
|
== 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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
frameno = IMB_anim_index_get_frame_index(sanim ? sanim->anim : NULL, seq->strip->proxy->tc, frameno);
|
== 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
|
|
|
|
2015-03-24 12:24:30 +01:00
|
|
|
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (BLI_exists(name)) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL);
|
|
|
|
|
|
|
|
if (ibuf)
|
2014-01-19 00:16:19 +06:00
|
|
|
sequencer_imbuf_assign_spaces(context->scene, ibuf);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
|
|
|
return ibuf;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-02-13 10:52:18 +00:00
|
|
|
return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 17:30:15 +05:00
|
|
|
static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, int cfra,
|
|
|
|
int proxy_render_size, const bool overwrite)
|
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;
|
2014-12-04 16:37:09 +01:00
|
|
|
ImBuf *ibuf_tmp, *ibuf;
|
2015-03-26 17:54:16 +01:00
|
|
|
Editing *ed = context->scene->ed;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (!seq_proxy_get_fname(ed, seq, cfra, proxy_render_size, name, context->view_id)) {
|
2009-01-12 19:02:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-28 17:30:15 +05:00
|
|
|
if (!overwrite && BLI_exists(name)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-04 16:37:09 +01:00
|
|
|
ibuf_tmp = seq_render_strip(context, seq, cfra);
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2014-12-04 16:37:09 +01:00
|
|
|
rectx = (proxy_render_size * ibuf_tmp->x) / 100;
|
|
|
|
recty = (proxy_render_size * ibuf_tmp->y) / 100;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-12-04 16:37:09 +01:00
|
|
|
if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) {
|
|
|
|
ibuf = IMB_dupImBuf(ibuf_tmp);
|
2015-05-06 13:05:59 +02:00
|
|
|
IMB_metadata_copy(ibuf, ibuf_tmp);
|
2014-12-04 16:37:09 +01:00
|
|
|
IMB_freeImBuf(ibuf_tmp);
|
2009-01-12 19:02:08 +00:00
|
|
|
IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
|
|
|
|
}
|
2014-12-04 16:37:09 +01:00
|
|
|
else {
|
|
|
|
ibuf = ibuf_tmp;
|
|
|
|
}
|
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
|
|
|
/* depth = 32 is intentionally left in, otherwise ALPHA channels
|
2012-03-09 18:28:30 +00:00
|
|
|
* won't work... */
|
2009-06-14 18:54:35 +00:00
|
|
|
quality = seq->strip->proxy->quality;
|
2012-03-29 22:26:11 +00:00
|
|
|
ibuf->ftype = JPG | quality;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2011-10-23 17:52:20 +00:00
|
|
|
/* unsupported feature only confuses other s/w */
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ibuf->planes == 32)
|
|
|
|
ibuf->planes = 24;
|
2011-10-23 17:52:20 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
BLI_make_existing_file(name);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
|
|
|
|
if (ok == 0) {
|
|
|
|
perror(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* returns whether the file this context would read from even exist, if not, don't create the context
|
|
|
|
*/
|
|
|
|
static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const size_t view_id)
|
|
|
|
{
|
|
|
|
if ((scene->r.scemode & R_MULTIVIEW) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((seq->type == SEQ_TYPE_IMAGE) && (seq->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
|
|
|
static char prefix[FILE_MAX];
|
2015-06-27 11:00:47 +02:00
|
|
|
static const char *ext = NULL;
|
2015-04-06 10:40:12 -03:00
|
|
|
char str[FILE_MAX];
|
|
|
|
|
|
|
|
if (view_id == 0) {
|
|
|
|
char path[FILE_MAX];
|
|
|
|
BLI_join_dirfile(path, sizeof(path), seq->strip->dir,
|
|
|
|
seq->strip->stripdata->name);
|
|
|
|
BLI_path_abs(path, G.main->name);
|
|
|
|
BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
|
|
|
|
}
|
2015-04-09 17:30:26 +10:00
|
|
|
else {
|
|
|
|
prefix[0] = '\0';
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
if (prefix[0] == '\0')
|
|
|
|
return view_id != 0;
|
|
|
|
|
|
|
|
seq_multiview_name(scene, view_id, prefix, ext, str, FILE_MAX);
|
|
|
|
|
|
|
|
if (BLI_access(str, R_OK) == 0)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return view_id != 0;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** This returns the maximum possible number of required contexts
|
|
|
|
*/
|
|
|
|
static size_t seq_proxy_context_count(Sequence *seq, Scene *scene)
|
|
|
|
{
|
|
|
|
size_t num_views = 1;
|
|
|
|
|
|
|
|
if ((scene->r.scemode & R_MULTIVIEW) == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
switch (seq->type) {
|
|
|
|
case SEQ_TYPE_MOVIE:
|
|
|
|
{
|
|
|
|
num_views = BLI_listbase_count(&seq->anims);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SEQ_TYPE_IMAGE:
|
|
|
|
{
|
|
|
|
switch (seq->views_format) {
|
|
|
|
case R_IMF_VIEWS_INDIVIDUAL:
|
|
|
|
num_views = BKE_scene_multiview_num_views_get(&scene->r);
|
|
|
|
break;
|
|
|
|
case R_IMF_VIEWS_STEREO_3D:
|
|
|
|
num_views = 2;
|
|
|
|
break;
|
|
|
|
case R_IMF_VIEWS_MULTIVIEW:
|
|
|
|
/* not supported at the moment */
|
|
|
|
/* pass through */
|
|
|
|
default:
|
|
|
|
num_views = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return num_views;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequencer_proxy_rebuild_context(Main *bmain, Scene *scene, Sequence *seq, struct GSet *file_list, ListBase *queue)
|
2012-04-21 12:51:47 +00:00
|
|
|
{
|
2012-02-29 12:08:26 +00:00
|
|
|
SeqIndexBuildContext *context;
|
|
|
|
Sequence *nseq;
|
2015-04-06 10:40:12 -03:00
|
|
|
LinkData *link;
|
|
|
|
size_t i;
|
|
|
|
size_t num_files;
|
== 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->strip || !seq->strip->proxy) {
|
2015-04-06 10:40:12 -03: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
|
|
|
}
|
|
|
|
|
|
|
|
if (!(seq->flag & SEQ_USE_PROXY)) {
|
2015-04-06 10:40:12 -03: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
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
num_files = seq_proxy_context_count(seq, scene);
|
|
|
|
|
|
|
|
for (i = 0; i < num_files; i++) {
|
|
|
|
if (seq_proxy_multiview_context_invalid(seq, scene, i))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
context = MEM_callocN(sizeof(SeqIndexBuildContext), "seq proxy rebuild context");
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
nseq = BKE_sequence_dupli_recursive(scene, scene, seq, 0);
|
2012-02-29 12:08:26 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
context->tc_flags = nseq->strip->proxy->build_tc_flags;
|
|
|
|
context->size_flags = nseq->strip->proxy->build_size_flags;
|
|
|
|
context->quality = nseq->strip->proxy->quality;
|
|
|
|
context->overwrite = (nseq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) == 0;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
context->bmain = bmain;
|
|
|
|
context->scene = scene;
|
|
|
|
context->orig_seq = seq;
|
|
|
|
context->seq = nseq;
|
2012-02-29 12:08:26 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
context->view_id = i; /* only for images */
|
2012-02-29 12:08:26 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
link = BLI_genericNodeN(context);
|
|
|
|
BLI_addtail(queue, link);
|
|
|
|
|
|
|
|
if (nseq->type == SEQ_TYPE_MOVIE) {
|
|
|
|
StripAnim *sanim;
|
|
|
|
|
|
|
|
seq_open_anim_file(scene, nseq, true);
|
|
|
|
sanim = BLI_findlink(&nseq->anims, i);
|
|
|
|
|
|
|
|
if (sanim->anim) {
|
|
|
|
context->index_context = IMB_anim_index_rebuild_context(sanim->anim,
|
|
|
|
context->tc_flags, context->size_flags, context->quality,
|
|
|
|
context->overwrite, file_list);
|
|
|
|
}
|
== 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
|
|
|
}
|
2012-02-29 12:08:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, short *do_update, float *progress)
|
2012-02-29 12:08:26 +00:00
|
|
|
{
|
2015-01-28 17:30:15 +05:00
|
|
|
const bool overwrite = context->overwrite;
|
2012-02-29 12:08:26 +00:00
|
|
|
SeqRenderData render_context;
|
|
|
|
Sequence *seq = context->seq;
|
|
|
|
Scene *scene = context->scene;
|
2013-12-26 17:24:42 +06:00
|
|
|
Main *bmain = context->bmain;
|
2012-02-29 12:08:26 +00:00
|
|
|
int cfra;
|
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_MOVIE) {
|
2012-02-29 12:08:26 +00:00
|
|
|
if (context->index_context) {
|
|
|
|
IMB_anim_index_rebuild(context->index_context, stop, do_update, progress);
|
|
|
|
}
|
|
|
|
|
== 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;
|
|
|
|
}
|
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... */
|
2015-03-24 12:24:30 +01:00
|
|
|
if (seq->strip->proxy && seq->strip->proxy->storage & SEQ_STORAGE_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
|
|
|
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
|
|
|
|
2015-01-04 22:46:54 +11:00
|
|
|
BKE_sequencer_new_render_data(
|
|
|
|
bmain->eval_ctx, bmain, context->scene,
|
|
|
|
(scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
|
|
|
|
(scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100,
|
|
|
|
&render_context);
|
|
|
|
|
2014-01-17 20:03:48 +06:00
|
|
|
render_context.skip_cache = true;
|
2014-03-20 15:08:23 +06:00
|
|
|
render_context.is_proxy_render = true;
|
2015-04-06 10:40:12 -03:00
|
|
|
render_context.view_id = context->view_id;
|
== 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
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
for (cfra = seq->startdisp + seq->startstill; cfra < seq->enddisp - seq->endstill; cfra++) {
|
2012-02-29 12:08:26 +00:00
|
|
|
if (context->size_flags & IMB_PROXY_25) {
|
2015-01-28 17:30:15 +05:00
|
|
|
seq_proxy_build_frame(&render_context, seq, cfra, 25, overwrite);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-02-29 12:08:26 +00:00
|
|
|
if (context->size_flags & IMB_PROXY_50) {
|
2015-01-28 17:30:15 +05:00
|
|
|
seq_proxy_build_frame(&render_context, seq, cfra, 50, overwrite);
|
== 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
|
|
|
}
|
2012-02-29 12:08:26 +00:00
|
|
|
if (context->size_flags & IMB_PROXY_75) {
|
2015-01-28 17:30:15 +05:00
|
|
|
seq_proxy_build_frame(&render_context, seq, cfra, 75, overwrite);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-02-29 12:08:26 +00:00
|
|
|
if (context->size_flags & IMB_PROXY_100) {
|
2015-01-28 17:30:15 +05:00
|
|
|
seq_proxy_build_frame(&render_context, seq, cfra, 100, overwrite);
|
== 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
|
|
|
}
|
|
|
|
|
2013-02-07 14:15:30 +00:00
|
|
|
*progress = (float) (cfra - seq->startdisp - seq->startstill) / (seq->enddisp - seq->endstill - seq->startdisp - seq->startstill);
|
2014-04-01 11:34:00 +11:00
|
|
|
*do_update = 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
|
|
|
|
2012-08-08 18:37:06 +00:00
|
|
|
if (*stop || G.is_break)
|
== 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
|
|
|
break;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
|
2012-02-29 12:08:26 +00:00
|
|
|
{
|
|
|
|
if (context->index_context) {
|
2015-04-06 10:40:12 -03:00
|
|
|
StripAnim *sanim;
|
|
|
|
|
|
|
|
for (sanim = context->seq->anims.first; sanim; sanim = sanim->next)
|
|
|
|
IMB_close_anim_proxies(sanim->anim);
|
|
|
|
|
|
|
|
for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next)
|
|
|
|
IMB_close_anim_proxies(sanim->anim);
|
|
|
|
|
2012-02-29 12:08:26 +00:00
|
|
|
IMB_anim_index_rebuild_finish(context->index_context, stop);
|
|
|
|
}
|
|
|
|
|
2012-12-17 08:45:44 +00:00
|
|
|
seq_free_sequence_recurse(NULL, context->seq);
|
2012-02-29 12:08:26 +00:00
|
|
|
|
|
|
|
MEM_freeN(context);
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2015-01-29 12:36:23 +01:00
|
|
|
void BKE_sequencer_proxy_set(struct Sequence *seq, bool value)
|
|
|
|
{
|
|
|
|
if (value) {
|
|
|
|
seq->flag |= SEQ_USE_PROXY;
|
|
|
|
if (seq->strip->proxy == NULL) {
|
|
|
|
seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy");
|
|
|
|
seq->strip->proxy->quality = 90;
|
|
|
|
seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL;
|
|
|
|
seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
seq->flag ^= SEQ_USE_PROXY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** color balance *************************/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
static StripColorBalance calc_cb(StripColorBalance *cb_)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +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 */
|
2012-03-24 06:18:31 +00:00
|
|
|
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];
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-12 19:02:08 +00:00
|
|
|
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) {
|
2012-03-29 22:26:11 +00:00
|
|
|
cb.gamma[c] = 1.0f / cb.gamma[c];
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-12 19:02:08 +00:00
|
|
|
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
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
float x = (((in - 1.0f) * lift) + 1.0f) * gain;
|
2010-07-07 15:06:57 +00:00
|
|
|
|
|
|
|
/* prevent NaN */
|
2012-08-08 11:15:36 +00:00
|
|
|
if (x < 0.f)
|
|
|
|
x = 0.f;
|
2010-07-07 15:06:57 +00:00
|
|
|
|
|
|
|
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_float(float lift, float gain, float gamma,
|
2012-03-29 22:26:11 +00:00
|
|
|
float *table, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
int y;
|
|
|
|
|
|
|
|
for (y = 0; y < 256; y++) {
|
2012-03-29 22:26:11 +00:00
|
|
|
float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
|
2012-08-08 11:15:36 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
table[y] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-12-31 13:52:13 +00:00
|
|
|
//unsigned char cb_tab[3][256];
|
|
|
|
unsigned char *cp = rect;
|
|
|
|
unsigned char *e = cp + width * 4 * height;
|
2012-08-11 14:37:58 +00:00
|
|
|
unsigned char *m = mask_rect;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
StripColorBalance cb = calc_cb(cb_);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
while (cp < e) {
|
|
|
|
float p[4];
|
|
|
|
int c;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
straight_uchar_to_premul_float(p, cp);
|
2012-08-11 14:37:58 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
for (c = 0; c < 3; c++) {
|
|
|
|
float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
|
2012-08-11 14:37:58 +00:00
|
|
|
|
2013-02-27 09:58:40 +00:00
|
|
|
if (m) {
|
|
|
|
float m_normal = (float) m[c] / 255.0f;
|
|
|
|
|
|
|
|
p[c] = p[c] * (1.0f - m_normal) + t * m_normal;
|
|
|
|
}
|
2012-12-31 13:52:13 +00:00
|
|
|
else
|
|
|
|
p[c] = t;
|
2012-08-11 14:37:58 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
premul_float_to_straight_uchar(cp, p);
|
|
|
|
|
|
|
|
cp += 4;
|
|
|
|
if (m)
|
|
|
|
m += 4;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
static void color_balance_byte_float(StripColorBalance *cb_, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
float cb_tab[4][256];
|
2012-03-29 22:26:11 +00:00
|
|
|
int c, i;
|
2012-08-07 16:09:42 +00:00
|
|
|
unsigned char *p = rect;
|
|
|
|
unsigned char *e = p + width * 4 * height;
|
2012-08-11 14:37:58 +00:00
|
|
|
unsigned char *m = mask_rect;
|
2012-03-29 22:26:11 +00:00
|
|
|
float *o;
|
2009-01-12 19:02:08 +00:00
|
|
|
StripColorBalance cb;
|
|
|
|
|
2012-08-07 16:09:42 +00:00
|
|
|
o = rect_float;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
cb = calc_cb(cb_);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
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++) {
|
2012-03-29 22:26:11 +00:00
|
|
|
cb_tab[3][i] = ((float)i) * (1.0f / 255.0f);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (p < e) {
|
2012-08-11 14:37:58 +00:00
|
|
|
if (m) {
|
|
|
|
float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
|
|
|
|
|
|
|
|
p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
|
|
|
|
p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
|
|
|
|
p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
|
|
|
|
|
|
|
|
m += 4;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
o[0] = cb_tab[0][p[0]];
|
|
|
|
o[1] = cb_tab[1][p[1]];
|
|
|
|
o[2] = cb_tab[2][p[2]];
|
|
|
|
}
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
o[3] = cb_tab[3][p[3]];
|
|
|
|
|
|
|
|
p += 4; o += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, float *mask_rect_float, int width, int height, float mul)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-08-07 16:09:42 +00:00
|
|
|
float *p = rect_float;
|
2014-04-27 00:20:13 +10:00
|
|
|
const float *e = rect_float + width * 4 * height;
|
|
|
|
const float *m = mask_rect_float;
|
2012-08-19 15:41:56 +00:00
|
|
|
StripColorBalance cb = calc_cb(cb_);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
while (p < e) {
|
|
|
|
int c;
|
|
|
|
for (c = 0; c < 3; c++) {
|
2012-08-11 14:37:58 +00:00
|
|
|
float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
|
|
|
|
|
|
|
|
if (m)
|
|
|
|
p[c] = p[c] * (1.0f - m[c]) + t * m[c];
|
|
|
|
else
|
|
|
|
p[c] = t;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2012-08-11 14:37:58 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
p += 4;
|
2012-08-11 14:37:58 +00:00
|
|
|
if (m)
|
|
|
|
m += 4;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 16:47:46 +00:00
|
|
|
typedef struct ColorBalanceInitData {
|
2012-08-19 15:41:56 +00:00
|
|
|
StripColorBalance *cb;
|
2012-08-07 16:47:46 +00:00
|
|
|
ImBuf *ibuf;
|
|
|
|
float mul;
|
2012-08-11 14:37:58 +00:00
|
|
|
ImBuf *mask;
|
2014-03-20 15:45:20 +06:00
|
|
|
bool make_float;
|
2012-08-07 16:47:46 +00:00
|
|
|
} ColorBalanceInitData;
|
|
|
|
|
2012-08-07 16:09:42 +00:00
|
|
|
typedef struct ColorBalanceThread {
|
2012-08-19 15:41:56 +00:00
|
|
|
StripColorBalance *cb;
|
2012-08-07 16:09:42 +00:00
|
|
|
float mul;
|
|
|
|
|
|
|
|
int width, height;
|
|
|
|
|
2012-08-11 14:37:58 +00:00
|
|
|
unsigned char *rect, *mask_rect;
|
|
|
|
float *rect_float, *mask_rect_float;
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
bool make_float;
|
2012-08-07 16:09:42 +00:00
|
|
|
} ColorBalanceThread;
|
|
|
|
|
2012-08-07 16:47:46 +00:00
|
|
|
static void color_balance_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
|
|
|
|
{
|
|
|
|
ColorBalanceThread *handle = (ColorBalanceThread *) handle_v;
|
|
|
|
ColorBalanceInitData *init_data = (ColorBalanceInitData *) init_data_v;
|
|
|
|
ImBuf *ibuf = init_data->ibuf;
|
2012-08-11 14:37:58 +00:00
|
|
|
ImBuf *mask = init_data->mask;
|
2012-08-07 16:47:46 +00:00
|
|
|
|
|
|
|
int offset = 4 * start_line * ibuf->x;
|
|
|
|
|
|
|
|
memset(handle, 0, sizeof(ColorBalanceThread));
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
handle->cb = init_data->cb;
|
2012-08-07 16:47:46 +00:00
|
|
|
handle->mul = init_data->mul;
|
|
|
|
handle->width = ibuf->x;
|
|
|
|
handle->height = tot_line;
|
2012-08-19 15:41:56 +00:00
|
|
|
handle->make_float = init_data->make_float;
|
2012-08-07 16:47:46 +00:00
|
|
|
|
|
|
|
if (ibuf->rect)
|
|
|
|
handle->rect = (unsigned char *) ibuf->rect + offset;
|
|
|
|
|
|
|
|
if (ibuf->rect_float)
|
|
|
|
handle->rect_float = ibuf->rect_float + offset;
|
2012-08-11 14:37:58 +00:00
|
|
|
|
|
|
|
if (mask) {
|
|
|
|
if (mask->rect)
|
|
|
|
handle->mask_rect = (unsigned char *) mask->rect + offset;
|
|
|
|
|
|
|
|
if (mask->rect_float)
|
|
|
|
handle->mask_rect_float = mask->rect_float + offset;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
handle->mask_rect = NULL;
|
|
|
|
handle->mask_rect_float = NULL;
|
|
|
|
}
|
2012-08-07 16:47:46 +00:00
|
|
|
}
|
|
|
|
|
2012-08-07 16:09:42 +00:00
|
|
|
static void *color_balance_do_thread(void *thread_data_v)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-08-07 16:09:42 +00:00
|
|
|
ColorBalanceThread *thread_data = (ColorBalanceThread *) thread_data_v;
|
2012-08-19 15:41:56 +00:00
|
|
|
StripColorBalance *cb = thread_data->cb;
|
2012-08-07 16:09:42 +00:00
|
|
|
int width = thread_data->width, height = thread_data->height;
|
|
|
|
unsigned char *rect = thread_data->rect;
|
2012-08-11 14:37:58 +00:00
|
|
|
unsigned char *mask_rect = thread_data->mask_rect;
|
2012-08-07 16:09:42 +00:00
|
|
|
float *rect_float = thread_data->rect_float;
|
2012-08-11 14:37:58 +00:00
|
|
|
float *mask_rect_float = thread_data->mask_rect_float;
|
2012-08-07 16:09:42 +00:00
|
|
|
float mul = thread_data->mul;
|
|
|
|
|
|
|
|
if (rect_float) {
|
2012-08-19 15:41:56 +00:00
|
|
|
color_balance_float_float(cb, rect_float, mask_rect_float, width, height, mul);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
else if (thread_data->make_float) {
|
|
|
|
color_balance_byte_float(cb, rect, rect_float, mask_rect, width, height, mul);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-08-19 15:41:56 +00:00
|
|
|
color_balance_byte_byte(cb, rect, mask_rect, width, height, mul);
|
2012-08-07 16:09:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-20 12:39:25 +01:00
|
|
|
/* cfra is offset by fra_offset only in case we are using a real mask. */
|
|
|
|
ImBuf *BKE_sequencer_render_mask_input(
|
|
|
|
const SeqRenderData *context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id,
|
|
|
|
int cfra, int fra_offset, bool make_float)
|
2012-08-19 15:41:56 +00:00
|
|
|
{
|
|
|
|
ImBuf *mask_input = NULL;
|
|
|
|
|
|
|
|
if (mask_input_type == SEQUENCE_MASK_INPUT_STRIP) {
|
|
|
|
if (mask_sequence) {
|
|
|
|
mask_input = seq_render_strip(context, mask_sequence, cfra);
|
|
|
|
|
|
|
|
if (make_float) {
|
|
|
|
if (!mask_input->rect_float)
|
|
|
|
IMB_float_from_rect(mask_input);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!mask_input->rect)
|
|
|
|
IMB_rect_from_float(mask_input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) {
|
2015-03-20 12:39:25 +01:00
|
|
|
mask_input = seq_render_mask(context, mask_id, cfra - fra_offset, make_float);
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return mask_input;
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float mul, bool make_float, ImBuf *mask_input)
|
2012-08-07 16:09:42 +00:00
|
|
|
{
|
2012-08-11 14:37:58 +00:00
|
|
|
ColorBalanceInitData init_data;
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (!ibuf->rect_float && make_float)
|
2012-08-07 16:47:46 +00:00
|
|
|
imb_addrectfloatImBuf(ibuf);
|
2012-08-07 16:09:42 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
init_data.cb = cb;
|
2012-08-11 14:37:58 +00:00
|
|
|
init_data.ibuf = ibuf;
|
|
|
|
init_data.mul = mul;
|
2012-08-19 15:41:56 +00:00
|
|
|
init_data.make_float = make_float;
|
|
|
|
init_data.mask = mask_input;
|
2012-08-07 16:09:42 +00:00
|
|
|
|
2012-08-11 14:37:58 +00:00
|
|
|
IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
|
2013-02-04 00:18:09 +00:00
|
|
|
color_balance_init_handle, color_balance_do_thread);
|
2012-08-07 16:09:42 +00:00
|
|
|
|
2012-08-12 18:38:01 +00:00
|
|
|
/* color balance either happens on float buffer or byte buffer, but never on both,
|
|
|
|
* free byte buffer if there's float buffer since float buffer would be used for
|
|
|
|
* color balance in favor of byte buffer
|
|
|
|
*/
|
|
|
|
if (ibuf->rect_float && ibuf->rect)
|
|
|
|
imb_freerectImBuf(ibuf);
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
2012-08-12 18:38:01 +00:00
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
/*
|
2012-06-07 15:49:02 +00:00
|
|
|
* input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE
|
2012-03-09 18:28:30 +00:00
|
|
|
*
|
|
|
|
* Do all the things you can't really do afterwards using sequence effects
|
|
|
|
* (read: before rescaling to render resolution has been done)
|
|
|
|
*
|
|
|
|
* Order is important!
|
|
|
|
*
|
|
|
|
* - Deinterlace
|
|
|
|
* - Crop and transform in image source coordinate space
|
|
|
|
* - Flip X + Flip Y (could be done afterwards, backward compatibility)
|
|
|
|
* - Promote image to float data (affects pipeline operations afterwards)
|
|
|
|
* - Color balance (is most efficient in the byte -> float
|
|
|
|
* (future: half -> float should also work fine!)
|
|
|
|
* case, if done on load, since we can use lookup tables)
|
|
|
|
* - Premultiply
|
|
|
|
*/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
bool BKE_sequencer_input_have_to_preprocess(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra))
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
float mul;
|
|
|
|
|
2014-03-20 15:08:23 +06:00
|
|
|
if (context->is_proxy_render) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return false;
|
2014-03-20 15:08:23 +06:00
|
|
|
}
|
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mul = seq->mul;
|
|
|
|
|
2012-03-24 06:18:31 +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) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2011-03-30 16:11:16 +00:00
|
|
|
if (seq->sat != 1.0f) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
if (seq->modifiers.first) {
|
2014-03-20 15:45:20 +06:00
|
|
|
return true;
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
2014-03-20 15:45:20 +06:00
|
|
|
|
|
|
|
return false;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, float cfra, ImBuf *ibuf,
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool is_proxy_image, const bool is_preprocessed)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2014-01-19 00:16:19 +06:00
|
|
|
Scene *scene = context->scene;
|
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);
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if ((seq->flag & SEQ_FILTERY) &&
|
2012-06-07 15:49:02 +00:00
|
|
|
!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP))
|
2012-03-29 22:26:11 +00:00
|
|
|
{
|
2010-07-23 16:57:11 +00:00
|
|
|
IMB_filtery(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (seq->flag & (SEQ_USE_CROP | SEQ_USE_TRANSFORM)) {
|
|
|
|
StripCrop c = {0};
|
|
|
|
StripTransform t = {0};
|
|
|
|
int sx, sy, dx, dy;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-18 11:13:28 +00:00
|
|
|
if (is_proxy_image) {
|
2014-01-19 00:16:19 +06:00
|
|
|
double f = seq_rendersize_to_scale_factor(context->preview_render_size);
|
2012-03-17 19:31:28 +00:00
|
|
|
|
2012-03-18 11:13:28 +00:00
|
|
|
if (f != 1.0) {
|
2012-08-08 11:15:36 +00:00
|
|
|
IMB_scalefastImBuf(ibuf, ibuf->x / f, ibuf->y / f);
|
2012-03-18 11:13:28 +00:00
|
|
|
}
|
2012-03-17 19:31:28 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SEQ_USE_CROP && seq->strip->crop) {
|
2009-01-12 19:02:08 +00:00
|
|
|
c = *seq->strip->crop;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) {
|
2009-01-12 19:02:08 +00:00
|
|
|
t = *seq->strip->transform;
|
|
|
|
}
|
|
|
|
|
2013-02-10 21:01:30 +00:00
|
|
|
if (is_preprocessed) {
|
2014-01-19 00:16:19 +06:00
|
|
|
double xscale = scene->r.xsch ? ((double)context->rectx / (double)scene->r.xsch) : 1.0;
|
|
|
|
double yscale = scene->r.ysch ? ((double)context->recty / (double)scene->r.ysch) : 1.0;
|
2013-02-10 21:01:30 +00:00
|
|
|
if (seq->flag & SEQ_USE_TRANSFORM) {
|
|
|
|
t.xofs *= xscale;
|
|
|
|
t.yofs *= yscale;
|
|
|
|
}
|
|
|
|
if (seq->flag & SEQ_USE_CROP) {
|
|
|
|
c.left *= xscale;
|
|
|
|
c.right *= xscale;
|
|
|
|
c.top *= yscale;
|
|
|
|
c.bottom *= yscale;
|
|
|
|
}
|
|
|
|
}
|
2012-11-28 09:01:00 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
if (seq->flag & SEQ_USE_TRANSFORM) {
|
2012-03-18 11:13:28 +00:00
|
|
|
if (is_preprocessed) {
|
2014-01-19 00:16:19 +06:00
|
|
|
dx = context->rectx;
|
|
|
|
dy = context->recty;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-01-19 00:16:19 +06:00
|
|
|
dx = scene->r.xsch;
|
|
|
|
dy = scene->r.ysch;
|
2012-03-18 11:13:28 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2013-02-10 21:01:30 +00:00
|
|
|
else {
|
|
|
|
dx = sx;
|
|
|
|
dy = sy;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-05-20 19:49:27 +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);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-08-08 11:15:36 +00:00
|
|
|
ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
|
2014-01-19 00:16:19 +06:00
|
|
|
sequencer_imbuf_assign_spaces(scene, i);
|
2012-12-31 13:52:13 +00:00
|
|
|
|
2015-05-04 12:17:49 +02:00
|
|
|
IMB_metadata_copy(i, ibuf);
|
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
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +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
|
|
|
|
2012-03-24 06:18:31 +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
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->sat != 1.0f) {
|
2012-03-17 19:31:28 +00:00
|
|
|
IMB_saturation(ibuf, seq->sat);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mul = seq->mul;
|
|
|
|
|
2012-03-24 06:18:31 +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
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SEQ_MAKE_FLOAT) {
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
if (!ibuf->rect_float) {
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf, true);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +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
|
|
|
}
|
|
|
|
|
2015-02-06 15:58:39 +01:00
|
|
|
if (ibuf->x != context->rectx || ibuf->y != context->recty) {
|
|
|
|
if (scene->r.mode & R_OSA) {
|
|
|
|
IMB_scaleImBuf(ibuf, (short)context->rectx, (short)context->recty);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
IMB_scalefastImBuf(ibuf, (short)context->rectx, (short)context->recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
if (seq->modifiers.first) {
|
|
|
|
ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra);
|
|
|
|
|
|
|
|
if (ibuf_new != ibuf) {
|
2015-05-04 12:17:49 +02:00
|
|
|
IMB_metadata_copy(ibuf_new, ibuf);
|
2012-08-19 15:41:56 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
ibuf = ibuf_new;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
return ibuf;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq, float nr)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +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) {
|
2012-08-08 11:15:40 +00:00
|
|
|
ibuf = BKE_sequencer_cache_get(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (nr == seq->len - 1) {
|
2012-08-08 11:15:40 +00:00
|
|
|
ibuf = BKE_sequencer_cache_get(context, seq, seq->start, 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);
|
2015-05-04 12:17:49 +02:00
|
|
|
IMB_metadata_copy(rval, ibuf);
|
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
|
|
|
|
|
|
|
return rval;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, float nr, ImBuf *ibuf)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-10-08 02:20:47 +00:00
|
|
|
/* warning: ibuf may be NULL if the video fails to load */
|
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
|
2012-03-09 18:28:30 +00:00
|
|
|
* could be preprocessed afterwards (thereby silently
|
|
|
|
* changing the cached image... */
|
2015-05-04 12:17:49 +02:00
|
|
|
ImBuf *oibuf = ibuf;
|
|
|
|
ibuf = IMB_dupImBuf(oibuf);
|
2011-04-17 10:05:27 +00:00
|
|
|
|
2012-10-08 02:20:47 +00:00
|
|
|
if (ibuf) {
|
2015-05-04 12:17:49 +02:00
|
|
|
IMB_metadata_copy(ibuf, oibuf);
|
2014-01-19 00:16:19 +06:00
|
|
|
sequencer_imbuf_assign_spaces(context->scene, ibuf);
|
2012-10-08 02:20:47 +00:00
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2011-04-17 10:05:27 +00:00
|
|
|
if (nr == 0) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2011-04-17 10:05:27 +00:00
|
|
|
|
|
|
|
if (nr == seq->len - 1) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
|
2011-04-17 10:05:27 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** strip rendering functions *************************/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 16:46:45 +00:00
|
|
|
typedef struct RenderEffectInitData {
|
|
|
|
struct SeqEffectHandle *sh;
|
2014-01-19 00:16:19 +06:00
|
|
|
const SeqRenderData *context;
|
2012-08-08 16:46:45 +00:00
|
|
|
Sequence *seq;
|
|
|
|
float cfra, facf0, facf1;
|
|
|
|
ImBuf *ibuf1, *ibuf2, *ibuf3;
|
|
|
|
|
|
|
|
ImBuf *out;
|
|
|
|
} RenderEffectInitData;
|
|
|
|
|
|
|
|
typedef struct RenderEffectThread {
|
|
|
|
struct SeqEffectHandle *sh;
|
2014-01-19 00:16:19 +06:00
|
|
|
const SeqRenderData *context;
|
2012-08-08 16:46:45 +00:00
|
|
|
Sequence *seq;
|
|
|
|
float cfra, facf0, facf1;
|
|
|
|
ImBuf *ibuf1, *ibuf2, *ibuf3;
|
|
|
|
|
|
|
|
ImBuf *out;
|
|
|
|
int start_line, tot_line;
|
|
|
|
} RenderEffectThread;
|
|
|
|
|
|
|
|
static void render_effect_execute_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
|
|
|
|
{
|
|
|
|
RenderEffectThread *handle = (RenderEffectThread *) handle_v;
|
|
|
|
RenderEffectInitData *init_data = (RenderEffectInitData *) init_data_v;
|
|
|
|
|
|
|
|
handle->sh = init_data->sh;
|
|
|
|
handle->context = init_data->context;
|
|
|
|
handle->seq = init_data->seq;
|
|
|
|
handle->cfra = init_data->cfra;
|
|
|
|
handle->facf0 = init_data->facf0;
|
|
|
|
handle->facf1 = init_data->facf1;
|
|
|
|
handle->ibuf1 = init_data->ibuf1;
|
|
|
|
handle->ibuf2 = init_data->ibuf2;
|
|
|
|
handle->ibuf3 = init_data->ibuf3;
|
|
|
|
handle->out = init_data->out;
|
|
|
|
|
|
|
|
handle->start_line = start_line;
|
|
|
|
handle->tot_line = tot_line;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *render_effect_execute_do_thread(void *thread_data_v)
|
|
|
|
{
|
|
|
|
RenderEffectThread *thread_data = (RenderEffectThread *) thread_data_v;
|
|
|
|
|
|
|
|
thread_data->sh->execute_slice(thread_data->context, thread_data->seq, thread_data->cfra,
|
|
|
|
thread_data->facf0, thread_data->facf1, thread_data->ibuf1,
|
|
|
|
thread_data->ibuf2, thread_data->ibuf3, thread_data->start_line,
|
|
|
|
thread_data->tot_line, thread_data->out);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, const SeqRenderData *context, Sequence *seq,
|
2012-08-08 16:46:45 +00:00
|
|
|
float cfra, float facf0, float facf1,
|
|
|
|
ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
|
|
|
|
{
|
|
|
|
RenderEffectInitData init_data;
|
|
|
|
ImBuf *out = sh->init_execution(context, ibuf1, ibuf2, ibuf3);
|
|
|
|
|
|
|
|
init_data.sh = sh;
|
|
|
|
init_data.context = context;
|
|
|
|
init_data.seq = seq;
|
|
|
|
init_data.cfra = cfra;
|
|
|
|
init_data.facf0 = facf0;
|
|
|
|
init_data.facf1 = facf1;
|
|
|
|
init_data.ibuf1 = ibuf1;
|
|
|
|
init_data.ibuf2 = ibuf2;
|
|
|
|
init_data.ibuf3 = ibuf3;
|
|
|
|
init_data.out = out;
|
|
|
|
|
|
|
|
IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data,
|
2014-08-05 13:36:35 +10:00
|
|
|
render_effect_execute_init_handle, render_effect_execute_do_thread);
|
2012-08-08 16:46:45 +00:00
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, Sequence *seq, float cfra)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2014-01-19 00:16:19 +06:00
|
|
|
Scene *scene = context->scene;
|
2010-07-23 16:57:11 +00:00
|
|
|
float fac, facf;
|
|
|
|
int early_out;
|
|
|
|
int i;
|
2012-08-08 11:15:40 +00:00
|
|
|
struct SeqEffectHandle sh = BKE_sequence_get_effect(seq);
|
2012-03-29 22:26:11 +00:00
|
|
|
FCurve *fcu = NULL;
|
|
|
|
ImBuf *ibuf[3];
|
2010-10-30 21:55:17 +00:00
|
|
|
Sequence *input[3];
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *out = NULL;
|
2010-10-30 21:55:17 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2012-08-08 16:46:45 +00:00
|
|
|
if (!sh.execute && !(sh.execute_slice && sh.init_execution)) {
|
2012-08-08 11:15:36 +00:00
|
|
|
/* effect not supported in this version... */
|
2014-01-19 00:16:19 +06:00
|
|
|
out = IMB_allocImBuf(context->rectx, 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
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
if ((scene->r.mode & R_FIELDS) == 0)
|
2012-03-29 22:26:11 +00:00
|
|
|
facf = fac;
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-01-19 00:16:19 +06:00
|
|
|
fcu = id_data_find_fcurve(&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);
|
2014-01-19 00:16:19 +06:00
|
|
|
if (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
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-07-23 16:57:11 +00:00
|
|
|
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) {
|
2012-03-29 22:26:11 +00:00
|
|
|
case EARLY_NO_INPUT:
|
2012-08-08 16:46:42 +00:00
|
|
|
out = sh.execute(context, seq, cfra, fac, facf, NULL, NULL, NULL);
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
|
|
|
case EARLY_DO_EFFECT:
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (input[i])
|
2012-08-08 16:46:42 +00:00
|
|
|
ibuf[i] = seq_render_strip(context, input[i], cfra);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
|
|
|
|
if (ibuf[0] && ibuf[1]) {
|
2012-08-08 16:46:45 +00:00
|
|
|
if (sh.multithreaded)
|
|
|
|
out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
|
|
|
|
else
|
|
|
|
out = sh.execute(context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
|
|
|
case EARLY_USE_INPUT_1:
|
|
|
|
if (input[0]) {
|
|
|
|
ibuf[0] = seq_render_strip(context, input[0], cfra);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ibuf[0]) {
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequencer_input_have_to_preprocess(context, seq, cfra)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
out = IMB_dupImBuf(ibuf[0]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
out = ibuf[0];
|
|
|
|
IMB_refImBuf(out);
|
|
|
|
}
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
|
|
|
case EARLY_USE_INPUT_2:
|
|
|
|
if (input[1]) {
|
|
|
|
ibuf[1] = seq_render_strip(context, input[1], cfra);
|
|
|
|
}
|
|
|
|
if (ibuf[1]) {
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequencer_input_have_to_preprocess(context, seq, cfra)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
out = IMB_dupImBuf(ibuf[1]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
out = ibuf[1];
|
|
|
|
IMB_refImBuf(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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) {
|
2014-01-19 00:16:19 +06:00
|
|
|
out = IMB_allocImBuf(context->rectx, 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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
|
|
|
|
{
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
char name[FILE_MAX];
|
|
|
|
bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
|
|
|
|
(context->scene->r.scemode & R_MULTIVIEW) != 0;
|
|
|
|
StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
if (s_elem) {
|
|
|
|
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
}
|
|
|
|
|
2015-05-04 12:17:49 +02:00
|
|
|
flag = IB_rect | IB_metadata;
|
2015-04-06 10:40:12 -03:00
|
|
|
if (seq->alpha_mode == SEQ_ALPHA_PREMUL)
|
|
|
|
flag |= IB_alphamode_premul;
|
|
|
|
|
|
|
|
if (!s_elem) {
|
|
|
|
/* don't do anything */
|
|
|
|
}
|
|
|
|
else if (is_multiview) {
|
|
|
|
size_t totfiles = seq_num_files(context->scene, seq->views_format, true);
|
|
|
|
size_t totviews;
|
|
|
|
struct ImBuf **ibufs_arr;
|
|
|
|
char prefix[FILE_MAX];
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *ext = NULL;
|
2015-04-06 10:40:12 -03:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (totfiles > 1) {
|
|
|
|
BKE_scene_multiview_view_prefix_get(context->scene, name, prefix, &ext);
|
|
|
|
if (prefix[0] == '\0') {
|
|
|
|
goto monoview_image;
|
|
|
|
}
|
|
|
|
}
|
2015-04-09 17:30:26 +10:00
|
|
|
else {
|
|
|
|
prefix[0] = '\0';
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
|
|
|
|
ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
|
|
|
|
|
|
|
|
for (i = 0; i < totfiles; i++) {
|
|
|
|
|
|
|
|
if (prefix[0] == '\0') {
|
|
|
|
ibufs_arr[i] = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char str[FILE_MAX];
|
|
|
|
seq_multiview_name(context->scene, i, prefix, ext, str, FILE_MAX);
|
|
|
|
ibufs_arr[i] = IMB_loadiffname(str, flag, seq->strip->colorspace_settings.name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ibufs_arr[i]) {
|
|
|
|
/* we don't need both (speed reasons)! */
|
|
|
|
if (ibufs_arr[i]->rect_float && ibufs_arr[i]->rect)
|
|
|
|
imb_freerectImBuf(ibufs_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->views_format == R_IMF_VIEWS_STEREO_3D && ibufs_arr[0])
|
|
|
|
IMB_ImBufFromStereo3d(seq->stereo3d_format, ibufs_arr[0], &ibufs_arr[0], &ibufs_arr[1]);
|
|
|
|
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
if (ibufs_arr[i]) {
|
|
|
|
SeqRenderData localcontext = *context;
|
|
|
|
localcontext.view_id = i;
|
|
|
|
|
|
|
|
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
|
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false);
|
|
|
|
|
|
|
|
if (i != context->view_id) {
|
|
|
|
copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]);
|
|
|
|
BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the original requested ImBuf */
|
|
|
|
ibuf = ibufs_arr[context->view_id];
|
|
|
|
if (ibuf) {
|
|
|
|
s_elem->orig_width = ibufs_arr[0]->x;
|
|
|
|
s_elem->orig_height = ibufs_arr[0]->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* "remove" the others (decrease their refcount) */
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
if (ibufs_arr[i] != ibuf) {
|
|
|
|
IMB_freeImBuf(ibufs_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(ibufs_arr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
monoview_image:
|
|
|
|
if ((ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) {
|
|
|
|
/* we don't need both (speed reasons)! */
|
|
|
|
if (ibuf->rect_float && ibuf->rect)
|
|
|
|
imb_freerectImBuf(ibuf);
|
|
|
|
|
|
|
|
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
|
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
|
|
|
|
|
|
|
|
s_elem->orig_width = ibuf->x;
|
|
|
|
s_elem->orig_height = ibuf->y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
|
|
|
|
{
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
StripAnim *sanim;
|
|
|
|
bool is_multiview = (seq->flag & SEQ_USE_VIEWS) != 0 &&
|
|
|
|
(context->scene->r.scemode & R_MULTIVIEW) != 0;
|
|
|
|
|
|
|
|
/* load all the videos */
|
|
|
|
seq_open_anim_file(context->scene, seq, false);
|
|
|
|
|
|
|
|
if (is_multiview) {
|
|
|
|
ImBuf **ibuf_arr;
|
|
|
|
size_t totviews;
|
|
|
|
size_t totfiles = seq_num_files(context->scene, seq->views_format, true);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1))
|
|
|
|
goto monoview_movie;
|
|
|
|
|
|
|
|
totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
|
|
|
|
ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
|
|
|
|
|
|
|
|
for (i = 0, sanim = seq->anims.first; sanim; sanim = sanim->next, i++) {
|
|
|
|
if (sanim->anim) {
|
|
|
|
IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size);
|
|
|
|
IMB_anim_set_preseek(sanim->anim, seq->anim_preseek);
|
|
|
|
|
|
|
|
ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
|
|
|
|
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
|
|
|
|
proxy_size);
|
|
|
|
|
|
|
|
/* fetching for requested proxy size failed, try fetching the original instead */
|
|
|
|
if (!ibuf_arr[i] && proxy_size != IMB_PROXY_NONE) {
|
|
|
|
ibuf_arr[i] = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
|
|
|
|
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
|
|
|
|
IMB_PROXY_NONE);
|
|
|
|
}
|
|
|
|
if (ibuf_arr[i]) {
|
|
|
|
/* we don't need both (speed reasons)! */
|
|
|
|
if (ibuf_arr[i]->rect_float && ibuf_arr[i]->rect)
|
|
|
|
imb_freerectImBuf(ibuf_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->views_format == R_IMF_VIEWS_STEREO_3D) {
|
|
|
|
if (ibuf_arr[0]) {
|
|
|
|
IMB_ImBufFromStereo3d(seq->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* probably proxy hasn't been created yet */
|
|
|
|
MEM_freeN(ibuf_arr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
SeqRenderData localcontext = *context;
|
|
|
|
localcontext.view_id = i;
|
|
|
|
|
|
|
|
if (ibuf_arr[i]) {
|
|
|
|
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
|
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf_arr[i], false);
|
|
|
|
}
|
|
|
|
if (i != context->view_id) {
|
|
|
|
copy_to_ibuf_still(&localcontext, seq, nr, ibuf_arr[i]);
|
|
|
|
BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the original requested ImBuf */
|
|
|
|
ibuf = ibuf_arr[context->view_id];
|
|
|
|
if (ibuf) {
|
|
|
|
seq->strip->stripdata->orig_width = ibuf->x;
|
|
|
|
seq->strip->stripdata->orig_height = ibuf->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* "remove" the others (decrease their refcount) */
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
if (ibuf_arr[i] != ibuf) {
|
|
|
|
IMB_freeImBuf(ibuf_arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(ibuf_arr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
monoview_movie:
|
|
|
|
sanim = seq->anims.first;
|
|
|
|
if (sanim && sanim->anim) {
|
|
|
|
IMB_Proxy_Size proxy_size = seq_rendersize_to_proxysize(context->preview_render_size);
|
|
|
|
IMB_anim_set_preseek(sanim->anim, seq->anim_preseek);
|
|
|
|
|
|
|
|
ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
|
|
|
|
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
|
|
|
|
proxy_size);
|
|
|
|
|
|
|
|
/* fetching for requested proxy size failed, try fetching the original instead */
|
|
|
|
if (!ibuf && proxy_size != IMB_PROXY_NONE) {
|
|
|
|
ibuf = IMB_anim_absolute(sanim->anim, nr + seq->anim_startofs,
|
|
|
|
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
|
|
|
|
IMB_PROXY_NONE);
|
|
|
|
}
|
|
|
|
if (ibuf) {
|
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
|
|
|
|
|
|
|
|
/* we don't need both (speed reasons)! */
|
|
|
|
if (ibuf->rect_float && ibuf->rect) {
|
|
|
|
imb_freerectImBuf(ibuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
seq->strip->stripdata->orig_width = ibuf->x;
|
|
|
|
seq->strip->stripdata->orig_height = ibuf->y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context, Sequence *seq, float nr)
|
2012-03-21 18:02:29 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *ibuf = NULL;
|
2012-03-21 18:02:29 +00:00
|
|
|
MovieClipUser user;
|
|
|
|
float tloc[2], tscale, tangle;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!seq->clip) {
|
2012-03-21 18:02:29 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&user, 0, sizeof(MovieClipUser));
|
|
|
|
|
2012-09-24 15:27:04 +00:00
|
|
|
BKE_movieclip_user_set_frame(&user, nr + seq->anim_startofs + seq->clip->start_frame);
|
2012-03-21 18:02:29 +00:00
|
|
|
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
switch (seq_rendersize_to_proxysize(context->preview_render_size)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
case IMB_PROXY_NONE:
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
|
|
|
|
break;
|
|
|
|
case IMB_PROXY_100:
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_100;
|
|
|
|
break;
|
|
|
|
case IMB_PROXY_75:
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_75;
|
|
|
|
break;
|
|
|
|
case IMB_PROXY_50:
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_50;
|
|
|
|
break;
|
|
|
|
case IMB_PROXY_25:
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_25;
|
|
|
|
break;
|
2012-03-21 18:02:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->clip_flag & SEQ_MOVIECLIP_RENDER_UNDISTORTED) {
|
|
|
|
user.render_flag = MCLIP_PROXY_RENDER_UNDISTORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seq->clip_flag & SEQ_MOVIECLIP_RENDER_STABILIZED) {
|
2012-08-08 11:15:36 +00:00
|
|
|
ibuf = BKE_movieclip_get_stable_ibuf(seq->clip, &user, tloc, &tscale, &tangle, 0);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-08-08 11:15:36 +00:00
|
|
|
ibuf = BKE_movieclip_get_ibuf_flag(seq->clip, &user, 0, MOVIECLIP_CACHE_SKIP);
|
2012-03-21 18:02:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2012-06-07 18:24:36 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr, bool make_float)
|
2012-06-07 18:24:36 +00:00
|
|
|
{
|
|
|
|
/* TODO - add option to rasterize to alpha imbuf? */
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
float *maskbuf;
|
|
|
|
int i;
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (!mask) {
|
2012-06-07 18:24:36 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-07-31 15:45:01 +00:00
|
|
|
else {
|
|
|
|
Mask *mask_temp;
|
|
|
|
MaskRasterHandle *mr_handle;
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
mask_temp = BKE_mask_copy_nolib(mask);
|
2012-07-31 15:45:01 +00:00
|
|
|
|
2013-10-29 18:46:45 +00:00
|
|
|
BKE_mask_evaluate(mask_temp, mask->sfra + nr, true);
|
2012-07-31 15:45:01 +00:00
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__);
|
2012-07-31 15:45:01 +00:00
|
|
|
|
|
|
|
mr_handle = BKE_maskrasterize_handle_new();
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_maskrasterize_handle_init(mr_handle, mask_temp, context->rectx, context->recty, true, true, true);
|
2012-06-07 18:24:36 +00:00
|
|
|
|
2012-09-14 01:15:08 +00:00
|
|
|
BKE_mask_free_nolib(mask_temp);
|
2012-07-31 15:45:01 +00:00
|
|
|
MEM_freeN(mask_temp);
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
BKE_maskrasterize_buffer(mr_handle, context->rectx, context->recty, maskbuf);
|
2012-07-31 15:45:01 +00:00
|
|
|
|
|
|
|
BKE_maskrasterize_handle_free(mr_handle);
|
|
|
|
}
|
2012-06-07 18:24:36 +00:00
|
|
|
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (make_float) {
|
2012-06-07 18:24:36 +00:00
|
|
|
/* pixels */
|
2014-04-27 00:20:13 +10:00
|
|
|
const float *fp_src;
|
2012-06-07 18:24:36 +00:00
|
|
|
float *fp_dst;
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ibuf = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rectfloat);
|
2012-06-07 18:24:36 +00:00
|
|
|
|
|
|
|
fp_src = maskbuf;
|
|
|
|
fp_dst = ibuf->rect_float;
|
2014-01-19 00:16:19 +06:00
|
|
|
i = context->rectx * context->recty;
|
2012-06-27 18:29:47 +00:00
|
|
|
while (--i) {
|
2012-06-07 18:24:36 +00:00
|
|
|
fp_dst[0] = fp_dst[1] = fp_dst[2] = *fp_src;
|
|
|
|
fp_dst[3] = 1.0f;
|
|
|
|
|
|
|
|
fp_src += 1;
|
|
|
|
fp_dst += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* pixels */
|
2014-04-27 00:20:13 +10:00
|
|
|
const float *fp_src;
|
2012-06-07 18:24:36 +00:00
|
|
|
unsigned char *ub_dst;
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ibuf = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect);
|
2012-06-07 18:24:36 +00:00
|
|
|
|
|
|
|
fp_src = maskbuf;
|
|
|
|
ub_dst = (unsigned char *)ibuf->rect;
|
2014-01-19 00:16:19 +06:00
|
|
|
i = context->rectx * context->recty;
|
2012-06-27 18:29:47 +00:00
|
|
|
while (--i) {
|
2012-06-07 18:24:36 +00:00
|
|
|
ub_dst[0] = ub_dst[1] = ub_dst[2] = (unsigned char)(*fp_src * 255.0f); /* already clamped */
|
|
|
|
ub_dst[3] = 255;
|
|
|
|
|
|
|
|
fp_src += 1;
|
|
|
|
ub_dst += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(maskbuf);
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_mask_strip(const SeqRenderData *context, Sequence *seq, float nr)
|
2012-08-19 15:41:56 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
bool make_float = (seq->flag & SEQ_MAKE_FLOAT) != 0;
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
return seq_render_mask(context, seq->mask, nr, make_float);
|
|
|
|
}
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
|
2010-07-23 16:57:11 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *ibuf = NULL;
|
2012-03-21 18:02:29 +00:00
|
|
|
float frame;
|
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:
|
2012-03-09 18:28:30 +00:00
|
|
|
* Hack! This function can be called from do_render_seq(), in that case
|
|
|
|
* the seq->scene can already have a Render initialized with same name,
|
|
|
|
* so we have to use a default name. (compositor uses scene name to
|
|
|
|
* find render).
|
|
|
|
* However, when called from within the UI (image preview in sequencer)
|
|
|
|
* we do want to use scene Render, that way the render result is defined
|
|
|
|
* for display in render/imagewindow
|
|
|
|
*
|
|
|
|
* Hmm, don't see, why we can't do that all the time,
|
2012-08-08 18:37:06 +00:00
|
|
|
* and since G.is_rendering is uhm, gone... (Peter)
|
2012-03-09 18:28:30 +00:00
|
|
|
*/
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2010-10-21 17:00:38 +00:00
|
|
|
/* New info:
|
2012-03-09 18:28:30 +00:00
|
|
|
* 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-10-21 17:00:38 +00:00
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool is_rendering = G.is_rendering;
|
2014-03-20 15:45:20 +06:00
|
|
|
const bool is_background = G.background;
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool do_seq_gl = is_rendering ?
|
|
|
|
0 /* (context->scene->r.seq_flag & R_SEQ_GL_REND) */ :
|
|
|
|
(context->scene->r.seq_flag & R_SEQ_GL_PREV) != 0;
|
2012-10-24 03:27:11 +00:00
|
|
|
int do_seq;
|
2014-03-20 15:45:20 +06:00
|
|
|
// bool have_seq = false; /* UNUSED */
|
|
|
|
bool have_comp = false;
|
2014-12-05 16:39:49 +13:00
|
|
|
bool use_gpencil = true;
|
2011-04-30 06:22:02 +00:00
|
|
|
Scene *scene;
|
2012-11-09 16:49:17 +00:00
|
|
|
int is_thread_main = BLI_thread_is_main();
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* don't refer to seq->scene above this point!, it can be NULL */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene == NULL) {
|
2011-04-30 06:22:02 +00:00
|
|
|
return NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
scene = seq->scene;
|
|
|
|
frame = scene->r.sfra + nr + seq->anim_startofs;
|
2010-07-30 11:40:23 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
|
2012-11-21 09:36:36 +00:00
|
|
|
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
|
2011-04-30 06:22:02 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
oldcfra = scene->r.cfra;
|
|
|
|
scene->r.cfra = frame;
|
2009-06-08 20:08:19 +00:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
if (seq->scene_camera) {
|
2012-03-29 22:26:11 +00:00
|
|
|
camera = seq->scene_camera;
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-05 14:33:36 +00:00
|
|
|
BKE_scene_camera_switch_update(scene);
|
2012-03-29 22:26:11 +00:00
|
|
|
camera = scene->camera;
|
2011-04-30 05:42:37 +00:00
|
|
|
}
|
2014-12-05 16:39:49 +13:00
|
|
|
|
|
|
|
if (seq->flag & SEQ_SCENE_NO_GPENCIL) {
|
|
|
|
use_gpencil = false;
|
|
|
|
}
|
2011-04-30 06:22:02 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
if (have_comp == false && camera == NULL) {
|
2012-03-29 22:26:11 +00:00
|
|
|
scene->r.cfra = oldcfra;
|
2011-04-30 06:22:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* prevent eternal loop */
|
2014-06-28 18:32:29 +02:00
|
|
|
do_seq = scene->r.scemode & R_DOSEQ;
|
2012-11-09 16:49:17 +00:00
|
|
|
scene->r.scemode &= ~R_DOSEQ;
|
2010-07-23 16:57:11 +00:00
|
|
|
|
|
|
|
#ifdef DURIAN_CAMERA_SWITCH
|
|
|
|
/* stooping to new low's in hackyness :( */
|
2012-03-29 22:26:11 +00:00
|
|
|
oldmarkers = scene->markers;
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&scene->markers);
|
2011-11-05 14:26:18 +00:00
|
|
|
#else
|
|
|
|
(void)oldmarkers;
|
2010-07-23 16:57:11 +00:00
|
|
|
#endif
|
2012-10-24 03:27:11 +00:00
|
|
|
|
2012-11-11 11:00:55 +00:00
|
|
|
if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) {
|
2012-03-29 22:26:11 +00:00
|
|
|
char err_out[256] = "unknown";
|
2014-04-24 14:28:18 +06:00
|
|
|
int width = (scene->r.xsch * scene->r.size) / 100;
|
|
|
|
int height = (scene->r.ysch * scene->r.size) / 100;
|
2015-04-06 10:40:12 -03:00
|
|
|
const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id);
|
2014-04-24 14:28:18 +06:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
/* for old scened this can be uninitialized,
|
|
|
|
* should probably be added to do_versions at some point if the functionality stays */
|
2014-01-19 00:16:19 +06: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 */
|
2014-01-19 00:16:19 +06:00
|
|
|
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
|
2014-04-24 14:28:18 +06:00
|
|
|
ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect,
|
2014-03-20 15:45:20 +06:00
|
|
|
context->scene->r.seq_prev_type,
|
|
|
|
(context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
|
2015-04-06 10:40:12 -03:00
|
|
|
use_gpencil, true, scene->r.alphamode, viewname, err_out);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf == NULL) {
|
2012-03-21 18:02:29 +00:00
|
|
|
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
|
2011-03-06 23:12:12 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-04-30 06:22:02 +00:00
|
|
|
Render *re = RE_GetRender(scene->id.name);
|
2015-04-06 10:40:12 -03:00
|
|
|
size_t totviews = BKE_scene_multiview_num_views_get(&scene->r);
|
|
|
|
int i;
|
|
|
|
ImBuf **ibufs_arr;
|
|
|
|
|
|
|
|
ibufs_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs");
|
2010-10-21 17:00:38 +00:00
|
|
|
|
2012-11-09 16:49:17 +00:00
|
|
|
/* XXX: this if can be removed when sequence preview rendering uses the job system
|
|
|
|
*
|
|
|
|
* disable rendered preview for sequencer while rendering -- it's very much possible
|
|
|
|
* that preview render will went into conflict with final render
|
2012-11-22 11:45:39 +00:00
|
|
|
*
|
|
|
|
* When rendering from command line renderer is called from main thread, in this
|
|
|
|
* case it's always safe to render scene here
|
2012-11-09 16:49:17 +00:00
|
|
|
*/
|
2015-01-27 17:13:21 +05:00
|
|
|
if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (re == NULL)
|
|
|
|
re = RE_NewRender(scene->id.name);
|
2013-12-26 17:24:42 +06:00
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
|
2014-04-01 11:34:00 +11: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 */
|
2012-10-24 03:27:11 +00:00
|
|
|
G.is_rendering = is_rendering;
|
2010-10-21 17:00:38 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
SeqRenderData localcontext = *context;
|
|
|
|
RenderResult rres;
|
|
|
|
|
|
|
|
localcontext.view_id = i;
|
|
|
|
|
|
|
|
RE_AcquireResultImage(re, &rres, i);
|
|
|
|
|
|
|
|
if (rres.rectf) {
|
|
|
|
ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat);
|
|
|
|
memcpy(ibufs_arr[i]->rect_float, rres.rectf, 4 * sizeof(float) * rres.rectx * rres.recty);
|
|
|
|
|
|
|
|
if (rres.rectz) {
|
|
|
|
addzbuffloatImBuf(ibufs_arr[i]);
|
|
|
|
memcpy(ibufs_arr[i]->zbuf_float, rres.rectz, sizeof(float) * rres.rectx * rres.recty);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* float buffers in the sequencer are not linear */
|
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibufs_arr[i], false);
|
|
|
|
}
|
|
|
|
else if (rres.rect32) {
|
|
|
|
ibufs_arr[i] = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
|
|
|
|
memcpy(ibufs_arr[i]->rect, rres.rect32, 4 * rres.rectx * rres.recty);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2010-07-30 11:55:41 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (i != context->view_id) {
|
|
|
|
copy_to_ibuf_still(&localcontext, seq, nr, ibufs_arr[i]);
|
|
|
|
BKE_sequencer_cache_put(&localcontext, seq, cfra, SEQ_STRIPELEM_IBUF, ibufs_arr[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
RE_ReleaseResultImage(re);
|
2010-07-30 11:55:41 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
/* return the original requested ImBuf */
|
|
|
|
ibuf = ibufs_arr[context->view_id];
|
|
|
|
|
|
|
|
/* "remove" the others (decrease their refcount) */
|
|
|
|
for (i = 0; i < totviews; i++) {
|
|
|
|
if (ibufs_arr[i] != ibuf) {
|
|
|
|
IMB_freeImBuf(ibufs_arr[i]);
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
MEM_freeN(ibufs_arr);
|
|
|
|
|
2010-07-23 16:57:11 +00:00
|
|
|
// BIF_end_render_callbacks();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore */
|
2012-11-09 16:49:17 +00:00
|
|
|
scene->r.scemode |= do_seq;
|
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
|
|
|
|
2013-12-26 17:24:42 +06:00
|
|
|
if (frame != oldcfra) {
|
2014-01-19 00:16:19 +06:00
|
|
|
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
|
2013-12-26 17:24:42 +06:00
|
|
|
}
|
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 :( */
|
2012-03-29 22:26:11 +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
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *seq, float cfra)
|
2010-07-23 16:57:11 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *ibuf = NULL;
|
2010-07-23 16:57:11 +00:00
|
|
|
float nr = give_stripelem_index(seq, cfra);
|
2012-06-07 15:49:02 +00:00
|
|
|
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
|
2014-03-20 15:45:20 +06:00
|
|
|
bool use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
switch (type) {
|
|
|
|
case SEQ_TYPE_META:
|
|
|
|
{
|
|
|
|
ImBuf *meta_ibuf = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (seq->seqbase.first)
|
|
|
|
meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (meta_ibuf) {
|
|
|
|
ibuf = meta_ibuf;
|
|
|
|
if (ibuf && use_preprocess) {
|
|
|
|
ImBuf *i = IMB_dupImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
ibuf = i;
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
2012-03-29 22:26:11 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
case SEQ_TYPE_SPEED:
|
|
|
|
{
|
|
|
|
ImBuf *child_ibuf = NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
float f_cfra;
|
|
|
|
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
/* weeek! */
|
|
|
|
f_cfra = seq->start + s->frameMap[(int)nr];
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
child_ibuf = seq_render_strip(context, seq->seq1, f_cfra);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (child_ibuf) {
|
|
|
|
ibuf = child_ibuf;
|
|
|
|
if (ibuf && use_preprocess) {
|
|
|
|
ImBuf *i = IMB_dupImBuf(ibuf);
|
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
|
|
|
ibuf = i;
|
2010-10-30 21:55:17 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-08-08 11:15:32 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
case SEQ_TYPE_EFFECT:
|
|
|
|
{
|
|
|
|
ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr);
|
|
|
|
break;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
case SEQ_TYPE_IMAGE:
|
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
ibuf = seq_render_image_strip(context, seq, nr, cfra);
|
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
2012-08-19 15:41:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SEQ_TYPE_MOVIE:
|
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
ibuf = seq_render_movie_strip(context, seq, nr, cfra);
|
2012-08-19 15:41:56 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
|
|
|
break;
|
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
case SEQ_TYPE_SCENE:
|
|
|
|
{
|
|
|
|
/* scene can be NULL after deletions */
|
2015-04-06 10:40:12 -03:00
|
|
|
ibuf = seq_render_scene_strip(context, seq, nr, cfra);
|
2010-12-03 12:08:59 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
/* Scene strips update all animation, so we need to restore original state.*/
|
2014-01-19 00:16:19 +06:00
|
|
|
BKE_animsys_evaluate_all_animation(context->bmain, context->scene, cfra);
|
2012-03-21 18:02:29 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
|
|
|
break;
|
|
|
|
}
|
2012-03-21 18:02:29 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
case SEQ_TYPE_MOVIECLIP:
|
|
|
|
{
|
|
|
|
ibuf = seq_render_movieclip_strip(context, seq, nr);
|
2012-03-21 18:02:29 +00:00
|
|
|
|
2012-09-24 14:48:24 +00:00
|
|
|
if (ibuf) {
|
2012-09-24 15:26:59 +00:00
|
|
|
/* duplicate frame so movie cache wouldn't be confused by sequencer's stuff */
|
|
|
|
ImBuf *i = IMB_dupImBuf(ibuf);
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
ibuf = i;
|
2012-03-21 18:02:29 +00:00
|
|
|
|
2012-09-24 15:26:59 +00:00
|
|
|
if (ibuf->rect_float)
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequencer_imbuf_to_sequencer_space(context->scene, ibuf, false);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2012-09-24 14:48:24 +00:00
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
2012-03-29 22:26:11 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-06-07 18:24:36 +00:00
|
|
|
case SEQ_TYPE_MASK:
|
|
|
|
{
|
|
|
|
/* ibuf is alwats new */
|
|
|
|
ibuf = seq_render_mask_strip(context, seq, nr);
|
|
|
|
|
|
|
|
copy_to_ibuf_still(context, seq, nr, ibuf);
|
|
|
|
break;
|
|
|
|
}
|
2012-08-08 11:15:36 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
if (ibuf)
|
2014-01-19 00:16:19 +06:00
|
|
|
sequencer_imbuf_assign_spaces(context->scene, ibuf);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, float cfra)
|
2012-08-19 15:41:56 +00:00
|
|
|
{
|
|
|
|
ImBuf *ibuf = NULL;
|
2014-02-03 18:55:59 +11:00
|
|
|
bool use_preprocess = false;
|
|
|
|
bool is_proxy_image = false;
|
2012-08-19 15:41:56 +00:00
|
|
|
float nr = give_stripelem_index(seq, cfra);
|
|
|
|
/* all effects are handled similarly with the exception of speed effect */
|
|
|
|
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
|
2014-07-20 01:30:29 +10:00
|
|
|
bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
|
|
|
|
|
|
|
|
if (ibuf == NULL) {
|
2014-06-17 18:52:39 +10:00
|
|
|
ibuf = copy_from_ibuf_still(context, seq, nr);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
if (ibuf == NULL) {
|
2012-12-31 13:52:13 +00:00
|
|
|
ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
if (ibuf == NULL) {
|
|
|
|
/* MOVIECLIPs have their own proxy management */
|
|
|
|
if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
|
|
|
|
ibuf = seq_proxy_fetch(context, seq, cfra);
|
|
|
|
is_proxy_image = (ibuf != NULL);
|
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
if (ibuf == NULL)
|
|
|
|
ibuf = do_render_strip_uncached(context, seq, cfra);
|
|
|
|
|
2014-03-20 15:08:23 +06:00
|
|
|
if (ibuf) {
|
|
|
|
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP)) {
|
|
|
|
is_proxy_image = (context->preview_render_size != 100);
|
|
|
|
}
|
2012-12-31 13:52:13 +00:00
|
|
|
BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
|
2014-03-20 15:08:23 +06:00
|
|
|
}
|
2012-12-31 13:52:13 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
2012-12-31 13:52:13 +00:00
|
|
|
|
|
|
|
if (ibuf)
|
|
|
|
use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
|
|
|
|
* but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL
|
|
|
|
* so, no need in check for preprocess here
|
|
|
|
*/
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
|
|
|
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
if (ibuf == NULL) {
|
2014-01-19 00:16:19 +06:00
|
|
|
ibuf = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect);
|
|
|
|
sequencer_imbuf_assign_spaces(context->scene, ibuf);
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-03-20 15:08:23 +06:00
|
|
|
if (context->is_proxy_render == false &&
|
|
|
|
(ibuf->x != context->rectx || ibuf->y != context->recty))
|
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
use_preprocess = true;
|
2014-03-20 15:08:23 +06:00
|
|
|
}
|
2010-07-24 19:42:29 +00:00
|
|
|
|
2010-10-30 21:55:17 +00:00
|
|
|
if (use_preprocess)
|
2012-08-08 11:15:36 +00:00
|
|
|
ibuf = input_preprocess(context, seq, cfra, ibuf, is_proxy_image, is_preprocessed);
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_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
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/*********************** strip stack rendering functions *************************/
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2014-02-05 22:36:15 +11:00
|
|
|
static bool seq_must_swap_input_in_blend_mode(Sequence *seq)
|
2010-03-14 16:36:41 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
bool swap_input = false;
|
2010-03-14 16:36:41 +00:00
|
|
|
|
|
|
|
/* bad hack, to fix crazy input ordering of
|
2012-03-09 18:28:30 +00:00
|
|
|
* those two effects */
|
2010-03-14 16:36:41 +00:00
|
|
|
|
2014-07-20 01:30:29 +10:00
|
|
|
if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
|
2014-03-20 15:45:20 +06:00
|
|
|
swap_input = true;
|
2010-03-14 16:36:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return swap_input;
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
static int seq_get_early_out_for_blend_mode(Sequence *seq)
|
2010-03-14 16:36:41 +00:00
|
|
|
{
|
2012-08-08 11:15:40 +00:00
|
|
|
struct SeqEffectHandle sh = BKE_sequence_get_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);
|
2014-02-11 16:02:26 +06:00
|
|
|
|
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;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (early_out == EARLY_USE_INPUT_1) {
|
2010-10-30 21:55:17 +00:00
|
|
|
return EARLY_USE_INPUT_2;
|
2010-03-14 16:36:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return early_out;
|
|
|
|
}
|
|
|
|
|
2014-02-11 16:02:26 +06:00
|
|
|
static ImBuf *seq_render_strip_stack_apply_effect(const SeqRenderData *context, Sequence *seq,
|
|
|
|
float cfra, ImBuf *ibuf1, ImBuf *ibuf2)
|
|
|
|
{
|
|
|
|
ImBuf *out;
|
|
|
|
struct SeqEffectHandle sh = BKE_sequence_get_blend(seq);
|
|
|
|
float facf = seq->blend_opacity / 100.0f;
|
|
|
|
int swap_input = seq_must_swap_input_in_blend_mode(seq);
|
|
|
|
|
|
|
|
if (swap_input) {
|
|
|
|
if (sh.multithreaded)
|
|
|
|
out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL);
|
|
|
|
else
|
|
|
|
out = sh.execute(context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (sh.multithreaded)
|
|
|
|
out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL);
|
|
|
|
else
|
|
|
|
out = sh.execute(context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seqbasep, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq_arr[MAXSEQ + 1];
|
2009-01-12 19:02:08 +00:00
|
|
|
int count;
|
|
|
|
int i;
|
2012-03-29 22:26:11 +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 */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scene->r.cfra != cfra) {
|
2012-07-07 22:51:57 +00:00
|
|
|
/* XXX for prefetch and overlay offset!..., very bad!!! */
|
2012-03-29 22:26:11 +00:00
|
|
|
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
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
out = BKE_sequencer_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
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (count == 1) {
|
2014-02-11 19:28:41 +06:00
|
|
|
Sequence *seq = seq_arr[0];
|
|
|
|
|
2014-02-11 16:02:26 +06:00
|
|
|
/* Some of the blend modes are unclear how to apply with only single input,
|
|
|
|
* or some of them will just produce an empty result..
|
|
|
|
*/
|
2014-07-20 01:30:29 +10:00
|
|
|
if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
|
2014-02-11 19:28:41 +06:00
|
|
|
int early_out;
|
|
|
|
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
|
|
|
|
early_out = EARLY_NO_INPUT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
early_out = seq_get_early_out_for_blend_mode(seq);
|
|
|
|
}
|
|
|
|
|
2014-02-11 16:02:26 +06:00
|
|
|
if (ELEM(early_out, EARLY_NO_INPUT, EARLY_USE_INPUT_2)) {
|
2014-02-11 19:28:41 +06:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2014-02-11 16:02:26 +06:00
|
|
|
}
|
|
|
|
else if (early_out == EARLY_USE_INPUT_1) {
|
|
|
|
out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect);
|
|
|
|
}
|
|
|
|
else {
|
2014-02-11 19:28:41 +06:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2014-02-11 16:02:26 +06:00
|
|
|
|
|
|
|
if (early_out == EARLY_DO_EFFECT) {
|
|
|
|
ImBuf *ibuf1 = IMB_allocImBuf(context->rectx, context->recty, 32,
|
|
|
|
out->rect_float ? IB_rectfloat : IB_rect);
|
|
|
|
ImBuf *ibuf2 = out;
|
|
|
|
|
2014-02-11 19:28:41 +06:00
|
|
|
out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2);
|
2014-02-11 16:02:26 +06:00
|
|
|
|
2015-05-04 12:52:58 +02:00
|
|
|
IMB_metadata_copy(out, ibuf2);
|
|
|
|
|
2014-02-11 16:02:26 +06:00
|
|
|
IMB_freeImBuf(ibuf1);
|
|
|
|
IMB_freeImBuf(ibuf2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2014-02-11 19:28:41 +06:00
|
|
|
out = seq_render_strip(context, seq, cfra);
|
2014-02-11 16:02:26 +06:00
|
|
|
}
|
Color Management, Stage 2: Switch color pipeline to use OpenColorIO
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.
This introduces two configurable color spaces:
- Input color space for images and movie clips. This space is used to convert
images/movies from color space in which file is saved to Blender's linear
space (for float images, byte images are not internally converted, only input
space is stored for such images and used later).
This setting could be found in image/clip data block settings.
- Display color space which defines space in which particular display is working.
This settings could be found in scene's Color Management panel.
When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.
This conversions are:
- View, which defines tone curve applying before display transformation.
These are different ways to view the image on the same display device.
For example it could be used to emulate film view on sRGB display.
- Exposure affects on image exposure before tone map is applied.
- Gamma is post-display gamma correction, could be used to match particular
display gamma.
- RGB curves are user-defined curves which are applying before display
transformation, could be used for different purposes.
All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.
This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).
Some technical notes:
- Image buffer's float buffer is now always in linear space, even if it was
created from 16bit byte images.
- Space of byte buffer is stored in image buffer's rect_colorspace property.
- Profile of image buffer was removed since it's not longer meaningful.
- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
to support other spaces, but it's quite large project which isn't so
much important.
- Legacy Color Management option disabled is emulated by using None display.
It could have some regressions, but there's no clear way to avoid them.
- If OpenColorIO is disabled on build time, it should make blender behaving
in the same way as previous release with color management enabled.
More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management
--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!
2012-09-15 10:05:07 +00:00
|
|
|
|
2014-02-11 19:28:41 +06:00
|
|
|
BKE_sequencer_cache_put(context, seq, 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
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
out = BKE_sequencer_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) {
|
2012-03-29 22:26:11 +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);
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
|
|
|
case EARLY_USE_INPUT_1:
|
|
|
|
if (i == 0) {
|
2014-01-19 00:16:19 +06:00
|
|
|
out = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect);
|
2012-03-29 22:26:11 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EARLY_DO_EFFECT:
|
|
|
|
if (i == 0) {
|
2014-06-04 22:05:33 +06:00
|
|
|
ImBuf *ibuf1 = IMB_allocImBuf(context->rectx, context->recty, 32, IB_rect);
|
|
|
|
ImBuf *ibuf2 = seq_render_strip(context, seq, cfra);
|
|
|
|
|
|
|
|
out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2);
|
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf1);
|
|
|
|
IMB_freeImBuf(ibuf2);
|
2012-03-29 22:26:11 +00:00
|
|
|
}
|
2010-07-23 16:57:11 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
break;
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_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++) {
|
2012-03-29 22:26:11 +00:00
|
|
|
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) {
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *ibuf1 = out;
|
|
|
|
ImBuf *ibuf2 = seq_render_strip(context, seq, cfra);
|
2010-02-10 17:28:46 +00:00
|
|
|
|
2014-02-11 16:02:26 +06:00
|
|
|
out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2);
|
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
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_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
|
|
|
*/
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(context->scene, false);
|
2009-01-12 19:02:08 +00:00
|
|
|
ListBase *seqbasep;
|
2009-01-28 22:36:34 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ed == NULL) return NULL;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-05-29 02:22:04 +10:00
|
|
|
if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) {
|
2014-11-16 13:57:58 +01:00
|
|
|
int count = BLI_listbase_count(&ed->metastack);
|
2012-10-23 16:21:55 +00:00
|
|
|
count = max_ii(count + chanshown, 0);
|
2012-03-29 22:26:11 +00:00
|
|
|
seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:26:11 +00:00
|
|
|
seqbasep = ed->seqbasep;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ImBuf *BKE_sequencer_give_ibuf_seqbase(const 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ImBuf *BKE_sequencer_give_ibuf_direct(const 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
|
|
|
}
|
|
|
|
|
|
|
|
/* *********************** 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;
|
2012-03-29 22:26:11 +00:00
|
|
|
static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
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;
|
2012-03-29 22:26:11 +00:00
|
|
|
static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
static volatile bool 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;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
ImBuf *ibuf;
|
2009-01-12 19:02:08 +00:00
|
|
|
} PrefetchQueueElem;
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
void BKE_sequencer_give_ibuf_prefetch_request(const 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");
|
2014-01-19 00:16:19 +06:00
|
|
|
e->rectx = context->rectx;
|
|
|
|
e->recty = context->recty;
|
2009-01-12 19:02:08 +00:00
|
|
|
e->cfra = cfra;
|
|
|
|
e->chanshown = chanshown;
|
2014-01-19 00:16:19 +06: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);
|
|
|
|
}
|
|
|
|
|
2014-01-19 00:16:19 +06:00
|
|
|
ImBuf *BKE_sequencer_give_ibuf_threaded(const SeqRenderData *context, float cfra, int chanshown)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
PrefetchQueueElem *e = NULL;
|
2014-03-20 15:45:20 +06:00
|
|
|
bool found_something = false;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
if (seq_thread_shutdown) {
|
2012-08-08 11:15:40 +00:00
|
|
|
return BKE_sequencer_give_ibuf(context, cfra, chanshown);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (!e) {
|
2014-03-20 15:45:20 +06:00
|
|
|
bool success = false;
|
2009-01-12 19:02:08 +00:00
|
|
|
pthread_mutex_lock(&queue_lock);
|
|
|
|
|
|
|
|
for (e = prefetch_done.first; e; e = e->next) {
|
|
|
|
if (cfra == e->cfra &&
|
2012-03-29 22:26:11 +00:00
|
|
|
chanshown == e->chanshown &&
|
2014-01-19 00:16:19 +06:00
|
|
|
context->rectx == e->rectx &&
|
|
|
|
context->recty == e->recty &&
|
|
|
|
context->preview_render_size == e->preview_render_size)
|
2012-03-29 22:26:11 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
success = true;
|
|
|
|
found_something = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
for (e = prefetch_wait.first; e; e = e->next) {
|
|
|
|
if (cfra == e->cfra &&
|
2012-03-29 22:26:11 +00:00
|
|
|
chanshown == e->chanshown &&
|
2014-01-19 00:16:19 +06:00
|
|
|
context->rectx == e->rectx &&
|
|
|
|
context->recty == e->recty &&
|
|
|
|
context->preview_render_size == e->preview_render_size)
|
2012-03-29 22:26:11 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
found_something = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
PrefetchThread *tslot;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
for (tslot = running_threads.first;
|
|
|
|
tslot;
|
2012-03-29 22:26:11 +00:00
|
|
|
tslot = tslot->next)
|
2012-02-23 02:17:50 +00:00
|
|
|
{
|
2009-01-12 19:02:08 +00:00
|
|
|
if (tslot->current &&
|
2012-02-23 02:17:50 +00:00
|
|
|
cfra == tslot->current->cfra &&
|
|
|
|
chanshown == tslot->current->chanshown &&
|
2014-01-19 00:16:19 +06:00
|
|
|
context->rectx == tslot->current->rectx &&
|
|
|
|
context->recty == tslot->current->recty &&
|
|
|
|
context->preview_render_size == tslot->current->preview_render_size)
|
2012-02-23 02:17:50 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
found_something = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
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) {
|
2012-08-08 11:15:36 +00:00
|
|
|
fprintf(stderr, "SEQ-THREAD: Requested frame not in queue ???\n");
|
2009-01-12 19:02:08 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-08-11 14:37:58 +00:00
|
|
|
/* check whether sequence cur depends on seq */
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
|
2012-08-11 14:37:58 +00:00
|
|
|
{
|
2012-08-27 09:01:36 +00:00
|
|
|
if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq)
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2012-08-27 09:01:36 +00:00
|
|
|
|
2012-08-11 14:37:58 +00:00
|
|
|
/* sequences are not intersecting in time, assume no dependency exists between them */
|
|
|
|
if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp)
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-08-11 14:37:58 +00:00
|
|
|
|
|
|
|
/* checking sequence is below reference one, not dependent on it */
|
|
|
|
if (cur->machine < seq->machine)
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-08-11 14:37:58 +00:00
|
|
|
|
|
|
|
/* sequence is not blending with lower machines, no dependency here occurs
|
|
|
|
* check for non-effects only since effect could use lower machines as input
|
|
|
|
*/
|
|
|
|
if ((cur->type & SEQ_TYPE_EFFECT) == 0 &&
|
2013-03-09 05:35:49 +00:00
|
|
|
((cur->blend_mode == SEQ_BLEND_REPLACE) ||
|
|
|
|
(cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f)))
|
2012-08-11 14:37:58 +00:00
|
|
|
{
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-08-11 14:37:58 +00:00
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2012-08-11 14:37:58 +00:00
|
|
|
}
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
static void sequence_do_invalidate_dependent(Sequence *seq, ListBase *seqbase)
|
|
|
|
{
|
|
|
|
Sequence *cur;
|
|
|
|
|
|
|
|
for (cur = seqbase->first; cur; cur = cur->next) {
|
|
|
|
if (cur == seq)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (BKE_sequence_check_depend(seq, cur)) {
|
|
|
|
BKE_sequencer_cache_cleanup_sequence(cur);
|
|
|
|
BKE_sequencer_preprocessed_cache_cleanup_sequence(cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cur->seqbase.first)
|
|
|
|
sequence_do_invalidate_dependent(seq, &cur->seqbase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
static void sequence_invalidate_cache(Scene *scene, Sequence *seq, bool invalidate_self, bool invalidate_preprocess)
|
2012-08-08 16:46:40 +00:00
|
|
|
{
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
|
|
|
|
/* invalidate cache for current sequence */
|
2013-07-15 07:58:15 +00:00
|
|
|
if (invalidate_self) {
|
2015-04-06 10:40:12 -03:00
|
|
|
/* Animation structure holds some buffers inside,
|
|
|
|
* so for proper cache invalidation we need to
|
|
|
|
* re-open the animation.
|
|
|
|
*/
|
|
|
|
BKE_sequence_free_anim(seq);
|
2012-09-13 10:51:18 +00:00
|
|
|
BKE_sequencer_cache_cleanup_sequence(seq);
|
2013-07-15 07:58:15 +00:00
|
|
|
}
|
2012-09-13 10:51:18 +00:00
|
|
|
|
|
|
|
/* if invalidation is invoked from sequence free routine, effectdata would be NULL here */
|
|
|
|
if (seq->effectdata && seq->type == SEQ_TYPE_SPEED)
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
|
2012-08-08 16:46:40 +00:00
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (invalidate_preprocess)
|
|
|
|
BKE_sequencer_preprocessed_cache_cleanup_sequence(seq);
|
|
|
|
|
2012-08-08 16:46:40 +00:00
|
|
|
/* invalidate cache for all dependent sequences */
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
/* NOTE: can not use SEQ_BEGIN/SEQ_END here because that macro will change sequence's depth,
|
|
|
|
* which makes transformation routines work incorrect
|
|
|
|
*/
|
|
|
|
sequence_do_invalidate_dependent(seq, &ed->seqbase);
|
2012-08-08 16:46:40 +00:00
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
|
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
sequence_invalidate_cache(scene, seq, true, true);
|
2012-09-13 10:51:18 +00:00
|
|
|
}
|
|
|
|
|
2012-10-04 18:30:28 +00:00
|
|
|
void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq)
|
2012-09-13 10:51:18 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
sequence_invalidate_cache(scene, seq, false, true);
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq)
|
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
sequence_invalidate_cache(scene, seq, true, false);
|
2012-08-19 15:41:56 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
2009-08-02 23:02:59 +00:00
|
|
|
|
2012-08-08 11:56:58 +00:00
|
|
|
BKE_sequencer_cache_cleanup();
|
2012-09-14 14:28:24 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
2012-09-14 14:28:24 +00:00
|
|
|
if (for_render && CFRA >= seq->startdisp && CFRA <= seq->enddisp) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->strip) {
|
2012-09-14 14:28:24 +00:00
|
|
|
if (seq->type == SEQ_TYPE_MOVIE) {
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_sequence_free_anim(seq);
|
2012-09-14 14:28:24 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_SPEED) {
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2012-09-14 14:28:24 +00:00
|
|
|
BKE_sequencer_free_imbuf(scene, &seq->seqbase, for_render);
|
2009-08-02 23:02:59 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_SCENE) {
|
2009-08-02 23:02:59 +00:00
|
|
|
/* FIXME: recurs downwards,
|
2012-04-22 11:54:53 +00:00
|
|
|
* 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
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
|
|
|
Sequence *subseq;
|
2014-03-20 15:45:20 +06:00
|
|
|
bool free_imbuf = false;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
|
|
|
/* recurs downwards to see if this seq depends on the changed seq */
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq == NULL)
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq == changed_seq)
|
2014-03-20 15:45:20 +06:00
|
|
|
free_imbuf = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (subseq = seq->seqbase.first; subseq; subseq = subseq->next)
|
2012-03-24 06:18:31 +00:00
|
|
|
if (update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change))
|
2014-03-20 15:45:20 +06:00
|
|
|
free_imbuf = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->seq1)
|
|
|
|
if (update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change))
|
2014-03-20 15:45:20 +06:00
|
|
|
free_imbuf = true;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->seq2 && (seq->seq2 != seq->seq1))
|
|
|
|
if (update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change))
|
2014-03-20 15:45:20 +06:00
|
|
|
free_imbuf = true;
|
2012-03-24 06:18:31 +00:00
|
|
|
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))
|
2014-03-20 15:45:20 +06:00
|
|
|
free_imbuf = true;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (free_imbuf) {
|
|
|
|
if (ibuf_change) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_MOVIE)
|
2015-04-06 10:40:12 -03:00
|
|
|
BKE_sequence_free_anim(seq);
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_SPEED) {
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len_change)
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc(scene, seq);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return free_imbuf;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2009-01-12 19:02:08 +00:00
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (ed == NULL) return;
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = ed->seqbase.first; seq; seq = seq->next)
|
2009-01-12 19:02:08 +00:00
|
|
|
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
|
2012-03-09 18:28:30 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2012-08-08 11:15:32 +00:00
|
|
|
static int seq_tx_get_start(Sequence *seq)
|
2011-09-28 05:53:40 +00:00
|
|
|
{
|
2009-01-21 07:01:20 +00:00
|
|
|
return seq->start;
|
|
|
|
}
|
2012-08-08 11:15:32 +00:00
|
|
|
static int seq_tx_get_end(Sequence *seq)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
return seq->start + seq->len;
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
2014-03-20 15:45:20 +06:00
|
|
|
int BKE_sequence_tx_get_final_left(Sequence *seq, bool metaclip)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
if (metaclip && seq->tmp) {
|
|
|
|
/* return the range clipped by the parents range */
|
2014-03-20 15:45:20 +06:00
|
|
|
return max_ii(BKE_sequence_tx_get_final_left(seq, false), BKE_sequence_tx_get_final_left((Sequence *)seq->tmp, true));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-21 07:01:20 +00:00
|
|
|
return (seq->start - seq->startstill) + seq->startofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2014-03-20 15:45:20 +06:00
|
|
|
int BKE_sequence_tx_get_final_right(Sequence *seq, bool metaclip)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
if (metaclip && seq->tmp) {
|
|
|
|
/* return the range clipped by the parents range */
|
2014-03-20 15:45:20 +06:00
|
|
|
return min_ii(BKE_sequence_tx_get_final_right(seq, false), BKE_sequence_tx_get_final_right((Sequence *)seq->tmp, true));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:26:11 +00:00
|
|
|
return ((seq->start + seq->len) + seq->endstill) - seq->endofs;
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_tx_set_final_left(Sequence *seq, int val)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
if (val < (seq)->start) {
|
|
|
|
seq->startstill = abs(val - (seq)->start);
|
2009-10-19 10:07:19 +00:00
|
|
|
seq->startofs = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-21 07:01:20 +00:00
|
|
|
seq->startofs = abs(val - (seq)->start);
|
|
|
|
seq->startstill = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_tx_set_final_right(Sequence *seq, int val)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
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;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-01-21 07:01:20 +00:00
|
|
|
seq->endofs = abs(val - ((seq)->start + (seq)->len));
|
|
|
|
seq->endstill = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* used so we can do a quick check for single image seq
|
2012-03-09 18:28:30 +00:00
|
|
|
* since they work a bit differently to normal image seq's (during transform) */
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_single_check(Sequence *seq)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
2012-04-21 15:11:03 +00:00
|
|
|
return ((seq->len == 1) &&
|
2012-06-07 15:49:02 +00:00
|
|
|
(seq->type == SEQ_TYPE_IMAGE ||
|
|
|
|
((seq->type & SEQ_TYPE_EFFECT) &&
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_effect_get_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 */
|
2014-11-06 14:06:24 +01:00
|
|
|
bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
|
2009-12-17 23:29:11 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
2014-11-06 14:06:24 +01:00
|
|
|
/* is there more than 1 select */
|
2013-03-09 05:35:49 +00:00
|
|
|
bool ok = false;
|
2009-12-17 23:29:11 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SELECT) {
|
2014-11-06 14:06:24 +01:00
|
|
|
ok = true;
|
|
|
|
break;
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
if (ok == false)
|
|
|
|
return false;
|
2009-12-17 23:29:11 +00:00
|
|
|
|
|
|
|
/* test relationships */
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if ((seq->type & SEQ_TYPE_EFFECT) == 0)
|
2010-10-30 21:55:17 +00:00
|
|
|
continue;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SELECT) {
|
2013-03-09 05:35:49 +00:00
|
|
|
if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) ||
|
|
|
|
(seq->seq2 && (seq->seq2->flag & SELECT) == 0) ||
|
|
|
|
(seq->seq3 && (seq->seq3->flag & SELECT) == 0) )
|
2012-04-28 06:31:57 +00:00
|
|
|
{
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
2010-10-30 21:55:17 +00:00
|
|
|
else {
|
2013-03-09 05:35:49 +00:00
|
|
|
if ((seq->seq1 && (seq->seq1->flag & SELECT)) ||
|
|
|
|
(seq->seq2 && (seq->seq2->flag & SELECT)) ||
|
|
|
|
(seq->seq3 && (seq->seq3->flag & SELECT)) )
|
2012-04-28 06:31:57 +00:00
|
|
|
{
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2009-12-17 23:29:11 +00:00
|
|
|
}
|
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* use to impose limits when dragging/extending - so impossible situations don't happen
|
2009-01-21 07:01:20 +00:00
|
|
|
* Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (leftflag) {
|
2014-03-20 15:45:20 +06:00
|
|
|
if (BKE_sequence_tx_get_final_left(seq, false) >= BKE_sequence_tx_get_final_right(seq, false)) {
|
|
|
|
BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_right(seq, false) - 1);
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequence_single_check(seq) == 0) {
|
2014-03-20 15:45:20 +06:00
|
|
|
if (BKE_sequence_tx_get_final_left(seq, false) >= seq_tx_get_end(seq)) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_tx_set_final_left(seq, seq_tx_get_end(seq) - 1);
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* dosnt work now - TODO */
|
2012-03-03 20:19:11 +00:00
|
|
|
#if 0
|
2009-01-21 07:01:20 +00:00
|
|
|
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;
|
2012-03-29 22:26:11 +00:00
|
|
|
seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs);
|
2012-03-03 20:19:11 +00:00
|
|
|
}
|
|
|
|
#endif
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (rightflag) {
|
2014-03-20 15:45:20 +06:00
|
|
|
if (BKE_sequence_tx_get_final_right(seq, false) <= BKE_sequence_tx_get_final_left(seq, false)) {
|
|
|
|
BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + 1);
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequence_single_check(seq) == 0) {
|
2014-03-20 15:45:20 +06:00
|
|
|
if (BKE_sequence_tx_get_final_right(seq, false) <= seq_tx_get_start(seq)) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_tx_set_final_right(seq, seq_tx_get_start(seq) + 1);
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sounds cannot be extended past their endpoints */
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->startstill = 0;
|
|
|
|
seq->endstill = 0;
|
2009-01-21 07:01:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_single_fix(Sequence *seq)
|
2009-01-21 07:01:20 +00:00
|
|
|
{
|
|
|
|
int left, start, offset;
|
2012-08-08 11:15:40 +00:00
|
|
|
if (!BKE_sequence_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,
|
2012-03-03 20:19:11 +00:00
|
|
|
* adjusting its start should be ok */
|
2014-03-20 15:45:20 +06:00
|
|
|
left = BKE_sequence_tx_get_final_left(seq, false);
|
2009-01-21 07:01:20 +00:00
|
|
|
start = seq->start;
|
|
|
|
if (start != left) {
|
|
|
|
offset = left - start;
|
2014-03-20 15:45:20 +06:00
|
|
|
BKE_sequence_tx_set_final_left(seq, BKE_sequence_tx_get_final_left(seq, false) - offset);
|
|
|
|
BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_right(seq, false) - offset);
|
2009-01-21 07:01:20 +00:00
|
|
|
seq->start += offset;
|
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_tx_test(Sequence *seq)
|
2009-01-23 23:14:02 +00:00
|
|
|
{
|
2012-08-08 11:15:40 +00:00
|
|
|
return (seq->type < SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0);
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
static bool seq_overlap(Sequence *seq1, Sequence *seq2)
|
2009-10-22 14:40:32 +00:00
|
|
|
{
|
2010-10-30 21:55:17 +00:00
|
|
|
return (seq1 != seq2 && seq1->machine == seq2->machine &&
|
2012-03-29 22:26:11 +00:00
|
|
|
((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0);
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq = seqbasep->first;
|
2012-03-24 06:18:31 +00:00
|
|
|
while (seq) {
|
|
|
|
if (seq_overlap(test, seq))
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2009-10-22 14:40:32 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq = seq->next;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_translate(Scene *evil_scene, Sequence *seq, int delta)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_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
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2009-01-25 14:53:41 +00:00
|
|
|
Sequence *seq_child;
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_translate(evil_scene, seq_child, delta);
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(evil_scene, seq);
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequence_sound_init(Scene *scene, Sequence *seq)
|
2011-04-01 08:51:12 +00:00
|
|
|
{
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2011-04-01 08:51:12 +00:00
|
|
|
Sequence *seq_child;
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_sound_init(scene, seq_child);
|
2011-04-01 08:51:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->sound) {
|
2015-03-26 11:35:41 +01:00
|
|
|
seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq);
|
2011-04-01 08:51:12 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene) {
|
2015-03-26 11:35:41 +01:00
|
|
|
seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(scene, seq);
|
2011-04-01 08:51:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
|
2011-02-17 22:34:41 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq, *best_seq = NULL;
|
2011-02-17 22:34:41 +00:00
|
|
|
int best_machine = -1;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ed) return NULL;
|
2011-02-17 22:34:41 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
|
2011-02-17 22:34:41 +00:00
|
|
|
continue;
|
|
|
|
/* only use elements you can see - not */
|
2014-07-20 01:30:29 +10:00
|
|
|
if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_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 */
|
2015-02-12 06:18:02 +11:00
|
|
|
bool BKE_sequence_base_shuffle_ex(ListBase *seqbasep, Sequence *test, Scene *evil_scene, int channel_delta)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2015-02-12 06:18:02 +11:00
|
|
|
const int orig_machine = test->machine;
|
|
|
|
BLI_assert(ELEM(channel_delta, -1, 1));
|
|
|
|
|
|
|
|
test->machine += channel_delta;
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc(evil_scene, test);
|
2015-02-12 06:18:02 +11:00
|
|
|
while (BKE_sequence_test_overlap(seqbasep, test)) {
|
|
|
|
if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine <= 1)) {
|
2009-01-25 14:53:41 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-02-12 06:18:02 +11:00
|
|
|
|
|
|
|
test->machine += channel_delta;
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc(evil_scene, test); // XXX - I don't think this is needed since were only moving vertically, Campbell.
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
2015-02-12 06:18:02 +11:00
|
|
|
if ((test->machine < 1) || (test->machine > MAXSEQ)) {
|
2009-01-25 14:53:41 +00:00
|
|
|
/* Blender 2.4x would remove the strip.
|
|
|
|
* nicer to move it to the end */
|
|
|
|
|
|
|
|
Sequence *seq;
|
2012-03-29 22:26:11 +00:00
|
|
|
int new_frame = test->enddisp;
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2009-01-25 14:53:41 +00:00
|
|
|
if (seq->machine == orig_machine)
|
2012-10-23 16:21:55 +00:00
|
|
|
new_frame = max_ii(new_frame, seq->enddisp);
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
test->machine = orig_machine;
|
|
|
|
new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_translate(evil_scene, test, new_frame - test->start);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc(evil_scene, test);
|
2013-03-09 05:35:49 +00:00
|
|
|
return false;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
}
|
2009-08-09 21:16:39 +00:00
|
|
|
|
2015-02-12 06:18:02 +11:00
|
|
|
bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
|
|
|
|
{
|
|
|
|
return BKE_sequence_base_shuffle_ex(seqbasep, test, evil_scene, 1);
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir)
|
2009-10-22 14:40:32 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
int offset = 0;
|
2009-10-22 14:40:32 +00:00
|
|
|
Sequence *seq, *seq_other;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->tmp) {
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq_other = seqbasep->first; seq_other; seq_other = seq_other->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!seq_other->tmp && seq_overlap(seq, seq_other)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
if (dir == 'L') {
|
2012-10-23 16:21:55 +00:00
|
|
|
offset = min_ii(offset, seq_other->startdisp - seq->enddisp);
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-10-23 16:21:55 +00:00
|
|
|
offset = max_ii(offset, seq_other->enddisp - seq->startdisp);
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir)
|
2009-10-22 14:40:32 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
int ofs = 0;
|
|
|
|
int tot_ofs = 0;
|
2009-10-22 14:40:32 +00:00
|
|
|
Sequence *seq;
|
2012-03-29 22:26:11 +00:00
|
|
|
while ( (ofs = shuffle_seq_time_offset_test(seqbasep, dir)) ) {
|
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->tmp) {
|
2009-10-22 14:40:32 +00:00
|
|
|
/* seq_test_overlap only tests display values */
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->startdisp += ofs;
|
|
|
|
seq->enddisp += ofs;
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
tot_ofs += ofs;
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->tmp)
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(scene, seq); /* corrects dummy startdisp/enddisp values */
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return tot_ofs;
|
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_base_shuffle_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');
|
2012-03-29 22:26:11 +00:00
|
|
|
int offset = (-offset_l < offset_r) ? offset_l : offset_r;
|
2009-10-22 14:40:32 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (offset) {
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->tmp) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_translate(evil_scene, seq, offset);
|
2009-10-22 14:40:32 +00:00
|
|
|
seq->flag &= ~SEQ_OVERLAP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
return offset ? false : true;
|
2009-10-22 14:40:32 +00:00
|
|
|
}
|
|
|
|
|
2013-08-20 19:50:31 +00:00
|
|
|
/* Unlike _update_sound_ funcs, these ones take info from audaspace to update sequence length! */
|
|
|
|
#ifdef WITH_AUDASPACE
|
2013-08-21 02:29:13 +00:00
|
|
|
static bool sequencer_refresh_sound_length_recursive(Scene *scene, ListBase *seqbase)
|
|
|
|
{
|
2013-08-20 19:50:31 +00:00
|
|
|
Sequence *seq;
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
|
|
|
if (sequencer_refresh_sound_length_recursive(scene, &seq->seqbase)) {
|
|
|
|
BKE_sequence_calc(scene, seq);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
|
|
|
AUD_SoundInfo info = AUD_getInfo(seq->sound->playback_handle);
|
|
|
|
int old = seq->len;
|
|
|
|
float fac;
|
|
|
|
|
|
|
|
seq->len = (int)ceil((double)info.length * FPS);
|
|
|
|
fac = (float)seq->len / (float)old;
|
|
|
|
old = seq->startofs;
|
|
|
|
seq->startofs *= fac;
|
|
|
|
seq->endofs *= fac;
|
|
|
|
seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */
|
|
|
|
|
|
|
|
BKE_sequence_calc(scene, seq);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void BKE_sequencer_refresh_sound_length(Scene *scene)
|
|
|
|
{
|
|
|
|
#ifdef WITH_AUDASPACE
|
|
|
|
if (scene->ed) {
|
|
|
|
sequencer_refresh_sound_length_recursive(scene, &scene->ed->seqbase);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
(void)scene;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_update_sound_bounds_all(Scene *scene)
|
2011-08-07 11:54:58 +00:00
|
|
|
{
|
|
|
|
Editing *ed = scene->ed;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ed) {
|
2011-08-07 11:54:58 +00:00
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (seq = ed->seqbase.first; seq; seq = seq->next) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_sound_bounds_recursive(scene, seq);
|
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_update_sound_bounds(scene, seq);
|
2011-08-07 11:54:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq)
|
2009-08-09 21:16:39 +00:00
|
|
|
{
|
2014-03-16 20:11:24 +01:00
|
|
|
if (seq->type == SEQ_TYPE_SCENE) {
|
|
|
|
if (seq->scene_sound) {
|
|
|
|
/* We have to take into account start frame of the sequence's scene! */
|
|
|
|
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
|
|
|
|
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs);
|
2014-03-16 20:11:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_move_scene_sound_defaults(scene, seq);
|
2014-03-16 20:11:24 +01:00
|
|
|
}
|
2012-01-05 10:34:50 +00:00
|
|
|
/* mute is set in seq_update_muting_recursive */
|
2009-12-08 13:57:51 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2012-04-22 11:54:53 +00:00
|
|
|
* since sound is played outside of evaluating the imbufs, */
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
|
|
|
seqmute = (mute || (seq->flag & SEQ_MUTE));
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2009-12-08 13:57:51 +00:00
|
|
|
/* if this is the current meta sequence, unmute because
|
2012-03-03 20:19:11 +00:00
|
|
|
* all sequences above this were set to mute */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq == metaseq)
|
2012-03-29 22:26:11 +00:00
|
|
|
seqmute = 0;
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2011-08-07 11:54:58 +00:00
|
|
|
seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute);
|
2009-12-08 13:57:51 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene_sound) {
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_mute_scene_sound(seq->scene_sound, seqmute);
|
2009-12-08 13:57:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_update_muting(Editing *ed)
|
2009-12-08 13:57:51 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ed) {
|
2009-12-08 13:57:51 +00:00
|
|
|
/* mute all sounds up to current metastack list */
|
2012-03-29 22:26:11 +00:00
|
|
|
MetaStack *ms = ed->metastack.last;
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
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;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbasep->first; seq; seq = seq->next) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2011-07-26 13:56:31 +00:00
|
|
|
seq_update_sound_recursive(scene, &seq->seqbase, sound);
|
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene_sound && sound == seq->sound) {
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_update_scene_sound(seq->scene_sound, sound);
|
2011-07-26 13:56:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_update_sound(Scene *scene, bSound *sound)
|
2011-07-26 13:56:31 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scene->ed) {
|
2011-07-26 13:56:31 +00:00
|
|
|
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 */
|
2012-08-08 11:15:40 +00:00
|
|
|
ListBase *BKE_sequence_seqbase(ListBase *seqbase, Sequence *seq)
|
2009-12-16 16:35:31 +00:00
|
|
|
{
|
|
|
|
Sequence *iseq;
|
2012-03-29 22:26:11 +00:00
|
|
|
ListBase *lb = NULL;
|
2009-12-16 16:35:31 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
|
|
|
|
if (seq == iseq) {
|
2009-12-16 16:35:31 +00:00
|
|
|
return seqbase;
|
|
|
|
}
|
2012-08-08 11:15:40 +00:00
|
|
|
else if (iseq->seqbase.first && (lb = BKE_sequence_seqbase(&iseq->seqbase, seq))) {
|
2009-12-16 16:35:31 +00:00
|
|
|
return lb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-12-09 16:46:41 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequence_metastrip(ListBase *seqbase, Sequence *meta, Sequence *seq)
|
2011-05-16 17:14:47 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *iseq;
|
2011-05-16 17:14:47 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *rval;
|
2011-05-16 17:14:47 +00:00
|
|
|
|
|
|
|
if (seq == iseq) {
|
|
|
|
return meta;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else if (iseq->seqbase.first &&
|
2012-08-08 11:15:40 +00:00
|
|
|
(rval = BKE_sequence_metastrip(&iseq->seqbase, iseq, seq)))
|
2012-05-20 19:49:27 +00:00
|
|
|
{
|
2011-05-16 17:14:47 +00:00
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
int BKE_sequence_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)];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_a->len != seq_b->len) {
|
2012-10-26 17:32:50 +00:00
|
|
|
*error_str = N_("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
|
|
|
|
2012-10-26 17:32:50 +00:00
|
|
|
/* type checking, could be more advanced but disallow sound vs non-sound copy */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_a->type != seq_b->type) {
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq_a->type == SEQ_TYPE_SOUND_RAM || seq_b->type == SEQ_TYPE_SOUND_RAM) {
|
2012-10-26 17:32:50 +00:00
|
|
|
*error_str = N_("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 */
|
2012-06-07 15:49:02 +00:00
|
|
|
if ((seq_a->type & SEQ_TYPE_EFFECT) != (seq_b->type & SEQ_TYPE_EFFECT)) {
|
2012-10-26 17:32:50 +00:00
|
|
|
*error_str = N_("Strips were not compatible");
|
2010-07-07 13:14:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) {
|
2012-08-08 11:15:40 +00:00
|
|
|
if (BKE_sequence_effect_get_num_inputs(seq_a->type) != BKE_sequence_effect_get_num_inputs(seq_b->type)) {
|
2012-10-26 17:32:50 +00:00
|
|
|
*error_str = N_("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
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* swap back names so animation fcurves don't get swapped */
|
2012-03-29 22:26:11 +00:00
|
|
|
BLI_strncpy(name, seq_a->name + 2, sizeof(name));
|
|
|
|
BLI_strncpy(seq_a->name + 2, seq_b->name + 2, sizeof(seq_b->name) - 2);
|
|
|
|
BLI_strncpy(seq_b->name + 2, name, sizeof(seq_b->name) - 2);
|
2010-07-07 13:14:51 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
2012-08-25 19:43:15 +00:00
|
|
|
SWAP(Sequence *, seq_a->prev, seq_b->prev);
|
|
|
|
SWAP(Sequence *, seq_a->next, seq_b->next);
|
2010-06-21 17:37:50 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-05-29 20:26:19 +10:00
|
|
|
/* prefix + [" + escaped_name + "] + \0 */
|
|
|
|
#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1)
|
|
|
|
|
|
|
|
static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name)
|
|
|
|
{
|
|
|
|
char name_esc[SEQ_NAME_MAXSTR * 2];
|
|
|
|
|
|
|
|
BLI_strescape(name_esc, name, sizeof(name_esc));
|
2015-04-22 05:37:22 +10:00
|
|
|
return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
|
2014-05-29 20:26:19 +10:00
|
|
|
}
|
|
|
|
|
2009-12-09 16:46:41 +00:00
|
|
|
/* XXX - hackish function needed for transforming strips! TODO - have some better solution */
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs)
|
2009-12-09 16:46:41 +00:00
|
|
|
{
|
2014-05-29 20:26:19 +10:00
|
|
|
char str[SEQ_RNAPATH_MAXSTR];
|
|
|
|
size_t str_len;
|
2009-12-09 18:08:14 +00:00
|
|
|
FCurve *fcu;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL)
|
2009-12-09 16:46:41 +00:00
|
|
|
return;
|
|
|
|
|
2014-05-29 20:26:19 +10:00
|
|
|
str_len = sequencer_rna_path_prefix(str, seq->name + 2);
|
2009-12-09 16:46:41 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) {
|
2014-05-29 20:26:19 +10:00
|
|
|
if (STREQLEN(fcu->rna_path, str, str_len)) {
|
2010-10-21 08:32:53 +00:00
|
|
|
unsigned int i;
|
2014-03-26 20:01:09 +01:00
|
|
|
if (fcu->bezt) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fcu->fpt) {
|
|
|
|
for (i = 0; i < fcu->totvert; i++) {
|
|
|
|
FPoint *fpt = &fcu->fpt[i];
|
|
|
|
fpt->vec[0] += ofs;
|
|
|
|
}
|
2009-12-09 16:46:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst)
|
2010-07-07 16:17:18 +00:00
|
|
|
{
|
2014-05-29 20:26:19 +10:00
|
|
|
char str_from[SEQ_RNAPATH_MAXSTR];
|
|
|
|
size_t str_from_len;
|
2010-07-07 16:17:18 +00:00
|
|
|
FCurve *fcu;
|
|
|
|
FCurve *fcu_last;
|
|
|
|
FCurve *fcu_cpy;
|
2012-03-29 22:26:11 +00:00
|
|
|
ListBase lb = {NULL, NULL};
|
2010-07-07 16:17:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (scene->adt == NULL || scene->adt->action == NULL)
|
2010-07-07 16:17:18 +00:00
|
|
|
return;
|
|
|
|
|
2014-05-29 20:26:19 +10:00
|
|
|
str_from_len = sequencer_rna_path_prefix(str_from, name_src);
|
2010-07-07 16:17:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
fcu_last = scene->adt->action->curves.last;
|
2010-07-07 16:17:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) {
|
2014-05-29 20:26:19 +10:00
|
|
|
if (STREQLEN(fcu->rna_path, str_from, str_from_len)) {
|
2012-03-29 22:26:11 +00:00
|
|
|
fcu_cpy = copy_fcurve(fcu);
|
2010-07-07 16:17:18 +00:00
|
|
|
BLI_addtail(&lb, fcu_cpy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* notice validate is 0, keep this because the seq may not be added to the scene yet */
|
2012-03-30 13:04:29 +00:00
|
|
|
BKE_animdata_fix_paths_rename(&scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name_src, name_dst, 0, 0, 0);
|
2010-07-07 16:17:18 +00:00
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2014-05-29 20:26:19 +10:00
|
|
|
char str[SEQ_RNAPATH_MAXSTR];
|
|
|
|
size_t str_len;
|
2010-07-03 21:13:08 +00:00
|
|
|
FCurve *fcu;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
if (scene->adt == NULL || scene->adt->action == NULL)
|
2010-07-03 21:13:08 +00:00
|
|
|
return;
|
|
|
|
|
2014-05-29 20:26:19 +10:00
|
|
|
str_len = sequencer_rna_path_prefix(str, seq->name + 2);
|
2010-07-03 21:13:08 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
fcu = scene->adt->action->curves.first;
|
2010-07-03 21:13:08 +00:00
|
|
|
|
|
|
|
while (fcu) {
|
2014-05-29 20:26:19 +10:00
|
|
|
if (STREQLEN(fcu->rna_path, str, str_len)) {
|
2010-07-03 21:13:08 +00:00
|
|
|
FCurve *next_fcu = fcu->next;
|
|
|
|
|
|
|
|
BLI_remlink(&scene->adt->action->curves, fcu);
|
|
|
|
free_fcurve(fcu);
|
|
|
|
|
|
|
|
fcu = next_fcu;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-07-03 21:13:08 +00:00
|
|
|
fcu = fcu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 20:26:19 +10:00
|
|
|
#undef SEQ_RNAPATH_MAXSTR
|
|
|
|
|
2014-03-31 23:39:08 +11:00
|
|
|
Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, bool recursive)
|
2009-12-17 04:55:15 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *iseq = NULL;
|
|
|
|
Sequence *rseq = NULL;
|
2009-12-17 11:16:28 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
|
2013-03-10 06:18:03 +00:00
|
|
|
if (STREQ(name, iseq->name + 2))
|
2009-12-17 11:16:28 +00:00
|
|
|
return iseq;
|
2012-08-18 05:49:55 +00:00
|
|
|
else if (recursive && (iseq->seqbase.first) && (rseq = BKE_sequence_get_by_name(&iseq->seqbase, name, 1))) {
|
2009-12-17 11:16:28 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-08-29 04:08:44 +00:00
|
|
|
/**
|
|
|
|
* Only use as last resort when the StripElem is available but no the Sequence.
|
|
|
|
* (needed for RNA)
|
|
|
|
*/
|
|
|
|
Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se)
|
|
|
|
{
|
|
|
|
Sequence *iseq;
|
|
|
|
|
|
|
|
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
|
|
|
|
Sequence *seq_found;
|
|
|
|
if ((iseq->strip && iseq->strip->stripdata) &&
|
|
|
|
(ARRAY_HAS_ITEM(se, iseq->strip->stripdata, iseq->len)))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if ((seq_found = BKE_sequencer_from_elem(&iseq->seqbase, se))) {
|
|
|
|
iseq = seq_found;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return iseq;
|
|
|
|
}
|
2009-12-17 04:55:15 +00:00
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
Sequence *BKE_sequencer_active_get(Scene *scene)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2012-08-08 11:15:36 +00:00
|
|
|
|
|
|
|
if (ed == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
return ed->act_seq;
|
|
|
|
}
|
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
void BKE_sequencer_active_set(Scene *scene, Sequence *seq)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2012-08-08 11:15:36 +00:00
|
|
|
|
|
|
|
if (ed == NULL)
|
|
|
|
return;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
ed->act_seq = seq;
|
2009-11-14 19:26:58 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
int BKE_sequencer_active_get_pair(Scene *scene, Sequence **seq_act, Sequence **seq_other)
|
2010-06-21 17:37:50 +00:00
|
|
|
{
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2012-05-11 10:04:55 +00:00
|
|
|
*seq_act = BKE_sequencer_active_get(scene);
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (*seq_act == NULL) {
|
2010-06-21 17:37:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
*seq_other = NULL;
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->flag & SELECT && (seq != (*seq_act))) {
|
|
|
|
if (*seq_other) {
|
2010-06-21 17:37:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
2012-03-29 22:26:11 +00:00
|
|
|
*seq_other = seq;
|
2010-06-21 17:37:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*seq_other != NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-24 09:53:29 +00:00
|
|
|
Mask *BKE_sequencer_mask_get(Scene *scene)
|
|
|
|
{
|
|
|
|
Sequence *seq_act = BKE_sequencer_active_get(scene);
|
|
|
|
|
|
|
|
if (seq_act && seq_act->type == SEQ_TYPE_MASK) {
|
|
|
|
return seq_act->mask;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
/* api like funcs for adding */
|
|
|
|
|
2012-08-08 11:15:32 +00:00
|
|
|
static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq) {
|
2013-07-15 11:26:43 +00:00
|
|
|
BLI_strncpy_utf8(seq->name + 2, seq_load->name, sizeof(seq->name) - 2);
|
2014-01-08 14:46:06 +11:00
|
|
|
BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2));
|
2012-10-04 18:30:28 +00:00
|
|
|
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) {
|
2009-11-14 19:26:58 +00:00
|
|
|
seq_load->start_frame += (seq->enddisp - seq->startdisp);
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_load->flag & SEQ_LOAD_REPLACE_SEL) {
|
2009-12-17 23:29:11 +00:00
|
|
|
seq_load->flag |= SELECT;
|
2012-05-11 10:04:55 +00:00
|
|
|
BKE_sequencer_active_set(scene, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
|
|
|
|
if (seq->sound)
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_cache(seq->sound);
|
2009-11-14 19:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
seq_load->tot_success++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
seq_load->tot_error++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
|
|
|
Sequence *seq;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq = MEM_callocN(sizeof(Sequence), "addseq");
|
2009-11-14 19:26:58 +00:00
|
|
|
BLI_addtail(lb, seq);
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
*( (short *)seq->name) = ID_SEQ;
|
|
|
|
seq->name[2] = 0;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->flag = SELECT;
|
|
|
|
seq->start = cfra;
|
|
|
|
seq->machine = machine;
|
|
|
|
seq->sat = 1.0;
|
|
|
|
seq->mul = 1.0;
|
2009-11-14 19:26:58 +00:00
|
|
|
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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format");
|
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
return seq;
|
|
|
|
}
|
|
|
|
|
2013-02-19 08:37:08 +00:00
|
|
|
void BKE_sequence_alpha_mode_from_extension(Sequence *seq)
|
|
|
|
{
|
|
|
|
if (seq->strip && seq->strip->stripdata) {
|
2014-01-31 03:09:01 +11:00
|
|
|
const char *filename = seq->strip->stripdata->name;
|
|
|
|
seq->alpha_mode = BKE_image_alpha_mode_from_extension_ex(filename);
|
2013-02-19 08:37:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-05 14:44:29 +00:00
|
|
|
void BKE_sequence_init_colorspace(Sequence *seq)
|
|
|
|
{
|
|
|
|
if (seq->strip && seq->strip->stripdata) {
|
|
|
|
char name[FILE_MAX];
|
|
|
|
ImBuf *ibuf;
|
|
|
|
|
|
|
|
BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name);
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
|
|
|
|
/* initialize input color space */
|
|
|
|
if (seq->type == SEQ_TYPE_IMAGE) {
|
2013-01-04 13:19:57 +00:00
|
|
|
ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
|
2012-11-05 14:44:29 +00:00
|
|
|
|
2012-12-31 13:52:13 +00:00
|
|
|
/* byte images are default to straight alpha, however sequencer
|
|
|
|
* works in premul space, so mark strip to be premultiplied first
|
|
|
|
*/
|
2013-01-04 13:19:57 +00:00
|
|
|
seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
|
2013-01-04 11:02:35 +00:00
|
|
|
if (ibuf) {
|
2013-01-04 13:19:57 +00:00
|
|
|
if (ibuf->flags & IB_alphamode_premul)
|
|
|
|
seq->alpha_mode = IMA_ALPHA_PREMUL;
|
|
|
|
|
2012-11-05 14:44:29 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2013-01-04 11:02:35 +00:00
|
|
|
}
|
2012-11-05 14:44:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-28 19:18:35 +00:00
|
|
|
/* NOTE: this function doesn't fill in image names */
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C); /* only for active seq */
|
2009-11-14 19:26:58 +00:00
|
|
|
Sequence *seq;
|
|
|
|
Strip *strip;
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel);
|
2012-06-07 15:49:02 +00:00
|
|
|
seq->type = SEQ_TYPE_IMAGE;
|
|
|
|
seq->blend_mode = SEQ_TYPE_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 */
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-03-21 18:02:29 +00:00
|
|
|
seq->len = seq_load->len ? seq_load->len : 1;
|
2012-03-29 22:26:11 +00:00
|
|
|
strip->us = 1;
|
|
|
|
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));
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (seq_load->stereo3d_format)
|
|
|
|
*seq->stereo3d_format = *seq_load->stereo3d_format;
|
|
|
|
|
|
|
|
seq->views_format = seq_load->views_format;
|
|
|
|
seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
|
|
|
|
|
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
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
Scene *scene = CTX_data_scene(C); /* only for sound */
|
2014-03-20 15:45:20 +06:00
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
2009-11-14 19:26:58 +00:00
|
|
|
bSound *sound;
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq; /* generic strip vars */
|
2009-11-14 19:26:58 +00:00
|
|
|
Strip *strip;
|
|
|
|
StripElem *se;
|
|
|
|
|
|
|
|
AUD_SoundInfo info;
|
|
|
|
|
2015-03-26 11:35:41 +01:00
|
|
|
sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2015-05-03 03:28:43 +10:00
|
|
|
if (sound->playback_handle == NULL) {
|
2012-10-04 13:26:15 +00:00
|
|
|
#if 0
|
2013-03-15 10:48:48 +00:00
|
|
|
if (op)
|
2012-08-08 11:15:36 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
|
2012-10-04 13:26:15 +00:00
|
|
|
#endif
|
2012-08-08 11:15:36 +00:00
|
|
|
|
2009-11-14 19:26:58 +00:00
|
|
|
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) {
|
2015-03-26 11:35:41 +01:00
|
|
|
BKE_sound_delete(bmain, sound);
|
2012-10-04 13:26:15 +00:00
|
|
|
#if 0
|
2012-08-08 11:15:36 +00:00
|
|
|
if (op)
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
|
2012-10-04 13:26:15 +00:00
|
|
|
#endif
|
2009-11-14 19:26:58 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
seq->type = SEQ_TYPE_SOUND_RAM;
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->sound = sound;
|
|
|
|
BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2);
|
2012-10-04 18:30:28 +00:00
|
|
|
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
/* basic defaults */
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
|
2012-11-04 07:18:29 +00:00
|
|
|
seq->len = (int)ceil((double)info.length * FPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
strip->us = 1;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2011-05-16 17:54:55 +00:00
|
|
|
/* we only need 1 element to store the filename */
|
2012-03-29 22:26:11 +00:00
|
|
|
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2011-10-15 03:56:05 +00:00
|
|
|
BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2015-03-26 11:35:41 +01:00
|
|
|
seq->scene_sound = BKE_sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_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
|
2012-08-10 12:56:09 +00:00
|
|
|
Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
2011-06-23 09:27:56 +00:00
|
|
|
{
|
2012-08-08 11:15:36 +00:00
|
|
|
(void) C;
|
|
|
|
(void) seqbasep;
|
|
|
|
(void) seq_load;
|
2011-06-23 09:27:56 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif // WITH_AUDASPACE
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static void seq_anim_add_suffix(Scene *scene, struct anim *anim, const size_t view_id)
|
|
|
|
{
|
|
|
|
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, view_id);
|
|
|
|
IMB_suffix_anim(anim, suffix);
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
|
2009-11-14 19:26:58 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
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
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seq; /* generic strip vars */
|
2009-11-14 19:26:58 +00:00
|
|
|
Strip *strip;
|
|
|
|
StripElem *se;
|
2012-11-05 14:44:29 +00:00
|
|
|
char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */
|
2015-04-06 10:40:12 -03:00
|
|
|
bool is_multiview_loaded = false;
|
|
|
|
const bool is_multiview = (seq_load->flag & SEQ_USE_VIEWS) != 0;
|
|
|
|
size_t totfiles = seq_num_files(scene, seq_load->views_format, is_multiview);
|
|
|
|
struct anim **anim_arr;
|
|
|
|
int i;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
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
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
anim_arr = MEM_callocN(sizeof(struct anim *) * totfiles, "Video files");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (is_multiview && (seq_load->views_format == R_IMF_VIEWS_INDIVIDUAL)) {
|
|
|
|
char prefix[FILE_MAX];
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *ext = NULL;
|
2015-04-06 10:40:12 -03:00
|
|
|
size_t j = 0;
|
|
|
|
|
|
|
|
BKE_scene_multiview_view_prefix_get(scene, path, prefix, &ext);
|
|
|
|
|
|
|
|
if (prefix[0] != '\0') {
|
|
|
|
for (i = 0; i < totfiles; i++) {
|
|
|
|
char str[FILE_MAX];
|
|
|
|
|
|
|
|
seq_multiview_name(scene, i, prefix, ext, str, FILE_MAX);
|
|
|
|
anim_arr[j] = openanim(str, IB_rect, 0, colorspace);
|
|
|
|
|
|
|
|
if (anim_arr[j]) {
|
2015-04-09 17:23:51 +10:00
|
|
|
seq_anim_add_suffix(scene, anim_arr[j], i);
|
2015-04-06 10:40:12 -03:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == 0) {
|
|
|
|
MEM_freeN(anim_arr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
is_multiview_loaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_multiview_loaded == false) {
|
|
|
|
anim_arr[0] = openanim(path, IB_rect, 0, colorspace);
|
|
|
|
|
|
|
|
if (anim_arr[0] == NULL) {
|
|
|
|
MEM_freeN(anim_arr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel);
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
/* multiview settings */
|
|
|
|
if (seq_load->stereo3d_format) {
|
|
|
|
*seq->stereo3d_format = *seq_load->stereo3d_format;
|
|
|
|
seq->views_format = seq_load->views_format;
|
|
|
|
}
|
|
|
|
seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
|
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
seq->type = SEQ_TYPE_MOVIE;
|
|
|
|
seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
|
2010-07-04 08:49:54 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
for (i = 0; i < totfiles; i++) {
|
|
|
|
if (anim_arr[i]) {
|
|
|
|
StripAnim *sanim = MEM_mallocN(sizeof(StripAnim), "Strip Anim");
|
|
|
|
BLI_addtail(&seq->anims, sanim);
|
|
|
|
sanim->anim = anim_arr[i];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
|
2012-03-29 22:26:11 +00:00
|
|
|
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
|
2012-10-04 18:30:28 +00:00
|
|
|
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
|
|
|
/* basic defaults */
|
2012-03-29 22:26:11 +00:00
|
|
|
seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
|
2015-04-06 10:40:12 -03:00
|
|
|
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
|
2012-03-29 22:26:11 +00:00
|
|
|
strip->us = 1;
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-11-05 14:44:29 +00:00
|
|
|
BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name));
|
|
|
|
|
2011-05-16 17:54:55 +00:00
|
|
|
/* we only need 1 element for MOVIE strips */
|
2012-03-29 22:26:11 +00:00
|
|
|
strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem");
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2011-10-15 03:56:05 +00:00
|
|
|
BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name));
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequence_calc_disp(scene, seq);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2013-06-20 13:52:58 +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
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
|
2012-03-29 22:26:11 +00:00
|
|
|
int start_frame_back = seq_load->start_frame;
|
2009-11-14 19:26:58 +00:00
|
|
|
seq_load->channel++;
|
|
|
|
|
2014-05-27 15:18:31 +10:00
|
|
|
seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load);
|
2009-11-14 19:26:58 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
seq_load->start_frame = start_frame_back;
|
2009-11-14 19:26:58 +00:00
|
|
|
seq_load->channel--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* can be NULL */
|
|
|
|
seq_load_apply(scene, seq, seq_load);
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
MEM_freeN(anim_arr);
|
2009-11-14 19:26:58 +00:00
|
|
|
return seq;
|
|
|
|
}
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2012-08-08 11:15:38 +00:00
|
|
|
static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag)
|
2010-06-24 10:04:18 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +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;
|
2012-03-29 22:26:11 +00:00
|
|
|
seqn->strip = MEM_dupallocN(seq->strip);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
seqn->stereo3d_format = MEM_dupallocN(seq->stereo3d_format);
|
|
|
|
|
2012-08-08 11:15:36 +00:00
|
|
|
/* XXX: add F-Curve duplication stuff? */
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-04-02 21:05:12 +11:00
|
|
|
if (seq->prop) {
|
|
|
|
seqn->prop = IDP_CopyProperty(seq->prop);
|
|
|
|
}
|
|
|
|
|
2012-08-19 15:41:56 +00:00
|
|
|
if (seqn->modifiers.first) {
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&seqn->modifiers);
|
2012-08-19 15:41:56 +00:00
|
|
|
|
|
|
|
BKE_sequence_modifier_list_copy(seqn, seq);
|
|
|
|
}
|
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
BLI_listbase_clear(&seqn->seqbase);
|
2010-06-24 10:04:18 +00:00
|
|
|
/* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
|
2012-12-29 01:54:58 +00:00
|
|
|
/* - seq_dupli_recursive(&seq->seqbase, &seqn->seqbase);*/
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_SCENE) {
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene_sound)
|
2015-03-26 11:35:41 +01:00
|
|
|
seqn->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce_audio, seqn);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2013-07-24 07:11:00 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_MOVIECLIP) {
|
|
|
|
/* avoid assert */
|
|
|
|
}
|
|
|
|
else if (seq->type == SEQ_TYPE_MASK) {
|
|
|
|
/* avoid assert */
|
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_MOVIE) {
|
2010-06-24 10:04:18 +00:00
|
|
|
seqn->strip->stripdata =
|
2012-03-29 22:26:11 +00:00
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_listbase_clear(&seqn->anims);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_SOUND_RAM) {
|
2010-06-24 10:04:18 +00:00
|
|
|
seqn->strip->stripdata =
|
2012-03-29 22:26:11 +00:00
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (seq->scene_sound)
|
2015-03-26 11:35:41 +01:00
|
|
|
seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2013-07-24 07:11:00 +00:00
|
|
|
id_us_plus((ID *)seqn->sound);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type == SEQ_TYPE_IMAGE) {
|
2010-06-24 10:04:18 +00:00
|
|
|
seqn->strip->stripdata =
|
2012-03-29 22:26:11 +00:00
|
|
|
MEM_dupallocN(seq->strip->stripdata);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-06-07 15:49:02 +00:00
|
|
|
else if (seq->type >= SEQ_TYPE_EFFECT) {
|
|
|
|
if (seq->type & SEQ_TYPE_EFFECT) {
|
2010-06-24 10:04:18 +00:00
|
|
|
struct SeqEffectHandle sh;
|
2012-08-08 11:15:40 +00:00
|
|
|
sh = BKE_sequence_get_effect(seq);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (sh.copy)
|
2010-06-24 10:04:18 +00:00
|
|
|
sh.copy(seq, seqn);
|
|
|
|
}
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
seqn->strip->stripdata = NULL;
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-07-24 07:11:00 +00:00
|
|
|
/* sequence type not handled in duplicate! Expect a crash now... */
|
|
|
|
BLI_assert(0);
|
2010-06-24 10:04:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dupe_flag & SEQ_DUPE_UNIQUE_NAME)
|
2012-10-04 18:30:28 +00:00
|
|
|
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqn);
|
2010-07-07 16:17:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dupe_flag & SEQ_DUPE_ANIM)
|
2012-08-08 11:15:40 +00:00
|
|
|
BKE_sequencer_dupe_animdata(scene, seq->name + 2, seqn->name + 2);
|
2010-06-24 10:04:18 +00:00
|
|
|
|
|
|
|
return seqn;
|
|
|
|
}
|
|
|
|
|
2015-04-20 11:51:43 +02:00
|
|
|
static void seq_new_fix_links_recursive(Sequence *seq)
|
|
|
|
{
|
|
|
|
SequenceModifierData *smd;
|
|
|
|
|
|
|
|
if (seq->type >= SEQ_TYPE_EFFECT) {
|
|
|
|
if (seq->seq1 && seq->seq1->tmp) seq->seq1 = seq->seq1->tmp;
|
|
|
|
if (seq->seq2 && seq->seq2->tmp) seq->seq2 = seq->seq2->tmp;
|
|
|
|
if (seq->seq3 && seq->seq3->tmp) seq->seq3 = seq->seq3->tmp;
|
|
|
|
}
|
|
|
|
else if (seq->type == SEQ_TYPE_META) {
|
|
|
|
Sequence *seqn;
|
|
|
|
for (seqn = seq->seqbase.first; seqn; seqn = seqn->next) {
|
|
|
|
seq_new_fix_links_recursive(seqn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (smd = seq->modifiers.first; smd; smd = smd->next) {
|
|
|
|
if (smd->mask_sequence && smd->mask_sequence->tmp)
|
|
|
|
smd->mask_sequence = smd->mask_sequence->tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag)
|
2010-06-24 10:04:18 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Sequence *seqn = seq_dupli(scene, scene_to, seq, dupe_flag);
|
2012-06-07 15:49:02 +00:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
2010-06-25 12:04:04 +00:00
|
|
|
Sequence *s;
|
2012-03-29 22:26:11 +00:00
|
|
|
for (s = seq->seqbase.first; s; s = s->next) {
|
2012-08-08 11:15:40 +00:00
|
|
|
Sequence *n = BKE_sequence_dupli_recursive(scene, scene_to, s, dupe_flag);
|
2010-06-24 10:04:18 +00:00
|
|
|
if (n) {
|
|
|
|
BLI_addtail(&seqn->seqbase, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-20 11:51:43 +02:00
|
|
|
|
|
|
|
seq_new_fix_links_recursive(seqn);
|
|
|
|
|
2010-06-24 10:04:18 +00:00
|
|
|
return seqn;
|
|
|
|
}
|
|
|
|
|
2014-10-21 11:10:45 +02:00
|
|
|
void BKE_sequence_base_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;
|
2012-05-11 10:04:55 +00:00
|
|
|
Sequence *last_seq = BKE_sequencer_active_get(scene);
|
2014-10-21 11:10:45 +02:00
|
|
|
/* always include meta's strips */
|
|
|
|
int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL;
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
for (seq = seqbase->first; seq; seq = seq->next) {
|
|
|
|
seq->tmp = NULL;
|
2012-03-24 06:18:31 +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 */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dupe_flag & SEQ_DUPE_CONTEXT) {
|
2010-06-24 10:04:18 +00:00
|
|
|
seq->flag &= ~SEQ_ALLSEL;
|
2012-03-29 22:26:11 +00:00
|
|
|
seqn->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
|
2010-06-24 10:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BLI_addtail(nseqbase, seqn);
|
2014-10-21 11:10:45 +02:00
|
|
|
if (seq->type == SEQ_TYPE_META) {
|
|
|
|
BKE_sequence_base_dupli_recursive(
|
|
|
|
scene, scene_to, &seqn->seqbase, &seq->seqbase,
|
|
|
|
dupe_flag_recursive);
|
|
|
|
}
|
2010-06-24 10:04:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dupe_flag & SEQ_DUPE_CONTEXT) {
|
2010-06-24 10:04:18 +00:00
|
|
|
if (seq == last_seq) {
|
2012-05-11 10:04:55 +00:00
|
|
|
BKE_sequencer_active_set(scene, seqn);
|
2010-06-24 10:04:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-20 11:51:43 +02:00
|
|
|
|
|
|
|
/* fix modifier linking */
|
|
|
|
for (seq = nseqbase->first; seq; seq = seq->next) {
|
|
|
|
seq_new_fix_links_recursive(seq);
|
|
|
|
}
|
2010-06-24 10:04:18 +00:00
|
|
|
}
|
2012-08-13 17:36:29 +00:00
|
|
|
|
|
|
|
/* called on draw, needs to be fast,
|
|
|
|
* we could cache and use a flag if we want to make checks for file paths resolving for eg. */
|
2013-03-09 05:35:49 +00:00
|
|
|
bool BKE_sequence_is_valid_check(Sequence *seq)
|
2012-08-13 17:36:29 +00:00
|
|
|
{
|
|
|
|
switch (seq->type) {
|
|
|
|
case SEQ_TYPE_MASK:
|
|
|
|
return (seq->mask != NULL);
|
|
|
|
case SEQ_TYPE_MOVIECLIP:
|
|
|
|
return (seq->clip != NULL);
|
|
|
|
case SEQ_TYPE_SCENE:
|
|
|
|
return (seq->scene != NULL);
|
|
|
|
case SEQ_TYPE_SOUND_RAM:
|
|
|
|
return (seq->sound != NULL);
|
|
|
|
}
|
|
|
|
|
2013-03-09 05:35:49 +00:00
|
|
|
return true;
|
2012-08-13 17:36:29 +00:00
|
|
|
}
|
2012-08-19 15:41:56 +00:00
|
|
|
|
2014-11-24 18:18:35 +01:00
|
|
|
int BKE_sequencer_find_next_prev_edit(
|
|
|
|
Scene *scene, int cfra, const short side,
|
|
|
|
const bool do_skip_mute, const bool do_center, const bool do_unselected)
|
|
|
|
{
|
|
|
|
Editing *ed = BKE_sequencer_editing_get(scene, false);
|
|
|
|
Sequence *seq;
|
|
|
|
|
|
|
|
int dist, best_dist, best_frame = cfra;
|
|
|
|
int seq_frames[2], seq_frames_tot;
|
|
|
|
|
|
|
|
/* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */
|
|
|
|
|
|
|
|
best_dist = MAXFRAME * 2;
|
|
|
|
|
|
|
|
if (ed == NULL) return cfra;
|
|
|
|
|
|
|
|
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (do_unselected && (seq->flag & SELECT))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (do_center) {
|
|
|
|
seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
|
|
|
|
seq_frames_tot = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
seq_frames[0] = seq->startdisp;
|
|
|
|
seq_frames[1] = seq->enddisp;
|
|
|
|
|
|
|
|
seq_frames_tot = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < seq_frames_tot; i++) {
|
|
|
|
const int seq_frame = seq_frames[i];
|
|
|
|
|
|
|
|
dist = MAXFRAME * 2;
|
|
|
|
|
|
|
|
switch (side) {
|
|
|
|
case SEQ_SIDE_LEFT:
|
|
|
|
if (seq_frame < cfra) {
|
|
|
|
dist = cfra - seq_frame;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SEQ_SIDE_RIGHT:
|
|
|
|
if (seq_frame > cfra) {
|
|
|
|
dist = seq_frame - cfra;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SEQ_SIDE_BOTH:
|
|
|
|
dist = abs(seq_frame - cfra);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dist < best_dist) {
|
|
|
|
best_frame = seq_frame;
|
|
|
|
best_dist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return best_frame;
|
|
|
|
}
|