2011-11-07 12:55:18 +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,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2011 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation,
|
|
|
|
* Sergey Sharybin
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file blender/blenkernel/intern/movieclip.c
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#ifndef WIN32
|
2013-12-12 13:10:03 +06:00
|
|
|
# include <unistd.h>
|
2011-11-07 12:55:18 +00:00
|
|
|
#else
|
2013-12-12 13:10:03 +06:00
|
|
|
# include <io.h>
|
2011-11-07 12:55:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_constraint_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_movieclip_types.h"
|
2012-10-01 07:54:37 +00:00
|
|
|
#include "DNA_node_types.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_ghash.h"
|
|
|
|
#include "BLI_math.h"
|
|
|
|
#include "BLI_threads.h"
|
|
|
|
|
2012-02-15 16:06:48 +00:00
|
|
|
#include "BKE_animsys.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 "BKE_colortools.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_library.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_main.h"
|
|
|
|
#include "BKE_movieclip.h"
|
2012-10-01 07:54:37 +00:00
|
|
|
#include "BKE_node.h"
|
2012-05-06 15:15:33 +00:00
|
|
|
#include "BKE_image.h" /* openanim */
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_tracking.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"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "IMB_moviecache.h"
|
|
|
|
|
2013-02-28 14:25:00 +00:00
|
|
|
#ifdef WITH_OPENEXR
|
2013-12-12 13:10:03 +06:00
|
|
|
# include "intern/openexr/openexr_multi.h"
|
2013-02-28 14:25:00 +00:00
|
|
|
#endif
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
#include "NOD_composite.h"
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/*********************** movieclip buffer loaders *************************/
|
|
|
|
|
2012-04-07 16:37:55 +00:00
|
|
|
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
char num[FILE_MAX] = {0};
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
BLI_strncpy(num, full_name + head_len, numlen + 1);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
return atoi(num);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rendersize_to_proxy(MovieClipUser *user, int flag)
|
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
if ((flag & MCLIP_USE_PROXY) == 0)
|
2011-11-07 12:55:18 +00:00
|
|
|
return IMB_PROXY_NONE;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
switch (user->render_size) {
|
2011-11-07 12:55:18 +00:00
|
|
|
case MCLIP_PROXY_RENDER_SIZE_25:
|
|
|
|
return IMB_PROXY_25;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_50:
|
|
|
|
return IMB_PROXY_50;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_75:
|
|
|
|
return IMB_PROXY_75;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_100:
|
|
|
|
return IMB_PROXY_100;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_FULL:
|
|
|
|
return IMB_PROXY_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IMB_PROXY_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rendersize_to_number(int render_size)
|
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
switch (render_size) {
|
2011-11-07 12:55:18 +00:00
|
|
|
case MCLIP_PROXY_RENDER_SIZE_25:
|
|
|
|
return 25;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_50:
|
|
|
|
return 50;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_75:
|
|
|
|
return 75;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_100:
|
|
|
|
return 100;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_FULL:
|
|
|
|
return 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_timecode(MovieClip *clip, int flag)
|
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
if ((flag & MCLIP_USE_PROXY) == 0)
|
2011-11-07 12:55:18 +00:00
|
|
|
return IMB_TC_NONE;
|
|
|
|
|
|
|
|
return clip->proxy.tc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
|
|
|
|
{
|
|
|
|
unsigned short numlen;
|
|
|
|
char head[FILE_MAX], tail[FILE_MAX];
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
BLI_strncpy(name, clip->name, sizeof(clip->name));
|
|
|
|
BLI_stringdec(name, head, tail, &numlen);
|
|
|
|
|
2012-06-06 18:58:30 +00:00
|
|
|
/* movieclips always points to first image from sequence,
|
|
|
|
* autoguess offset for now. could be something smarter in the future
|
|
|
|
*/
|
|
|
|
offset = sequence_guess_offset(clip->name, strlen(head), numlen);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (numlen)
|
2012-06-12 21:25:23 +00:00
|
|
|
BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
|
2012-03-25 23:19:21 +00:00
|
|
|
else
|
|
|
|
BLI_strncpy(name, clip->name, sizeof(clip->name));
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2011-11-07 15:19:26 +00:00
|
|
|
BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* supposed to work with sequences only */
|
2014-02-03 18:55:59 +11:00
|
|
|
static void get_proxy_fname(MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *name)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
int size = rendersize_to_number(proxy_render_size);
|
2011-11-07 12:55:18 +00:00
|
|
|
char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
|
2012-06-12 21:25:23 +00:00
|
|
|
int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
|
2011-11-07 15:19:26 +00:00
|
|
|
BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (undistorted)
|
2012-06-06 18:58:30 +00:00
|
|
|
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
|
2011-11-07 12:55:18 +00:00
|
|
|
else
|
2012-06-06 18:58:30 +00:00
|
|
|
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
BLI_path_frame(name, 1, 0);
|
|
|
|
|
|
|
|
strcat(name, ".jpg");
|
|
|
|
}
|
|
|
|
|
|
|
|
static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
|
|
|
|
{
|
|
|
|
struct ImBuf *ibuf;
|
|
|
|
char name[FILE_MAX];
|
2014-03-31 17:59:50 +06:00
|
|
|
int loadflag;
|
|
|
|
bool use_proxy = false;
|
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
|
|
|
char *colorspace;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (use_proxy) {
|
2012-03-25 23:19:21 +00:00
|
|
|
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
|
2011-11-07 12:55:18 +00:00
|
|
|
get_proxy_fname(clip, user->render_size, undistort, framenr, 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-06 17:27:16 +06:00
|
|
|
/* Well, this is a bit weird, but proxies for movie sources
|
|
|
|
* are built in the same exact color space as the input,
|
|
|
|
*
|
|
|
|
* But image sequences are built in the display space.
|
|
|
|
*/
|
|
|
|
if (clip->source == MCLIP_SRC_MOVIE) {
|
|
|
|
colorspace = clip->colorspace_settings.name;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
colorspace = NULL;
|
|
|
|
}
|
2012-03-24 06:18:31 +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
|
|
|
else {
|
2011-11-07 12:55:18 +00:00
|
|
|
get_sequence_fname(clip, framenr, 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
|
|
|
colorspace = clip->colorspace_settings.name;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-02-18 19:34:14 +00:00
|
|
|
loadflag = IB_rect | IB_multilayer | IB_alphamode_detect;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* read 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
|
|
|
ibuf = IMB_loadiffname(name, loadflag, colorspace);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-02-28 14:25:00 +00:00
|
|
|
#ifdef WITH_OPENEXR
|
2013-02-28 17:23:44 +00:00
|
|
|
if (ibuf) {
|
|
|
|
if (ibuf->ftype == OPENEXR && ibuf->userdata) {
|
|
|
|
IMB_exr_close(ibuf->userdata);
|
|
|
|
ibuf->userdata = NULL;
|
|
|
|
}
|
2013-02-28 14:25:00 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2012-03-26 15:57:00 +00:00
|
|
|
static void movieclip_open_anim_file(MovieClip *clip)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
char str[FILE_MAX];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!clip->anim) {
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_strncpy(str, clip->name, FILE_MAX);
|
2011-11-07 15:19:26 +00:00
|
|
|
BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* FIXME: make several stream accessible in image editor, too */
|
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
|
|
|
clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->anim) {
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
|
2011-11-07 12:55:18 +00:00
|
|
|
char dir[FILE_MAX];
|
2011-11-07 15:19:26 +00:00
|
|
|
BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_path_abs(dir, G.main->name);
|
|
|
|
IMB_anim_set_index_dir(clip->anim, dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-26 15:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
|
|
|
|
{
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
int tc = get_timecode(clip, flag);
|
|
|
|
int proxy = rendersize_to_proxy(user, flag);
|
|
|
|
|
|
|
|
movieclip_open_anim_file(clip);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->anim) {
|
2014-04-02 14:07:44 +06:00
|
|
|
int fra = framenr - clip->start_frame + clip->frame_offset;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2012-03-26 13:30:53 +00:00
|
|
|
static void movieclip_calc_length(MovieClip *clip)
|
|
|
|
{
|
2012-03-26 15:57:00 +00:00
|
|
|
if (clip->source == MCLIP_SRC_MOVIE) {
|
|
|
|
movieclip_open_anim_file(clip);
|
|
|
|
|
|
|
|
if (clip->anim) {
|
|
|
|
clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
|
|
|
|
}
|
2012-03-26 13:30:53 +00:00
|
|
|
}
|
|
|
|
else if (clip->source == MCLIP_SRC_SEQUENCE) {
|
2012-04-08 07:34:09 +00:00
|
|
|
unsigned short numlen;
|
2012-04-07 16:37:55 +00:00
|
|
|
char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
|
2012-03-26 13:30:53 +00:00
|
|
|
|
2012-04-07 16:37:55 +00:00
|
|
|
BLI_stringdec(clip->name, head, tail, &numlen);
|
2012-03-26 13:30:53 +00:00
|
|
|
|
2012-04-07 16:37:55 +00:00
|
|
|
if (numlen == 0) {
|
|
|
|
/* there's no number group in file name, assume it's single framed sequence */
|
2013-05-09 14:57:20 +00:00
|
|
|
clip->len = 1;
|
2012-04-07 16:37:55 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-05-09 14:57:20 +00:00
|
|
|
clip->len = 0;
|
2012-09-24 15:27:04 +00:00
|
|
|
for (;;) {
|
2013-05-09 14:57:20 +00:00
|
|
|
get_sequence_fname(clip, clip->len + clip->start_frame, name);
|
2012-03-26 13:30:53 +00:00
|
|
|
|
2013-05-09 14:57:20 +00:00
|
|
|
if (BLI_exists(name))
|
|
|
|
clip->len++;
|
|
|
|
else
|
2012-04-07 16:37:55 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-03-26 13:30:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/*********************** image buffer cache *************************/
|
|
|
|
|
|
|
|
typedef struct MovieClipCache {
|
|
|
|
/* regular movie cache */
|
|
|
|
struct MovieCache *moviecache;
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* cached postprocessed shot */
|
|
|
|
struct {
|
|
|
|
ImBuf *ibuf;
|
|
|
|
int framenr;
|
2012-01-15 13:31:58 +00:00
|
|
|
int flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* cache for undistorted shot */
|
|
|
|
float principal[2];
|
2014-02-20 19:41:05 +06:00
|
|
|
float polynomial_k1, polynomial_k2, polynomial_k3;
|
|
|
|
float division_k1, division_k2;
|
|
|
|
short distortion_model;
|
2014-03-31 17:59:50 +06:00
|
|
|
bool undistortion_used;
|
2012-01-15 13:31:25 +00:00
|
|
|
|
|
|
|
int proxy;
|
|
|
|
short render_flag;
|
|
|
|
} postprocessed;
|
|
|
|
|
|
|
|
/* cache for stable shot */
|
|
|
|
struct {
|
2012-07-09 10:26:01 +00:00
|
|
|
ImBuf *reference_ibuf;
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
ImBuf *ibuf;
|
|
|
|
int framenr;
|
2012-02-16 07:45:01 +00:00
|
|
|
int postprocess_flag;
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2012-02-16 15:03:18 +00:00
|
|
|
float loc[2], scale, angle, aspect;
|
2012-02-16 15:03:37 +00:00
|
|
|
int proxy, filter;
|
2012-01-15 13:31:25 +00:00
|
|
|
short render_flag;
|
|
|
|
} stabilized;
|
2013-03-25 15:32:11 +00:00
|
|
|
|
|
|
|
int sequence_offset;
|
2011-11-07 12:55:18 +00:00
|
|
|
} MovieClipCache;
|
|
|
|
|
|
|
|
typedef struct MovieClipImBufCacheKey {
|
|
|
|
int framenr;
|
|
|
|
int proxy;
|
|
|
|
short render_flag;
|
|
|
|
} MovieClipImBufCacheKey;
|
|
|
|
|
2012-07-10 14:43:50 +00:00
|
|
|
typedef struct MovieClipCachePriorityData {
|
|
|
|
int framenr;
|
|
|
|
} MovieClipCachePriorityData;
|
|
|
|
|
2013-03-25 15:32:11 +00:00
|
|
|
static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
index = framenr - clip->start_frame + clip->frame_offset;
|
|
|
|
|
|
|
|
if (clip->source == MCLIP_SRC_SEQUENCE) {
|
|
|
|
if (clip->cache->sequence_offset == -1) {
|
|
|
|
unsigned short numlen;
|
|
|
|
char head[FILE_MAX], tail[FILE_MAX];
|
|
|
|
|
|
|
|
BLI_stringdec(clip->name, head, tail, &numlen);
|
|
|
|
|
|
|
|
/* see comment in get_sequence_fname */
|
|
|
|
clip->cache->sequence_offset = sequence_guess_offset(clip->name, strlen(head), numlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
index += clip->cache->sequence_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index < 0)
|
|
|
|
return framenr - index;
|
|
|
|
|
|
|
|
return framenr;
|
|
|
|
}
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
*framenr = key->framenr;
|
|
|
|
*proxy = key->proxy;
|
|
|
|
*render_flags = key->render_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int moviecache_hashhash(const void *keyv)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)keyv;
|
2012-03-25 23:19:21 +00:00
|
|
|
int rval = key->framenr;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int moviecache_hashcmp(const void *av, const void *bv)
|
|
|
|
{
|
2012-05-06 15:15:33 +00:00
|
|
|
const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey *)av;
|
|
|
|
const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey *)bv;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (a->framenr < b->framenr)
|
|
|
|
return -1;
|
|
|
|
else if (a->framenr > b->framenr)
|
|
|
|
return 1;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (a->proxy < b->proxy)
|
|
|
|
return -1;
|
|
|
|
else if (a->proxy > b->proxy)
|
|
|
|
return 1;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (a->render_flag < b->render_flag)
|
|
|
|
return -1;
|
|
|
|
else if (a->render_flag > b->render_flag)
|
|
|
|
return 1;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
static void *moviecache_getprioritydata(void *key_v)
|
2012-07-10 14:43:50 +00:00
|
|
|
{
|
|
|
|
MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *) key_v;
|
|
|
|
MovieClipCachePriorityData *priority_data;
|
|
|
|
|
2013-07-13 05:43:35 +00:00
|
|
|
priority_data = MEM_callocN(sizeof(*priority_data), "movie cache clip priority data");
|
2012-07-10 14:43:50 +00:00
|
|
|
priority_data->framenr = key->framenr;
|
|
|
|
|
|
|
|
return priority_data;
|
|
|
|
}
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
|
2012-07-10 14:43:50 +00:00
|
|
|
{
|
|
|
|
MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *) last_userkey_v;
|
|
|
|
MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
|
|
|
|
|
|
|
|
return -abs(last_userkey->framenr - priority_data->framenr);
|
|
|
|
}
|
|
|
|
|
2012-09-15 01:52:28 +00:00
|
|
|
static void moviecache_prioritydeleter(void *priority_data_v)
|
2012-07-10 14:43:50 +00:00
|
|
|
{
|
|
|
|
MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
|
|
|
|
|
|
|
|
MEM_freeN(priority_data);
|
|
|
|
}
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->cache) {
|
2011-11-07 12:55:18 +00:00
|
|
|
MovieClipImBufCacheKey key;
|
|
|
|
|
2013-03-25 15:32:11 +00:00
|
|
|
key.framenr = user_frame_to_cache_frame(clip, user->framenr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (flag & MCLIP_USE_PROXY) {
|
|
|
|
key.proxy = rendersize_to_proxy(user, flag);
|
|
|
|
key.render_flag = user->render_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
key.proxy = IMB_PROXY_NONE;
|
|
|
|
key.render_flag = 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return IMB_moviecache_get(clip->cache->moviecache, &key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
static bool has_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
|
2013-03-20 17:03:20 +00:00
|
|
|
{
|
|
|
|
if (clip->cache) {
|
|
|
|
MovieClipImBufCacheKey key;
|
|
|
|
|
2013-03-25 15:32:11 +00:00
|
|
|
key.framenr = user_frame_to_cache_frame(clip, user->framenr);
|
2013-03-20 17:03:20 +00:00
|
|
|
|
|
|
|
if (flag & MCLIP_USE_PROXY) {
|
|
|
|
key.proxy = rendersize_to_proxy(user, flag);
|
|
|
|
key.render_flag = user->render_flag;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
key.proxy = IMB_PROXY_NONE;
|
|
|
|
key.render_flag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
|
|
|
|
}
|
|
|
|
|
2014-03-31 17:59:50 +06:00
|
|
|
return false;
|
2013-03-20 17:03:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
MovieClipImBufCacheKey key;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!clip->cache) {
|
2012-07-10 14:43:50 +00:00
|
|
|
struct MovieCache *moviecache;
|
|
|
|
|
|
|
|
// char cache_name[64];
|
|
|
|
// BLI_snprintf(cache_name, sizeof(cache_name), "movie %s", clip->id.name);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-07-10 14:43:50 +00:00
|
|
|
moviecache = IMB_moviecache_create("movieclip", sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
|
|
|
|
|
|
|
|
IMB_moviecache_set_getdata_callback(moviecache, moviecache_keydata);
|
|
|
|
IMB_moviecache_set_priority_callback(moviecache, moviecache_getprioritydata, moviecache_getitempriority,
|
|
|
|
moviecache_prioritydeleter);
|
|
|
|
|
|
|
|
clip->cache->moviecache = moviecache;
|
2013-03-25 15:32:11 +00:00
|
|
|
clip->cache->sequence_offset = -1;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2013-03-25 15:32:11 +00:00
|
|
|
key.framenr = user_frame_to_cache_frame(clip, user->framenr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (flag & MCLIP_USE_PROXY) {
|
|
|
|
key.proxy = rendersize_to_proxy(user, flag);
|
|
|
|
key.render_flag = user->render_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
key.proxy = IMB_PROXY_NONE;
|
|
|
|
key.render_flag = 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2013-03-20 17:03:20 +00:00
|
|
|
if (destructive) {
|
|
|
|
IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*********************** common functions *************************/
|
|
|
|
|
|
|
|
/* only image block itself */
|
2013-02-05 12:46:15 +00:00
|
|
|
static MovieClip *movieclip_alloc(Main *bmain, const char *name)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
MovieClip *clip;
|
|
|
|
|
2014-01-15 16:37:03 +01:00
|
|
|
clip = BKE_libblock_alloc(bmain, ID_MC, name);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-05-03 23:47:39 +00:00
|
|
|
clip->aspx = clip->aspy = 1.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_settings_init(&clip->tracking);
|
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
|
|
|
BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->proxy.build_size_flag = IMB_PROXY_25;
|
|
|
|
clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
|
|
|
|
IMB_TC_FREE_RUN |
|
|
|
|
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
|
|
|
|
IMB_TC_RECORD_RUN_NO_GAPS;
|
|
|
|
clip->proxy.quality = 90;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-05 18:38:09 +00:00
|
|
|
clip->start_frame = 1;
|
2012-06-12 21:29:15 +00:00
|
|
|
clip->frame_offset = 0;
|
2012-06-05 18:38:09 +00:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return clip;
|
|
|
|
}
|
|
|
|
|
2012-06-17 16:40:16 +00:00
|
|
|
static void movieclip_load_get_szie(MovieClip *clip)
|
|
|
|
{
|
|
|
|
int width, height;
|
|
|
|
MovieClipUser user = {0};
|
|
|
|
|
|
|
|
user.framenr = 1;
|
|
|
|
BKE_movieclip_get_size(clip, &user, &width, &height);
|
|
|
|
|
|
|
|
if (width && height) {
|
|
|
|
clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
|
|
|
|
clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
|
2012-07-28 18:14:44 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
|
2012-06-17 16:40:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-05 10:32:47 +00:00
|
|
|
static void detect_clip_source(MovieClip *clip)
|
|
|
|
{
|
|
|
|
ImBuf *ibuf;
|
|
|
|
char name[FILE_MAX];
|
|
|
|
|
|
|
|
BLI_strncpy(name, clip->name, sizeof(name));
|
|
|
|
BLI_path_abs(name, G.main->name);
|
|
|
|
|
|
|
|
ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
|
|
|
|
if (ibuf) {
|
|
|
|
clip->source = MCLIP_SRC_SEQUENCE;
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
clip->source = MCLIP_SRC_MOVIE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* checks if image was already loaded, then returns same image
|
2012-03-03 20:19:11 +00:00
|
|
|
* otherwise creates new.
|
|
|
|
* does not load ibuf itself
|
|
|
|
* pass on optional frame for #name images */
|
2013-02-05 12:46:15 +00:00
|
|
|
MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
MovieClip *clip;
|
2012-06-17 16:40:16 +00:00
|
|
|
int file, len;
|
2011-11-07 12:55:18 +00:00
|
|
|
const char *libname;
|
|
|
|
char str[FILE_MAX], strtest[FILE_MAX];
|
|
|
|
|
|
|
|
BLI_strncpy(str, name, sizeof(str));
|
2013-02-05 12:46:15 +00:00
|
|
|
BLI_path_abs(str, bmain->name);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* exists? */
|
2012-04-29 15:47:02 +00:00
|
|
|
file = BLI_open(str, O_BINARY | O_RDONLY, 0);
|
2014-04-22 16:40:17 +10:00
|
|
|
if (file == -1)
|
2012-03-25 23:19:21 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
close(file);
|
|
|
|
|
|
|
|
/* ** first search an identical clip ** */
|
2013-02-05 12:46:15 +00:00
|
|
|
for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_strncpy(strtest, clip->name, sizeof(clip->name));
|
|
|
|
BLI_path_abs(strtest, G.main->name);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (strcmp(strtest, str) == 0) {
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */
|
|
|
|
clip->id.us++; /* officially should not, it doesn't link here! */
|
|
|
|
|
|
|
|
return clip;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ** add new movieclip ** */
|
|
|
|
|
|
|
|
/* create a short library name */
|
2012-03-25 23:19:21 +00:00
|
|
|
len = strlen(name);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
|
|
|
|
len--;
|
|
|
|
libname = name + len;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-02-05 12:46:15 +00:00
|
|
|
clip = movieclip_alloc(bmain, libname);
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_strncpy(clip->name, name, sizeof(clip->name));
|
|
|
|
|
2012-11-05 10:32:47 +00:00
|
|
|
detect_clip_source(clip);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-17 16:40:16 +00:00
|
|
|
movieclip_load_get_szie(clip);
|
2012-06-18 18:22:49 +00:00
|
|
|
if (clip->lastsize[0]) {
|
|
|
|
int width = clip->lastsize[0];
|
|
|
|
|
|
|
|
clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-26 13:30:53 +00:00
|
|
|
movieclip_calc_length(clip);
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return clip;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
|
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
*width = ibuf->x;
|
|
|
|
*height = ibuf->y;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->flag & MCLIP_USE_PROXY) {
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (user->render_size) {
|
2011-11-07 12:55:18 +00:00
|
|
|
case MCLIP_PROXY_RENDER_SIZE_25:
|
2012-03-25 23:19:21 +00:00
|
|
|
(*width) *= 4;
|
|
|
|
(*height) *= 4;
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_50:
|
2012-03-25 23:19:21 +00:00
|
|
|
(*width) *= 2.0f;
|
|
|
|
(*height) *= 2.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MCLIP_PROXY_RENDER_SIZE_75:
|
2012-05-06 15:15:33 +00:00
|
|
|
*width = ((float)*width) * 4.0f / 3.0f;
|
|
|
|
*height = ((float)*height) * 4.0f / 3.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-01-15 13:31:25 +00:00
|
|
|
ImBuf *undistibuf;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (distortion)
|
2012-03-25 23:19:21 +00:00
|
|
|
undistibuf = BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
|
2012-01-15 13:31:25 +00:00
|
|
|
else
|
2012-06-15 11:03:23 +00:00
|
|
|
undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
|
|
|
IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
|
|
|
|
|
|
|
|
return undistibuf;
|
|
|
|
}
|
|
|
|
|
2012-10-01 11:26:52 +00:00
|
|
|
static int need_undistortion_postprocess(MovieClipUser *user)
|
2012-01-15 13:31:25 +00:00
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* only full undistorted render can be used as on-fly undistorting image */
|
2012-10-01 11:26:52 +00:00
|
|
|
result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
|
|
|
|
(user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
return result;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 11:26:52 +00:00
|
|
|
static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-01-15 13:31:58 +00:00
|
|
|
int result = postprocess_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-10-01 11:26:52 +00:00
|
|
|
result |= need_undistortion_postprocess(user);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
return result;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-03-31 17:59:50 +06:00
|
|
|
static bool check_undistortion_cache_flags(MovieClip *clip)
|
2012-01-15 13:31:25 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieClipCache *cache = clip->cache;
|
|
|
|
MovieTrackingCamera *camera = &clip->tracking.camera;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* check for distortion model changes */
|
2014-02-20 19:41:05 +06:00
|
|
|
if (!equals_v2v2(camera->principal, cache->postprocessed.principal)) {
|
2014-03-31 17:59:50 +06:00
|
|
|
return false;
|
2014-02-20 19:41:05 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (camera->distortion_model != cache->postprocessed.distortion_model) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-02-20 19:41:05 +06:00
|
|
|
if (!equals_v3v3(&camera->k1, &cache->postprocessed.polynomial_k1)) {
|
2014-03-31 17:59:50 +06:00
|
|
|
return false;
|
2014-02-20 19:41:05 +06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!equals_v2v2(&camera->division_k1, &cache->postprocessed.division_k1)) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-03-31 17:59:50 +06:00
|
|
|
return true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-01-15 13:31:58 +00:00
|
|
|
static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieClipCache *cache = clip->cache;
|
|
|
|
int framenr = user->framenr;
|
|
|
|
short proxy = IMB_PROXY_NONE;
|
|
|
|
int render_flag = 0;
|
|
|
|
|
|
|
|
if (flag & MCLIP_USE_PROXY) {
|
|
|
|
proxy = rendersize_to_proxy(user, flag);
|
|
|
|
render_flag = user->render_flag;
|
2012-01-15 13:31:25 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* no cache or no cached postprocessed image */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!clip->cache || !clip->cache->postprocessed.ibuf)
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* postprocessing happened for other frame */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->postprocessed.framenr != framenr)
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* cached ibuf used different proxy settings */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
|
2012-01-15 13:31:58 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->postprocessed.flag != postprocess_flag)
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-10-01 11:26:52 +00:00
|
|
|
if (need_undistortion_postprocess(user)) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!check_undistortion_cache_flags(clip))
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-06-08 17:16:32 +00:00
|
|
|
else if (cache->postprocessed.undistortion_used)
|
2012-01-15 13:31:58 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
IMB_refImBuf(cache->postprocessed.ibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
return cache->postprocessed.ibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2014-02-04 15:16:21 +06:00
|
|
|
static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int postprocess_flag)
|
|
|
|
{
|
|
|
|
ImBuf *postproc_ibuf = NULL;
|
|
|
|
|
|
|
|
if (need_undistortion_postprocess(user)) {
|
|
|
|
postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
postproc_ibuf = IMB_dupImBuf(ibuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (postprocess_flag) {
|
|
|
|
bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0,
|
|
|
|
disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0,
|
|
|
|
disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0,
|
|
|
|
grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
|
|
|
|
|
|
|
|
if (disable_red || disable_green || disable_blue || grayscale)
|
|
|
|
BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return postproc_ibuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
|
2012-05-07 08:53:59 +00:00
|
|
|
int flag, int postprocess_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieClipCache *cache = clip->cache;
|
|
|
|
MovieTrackingCamera *camera = &clip->tracking.camera;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
cache->postprocessed.framenr = user->framenr;
|
2012-01-15 13:31:58 +00:00
|
|
|
cache->postprocessed.flag = postprocess_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (flag & MCLIP_USE_PROXY) {
|
|
|
|
cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
|
|
|
|
cache->postprocessed.render_flag = user->render_flag;
|
2012-01-15 13:31:25 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
cache->postprocessed.proxy = IMB_PROXY_NONE;
|
|
|
|
cache->postprocessed.render_flag = 0;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-10-01 11:26:52 +00:00
|
|
|
if (need_undistortion_postprocess(user)) {
|
2014-02-20 19:41:05 +06:00
|
|
|
cache->postprocessed.distortion_model = camera->distortion_model;
|
2012-01-15 13:31:25 +00:00
|
|
|
copy_v2_v2(cache->postprocessed.principal, camera->principal);
|
2014-02-20 19:41:05 +06:00
|
|
|
copy_v3_v3(&cache->postprocessed.polynomial_k1, &camera->k1);
|
|
|
|
copy_v2_v2(&cache->postprocessed.division_k1, &camera->division_k1);
|
2014-03-31 17:59:50 +06:00
|
|
|
cache->postprocessed.undistortion_used = true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else {
|
2014-03-31 17:59:50 +06:00
|
|
|
cache->postprocessed.undistortion_used = false;
|
2012-03-25 23:19:21 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-02-04 15:16:21 +06:00
|
|
|
IMB_refImBuf(ibuf);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2012-07-09 10:26:01 +00:00
|
|
|
if (cache->postprocessed.ibuf)
|
|
|
|
IMB_freeImBuf(cache->postprocessed.ibuf);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2014-02-04 15:16:21 +06:00
|
|
|
cache->postprocessed.ibuf = ibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-02-01 19:06:21 +00:00
|
|
|
static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
|
|
|
|
int postprocess_flag, int cache_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *ibuf = NULL;
|
2014-03-31 17:59:50 +06:00
|
|
|
int framenr = user->framenr;
|
|
|
|
bool need_postprocess = false;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* cache isn't threadsafe itself and also loading of movies
|
2012-03-03 20:19:11 +00:00
|
|
|
* can't happen from concurent threads that's why we use lock here */
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_lock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* try to obtain cached postprocessed frame first */
|
2012-10-01 11:26:52 +00:00
|
|
|
if (need_postprocessed_frame(user, postprocess_flag)) {
|
2012-05-03 23:47:39 +00:00
|
|
|
ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ibuf)
|
2014-03-31 17:59:50 +06:00
|
|
|
need_postprocess = true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ibuf)
|
2012-05-03 23:47:39 +00:00
|
|
|
ibuf = get_imbuf_cache(clip, user, flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ibuf) {
|
2014-03-31 17:59:50 +06:00
|
|
|
bool use_sequence = false;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* undistorted proxies for movies should be read as image sequence */
|
2012-03-25 23:19:21 +00:00
|
|
|
use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
|
|
|
|
(user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
|
|
|
|
ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
|
2013-03-20 17:03:20 +00:00
|
|
|
put_imbuf_cache(clip, user, ibuf, flag, true);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf) {
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->lastframe = framenr;
|
2011-11-07 12:55:18 +00:00
|
|
|
real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
|
|
|
|
|
2014-02-04 15:16:21 +06:00
|
|
|
/* postprocess frame and put to cache if needed*/
|
2012-03-24 06:18:31 +00:00
|
|
|
if (need_postprocess) {
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *tmpibuf = ibuf;
|
2014-02-04 15:16:21 +06:00
|
|
|
ibuf = postprocess_frame(clip, user, tmpibuf, postprocess_flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(tmpibuf);
|
2014-02-04 15:16:21 +06:00
|
|
|
if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
|
|
|
|
put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_unlock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
|
|
|
|
{
|
2012-02-01 19:06:21 +00:00
|
|
|
return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
|
2012-01-15 13:31:25 +00:00
|
|
|
}
|
|
|
|
|
2012-02-01 19:06:21 +00:00
|
|
|
ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-02-01 19:06:21 +00:00
|
|
|
return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
|
2012-01-15 13:31:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
|
|
|
|
{
|
2012-02-01 19:06:21 +00:00
|
|
|
return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
|
2012-01-15 13:31:25 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-07-09 10:26:01 +00:00
|
|
|
static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBuf *reference_ibuf,
|
|
|
|
int framenr, int postprocess_flag)
|
2012-01-15 13:31:25 +00:00
|
|
|
{
|
|
|
|
MovieClipCache *cache = clip->cache;
|
2012-02-16 15:03:37 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2012-01-15 13:31:25 +00:00
|
|
|
ImBuf *stableibuf;
|
|
|
|
float tloc[2], tscale, tangle;
|
|
|
|
short proxy = IMB_PROXY_NONE;
|
|
|
|
int render_flag = 0;
|
2012-06-15 11:15:48 +00:00
|
|
|
int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->flag & MCLIP_USE_PROXY) {
|
2012-01-15 13:31:25 +00:00
|
|
|
proxy = rendersize_to_proxy(user, clip->flag);
|
|
|
|
render_flag = user->render_flag;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* there's no cached frame or it was calculated for another frame */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-07-09 10:26:01 +00:00
|
|
|
if (cache->stabilized.reference_ibuf != reference_ibuf)
|
|
|
|
return NULL;
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
/* cached ibuf used different proxy settings */
|
2012-03-25 23:19:21 +00:00
|
|
|
if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy)
|
2012-01-15 13:31:25 +00:00
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->stabilized.postprocess_flag != postprocess_flag)
|
2012-02-16 07:45:01 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-02-16 15:03:18 +00:00
|
|
|
/* stabilization also depends on pixel aspect ratio */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->stabilized.aspect != tracking->camera.pixel_aspect)
|
2012-02-16 15:03:37 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (cache->stabilized.filter != tracking->stabilization.filter)
|
2012-02-16 15:03:18 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
stableibuf = cache->stabilized.ibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-15 11:15:48 +00:00
|
|
|
BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
|
|
|
/* check for stabilization parameters */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tscale != cache->stabilized.scale ||
|
2012-05-06 15:15:33 +00:00
|
|
|
tangle != cache->stabilized.angle ||
|
|
|
|
!equals_v2v2(tloc, cache->stabilized.loc))
|
2012-01-15 13:31:25 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
IMB_refImBuf(stableibuf);
|
|
|
|
|
|
|
|
return stableibuf;
|
|
|
|
}
|
|
|
|
|
2012-02-16 07:45:01 +00:00
|
|
|
static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
|
|
|
|
int framenr, int postprocess_flag)
|
2012-01-15 13:31:25 +00:00
|
|
|
{
|
|
|
|
MovieClipCache *cache = clip->cache;
|
2012-02-16 15:03:37 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2012-01-15 13:31:25 +00:00
|
|
|
ImBuf *stableibuf;
|
|
|
|
float tloc[2], tscale, tangle;
|
2012-06-15 11:15:48 +00:00
|
|
|
int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2012-06-15 11:15:48 +00:00
|
|
|
stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle);
|
2012-01-15 13:31:25 +00:00
|
|
|
|
|
|
|
copy_v2_v2(cache->stabilized.loc, tloc);
|
|
|
|
|
2013-04-08 10:56:50 +00:00
|
|
|
cache->stabilized.reference_ibuf = ibuf;
|
2012-01-15 13:31:25 +00:00
|
|
|
cache->stabilized.scale = tscale;
|
|
|
|
cache->stabilized.angle = tangle;
|
|
|
|
cache->stabilized.framenr = framenr;
|
2012-02-16 15:03:37 +00:00
|
|
|
cache->stabilized.aspect = tracking->camera.pixel_aspect;
|
|
|
|
cache->stabilized.filter = tracking->stabilization.filter;
|
2012-01-15 13:31:25 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->flag & MCLIP_USE_PROXY) {
|
|
|
|
cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
|
|
|
|
cache->stabilized.render_flag = user->render_flag;
|
2012-01-15 13:31:25 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
cache->stabilized.proxy = IMB_PROXY_NONE;
|
|
|
|
cache->stabilized.render_flag = 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-02-16 07:45:01 +00:00
|
|
|
cache->stabilized.postprocess_flag = postprocess_flag;
|
|
|
|
|
2012-07-09 10:26:01 +00:00
|
|
|
if (cache->stabilized.ibuf)
|
|
|
|
IMB_freeImBuf(cache->stabilized.ibuf);
|
|
|
|
|
|
|
|
cache->stabilized.ibuf = stableibuf;
|
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
IMB_refImBuf(stableibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-01-15 13:31:25 +00:00
|
|
|
return stableibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle,
|
|
|
|
int postprocess_flag)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *ibuf, *stableibuf = NULL;
|
|
|
|
int framenr = user->framenr;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!ibuf)
|
2011-11-07 12:55:18 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
|
2012-05-03 23:47:39 +00:00
|
|
|
MovieClipCache *cache = clip->cache;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-07-09 10:26:01 +00:00
|
|
|
stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!stableibuf)
|
2012-03-25 23:19:21 +00:00
|
|
|
stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
|
|
|
|
|
|
|
|
if (loc)
|
|
|
|
copy_v2_v2(loc, cache->stabilized.loc);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (scale)
|
2012-05-03 23:47:39 +00:00
|
|
|
*scale = cache->stabilized.scale;
|
2012-03-25 23:19:21 +00:00
|
|
|
|
|
|
|
if (angle)
|
2012-05-03 23:47:39 +00:00
|
|
|
*angle = cache->stabilized.angle;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
if (loc)
|
|
|
|
zero_v2(loc);
|
|
|
|
|
|
|
|
if (scale)
|
2012-05-03 23:47:39 +00:00
|
|
|
*scale = 1.0f;
|
2012-03-25 23:19:21 +00:00
|
|
|
|
|
|
|
if (angle)
|
2012-05-03 23:47:39 +00:00
|
|
|
*angle = 0.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
stableibuf = ibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (stableibuf != ibuf) {
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2012-03-25 23:19:21 +00:00
|
|
|
ibuf = stableibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf) {
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2014-03-31 17:59:50 +06:00
|
|
|
return true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2014-03-31 17:59:50 +06:00
|
|
|
return false;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
|
|
|
|
{
|
2012-06-07 16:15:24 +00:00
|
|
|
#if 0
|
|
|
|
/* originally was needed to support image sequences with different image dimensions,
|
|
|
|
* which might be useful for such things as reconstruction of unordered image sequence,
|
|
|
|
* or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded
|
|
|
|
* cache lookups and even unwanted non-proxied files loading when doing mask parenting,
|
|
|
|
* so let's disable this for now and assume image sequence consists of images with
|
|
|
|
* equal sizes (sergey)
|
|
|
|
*/
|
2012-03-25 23:19:21 +00:00
|
|
|
if (user->framenr == clip->lastframe) {
|
2012-06-07 16:15:24 +00:00
|
|
|
#endif
|
|
|
|
if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
|
2012-03-25 23:19:21 +00:00
|
|
|
*width = clip->lastsize[0];
|
|
|
|
*height = clip->lastsize[1];
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf && ibuf->x && ibuf->y) {
|
2011-11-07 12:55:18 +00:00
|
|
|
real_ibuf_size(clip, user, ibuf, width, height);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-04-28 10:09:58 +00:00
|
|
|
*width = clip->lastsize[0];
|
|
|
|
*height = clip->lastsize[1];
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf)
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
}
|
|
|
|
}
|
2012-09-13 05:29:38 +00:00
|
|
|
void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2])
|
|
|
|
{
|
|
|
|
int width, height;
|
|
|
|
BKE_movieclip_get_size(clip, user, &width, &height);
|
|
|
|
|
|
|
|
size[0] = (float)width;
|
|
|
|
size[1] = (float)height;
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-26 13:30:53 +00:00
|
|
|
int BKE_movieclip_get_duration(MovieClip *clip)
|
2012-03-21 18:02:29 +00:00
|
|
|
{
|
2012-03-26 13:36:22 +00:00
|
|
|
if (!clip->len) {
|
|
|
|
movieclip_calc_length(clip);
|
2012-03-26 13:30:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return clip->len;
|
2012-03-21 18:02:29 +00:00
|
|
|
}
|
|
|
|
|
2012-09-13 05:29:38 +00:00
|
|
|
void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-09-13 05:29:38 +00:00
|
|
|
*aspx = 1.0;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* x is always 1 */
|
2012-03-25 23:19:21 +00:00
|
|
|
*aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get segments of cached frames. useful for debugging cache policies */
|
|
|
|
void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
|
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
*totseg_r = 0;
|
|
|
|
*points_r = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->cache) {
|
2012-03-25 23:19:21 +00:00
|
|
|
int proxy = rendersize_to_proxy(user, clip->flag);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
|
|
|
|
{
|
|
|
|
/* TODO: clamp framenr here? */
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
iuser->framenr = framenr;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void free_buffers(MovieClip *clip)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->cache) {
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_moviecache_free(clip->cache->moviecache);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->cache->postprocessed.ibuf)
|
2012-01-15 13:31:25 +00:00
|
|
|
IMB_freeImBuf(clip->cache->postprocessed.ibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->cache->stabilized.ibuf)
|
2012-01-15 13:31:25 +00:00
|
|
|
IMB_freeImBuf(clip->cache->stabilized.ibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
MEM_freeN(clip->cache);
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->cache = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip->anim) {
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_free_anim(clip->anim);
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->anim = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-02-15 16:06:48 +00:00
|
|
|
|
|
|
|
BKE_free_animdata((ID *) clip);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2013-04-04 09:50:51 +00:00
|
|
|
void BKE_movieclip_clear_cache(MovieClip *clip)
|
|
|
|
{
|
|
|
|
free_buffers(clip);
|
|
|
|
}
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
void BKE_movieclip_reload(MovieClip *clip)
|
|
|
|
{
|
|
|
|
/* clear cache */
|
|
|
|
free_buffers(clip);
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
clip->tracking.stabilization.ok = false;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* update clip source */
|
2012-11-05 10:32:47 +00:00
|
|
|
detect_clip_source(clip);
|
2012-03-26 13:30:53 +00:00
|
|
|
|
2012-07-28 18:14:44 +00:00
|
|
|
clip->lastsize[0] = clip->lastsize[1] = 0;
|
2012-06-17 16:40:16 +00:00
|
|
|
movieclip_load_get_szie(clip);
|
|
|
|
|
2012-03-26 13:30:53 +00:00
|
|
|
movieclip_calc_length(clip);
|
2012-10-18 09:48:51 +00:00
|
|
|
|
|
|
|
/* same as for image update -- don't use notifiers because they are not 100% sure to succeeded
|
|
|
|
* (node trees which are not currently visible wouldn't be refreshed)
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
Scene *scene;
|
|
|
|
for (scene = G.main->scene.first; scene; scene = scene->id.next) {
|
|
|
|
if (scene->nodetree) {
|
|
|
|
nodeUpdateID(scene->nodetree, &clip->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scopes->ok)
|
2011-12-05 18:57:17 +00:00
|
|
|
return;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (scopes->track_preview) {
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(scopes->track_preview);
|
2012-03-25 23:19:21 +00:00
|
|
|
scopes->track_preview = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
if (scopes->track_search) {
|
|
|
|
IMB_freeImBuf(scopes->track_search);
|
|
|
|
scopes->track_search = NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
scopes->marker = NULL;
|
|
|
|
scopes->track = NULL;
|
2014-04-01 11:34:00 +11:00
|
|
|
scopes->track_locked = true;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clip) {
|
2012-06-15 11:03:23 +00:00
|
|
|
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (act_track) {
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTrackingTrack *track = act_track;
|
2012-06-06 18:58:30 +00:00
|
|
|
int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
|
2012-06-15 11:03:23 +00:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-24 14:16:40 +00:00
|
|
|
scopes->marker = marker;
|
|
|
|
scopes->track = track;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (marker->flag & MARKER_DISABLED) {
|
2014-04-01 11:34:00 +11:00
|
|
|
scopes->track_disabled = true;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
scopes->track_disabled = false;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-05-09 08:33:11 +00:00
|
|
|
if (ibuf && (ibuf->rect || ibuf->rect_float)) {
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTrackingMarker undist_marker = *marker;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
|
2011-11-07 12:55:18 +00:00
|
|
|
int width, height;
|
2012-05-03 23:47:39 +00:00
|
|
|
float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
BKE_movieclip_get_size(clip, user, &width, &height);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
undist_marker.pos[0] *= width;
|
2012-05-06 15:15:33 +00:00
|
|
|
undist_marker.pos[1] *= height * aspy;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
undist_marker.pos[0] /= width;
|
2012-05-06 15:15:33 +00:00
|
|
|
undist_marker.pos[1] /= height * aspy;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2014-04-10 21:14:36 +06:00
|
|
|
scopes->track_search = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, true, true);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
scopes->undist_marker = undist_marker;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
scopes->frame_width = ibuf->x;
|
|
|
|
scopes->frame_height = ibuf->y;
|
2012-06-12 11:13:53 +00:00
|
|
|
|
|
|
|
scopes->use_track_mask = track->flag & TRACK_PREVIEW_ALPHA;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
}
|
|
|
|
|
2012-05-06 15:15:33 +00:00
|
|
|
if ((track->flag & TRACK_LOCKED) == 0) {
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
float pat_min[2], pat_max[2];
|
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
scopes->track_locked = false;
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
|
|
|
|
/* XXX: would work fine with non-transformed patterns, but would likely fail
|
|
|
|
* with transformed patterns, but that would be easier to debug when
|
|
|
|
* we'll have real pattern sampling (at least to test) */
|
|
|
|
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
|
|
|
|
|
|
|
|
scopes->slide_scale[0] = pat_max[0] - pat_min[0];
|
|
|
|
scopes->slide_scale[1] = pat_max[1] - pat_min[1];
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
scopes->framenr = user->framenr;
|
2014-04-01 11:34:00 +11:00
|
|
|
scopes->ok = true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2011-11-26 04:07:38 +00:00
|
|
|
char name[FILE_MAX];
|
2011-11-07 12:55:18 +00:00
|
|
|
int quality, rectx, recty;
|
2012-03-25 23:19:21 +00:00
|
|
|
int size = rendersize_to_number(proxy_render_size);
|
2011-11-07 12:55:18 +00:00
|
|
|
ImBuf *scaleibuf;
|
|
|
|
|
|
|
|
get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
rectx = ibuf->x * size / 100.0f;
|
|
|
|
recty = ibuf->y * size / 100.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
scaleibuf = IMB_dupImBuf(ibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-03-15 16:57:19 +00:00
|
|
|
if (threaded)
|
|
|
|
IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
|
|
|
|
else
|
|
|
|
IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
quality = clip->proxy.quality;
|
|
|
|
scaleibuf->ftype = JPG | quality;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* unsupported feature only confuses other s/w */
|
2012-03-25 23:19:21 +00:00
|
|
|
if (scaleibuf->planes == 32)
|
|
|
|
scaleibuf->planes = 24;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-03-15 16:57:19 +00:00
|
|
|
/* TODO: currently the most weak part of multithreaded proxies,
|
|
|
|
* could be solved in a way that thread only prepares memory
|
|
|
|
* buffer and write to disk happens separately
|
|
|
|
*/
|
2011-11-07 12:55:18 +00:00
|
|
|
BLI_lock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
|
|
|
BLI_make_existing_file(name);
|
2012-03-25 23:19:21 +00:00
|
|
|
if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
|
2011-11-07 12:55:18 +00:00
|
|
|
perror(name);
|
|
|
|
|
|
|
|
BLI_unlock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
|
|
|
IMB_freeImBuf(scaleibuf);
|
|
|
|
}
|
|
|
|
|
2013-03-15 16:57:19 +00:00
|
|
|
/* note: currently used by proxy job for movies, threading happens within single frame
|
|
|
|
* (meaning scaling shall be threaded)
|
|
|
|
*/
|
2011-12-27 11:09:06 +00:00
|
|
|
void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
|
2014-02-03 18:55:59 +11:00
|
|
|
int cfra, int *build_sizes, int build_count, bool undistorted)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
ImBuf *ibuf;
|
|
|
|
MovieClipUser user;
|
|
|
|
|
2013-03-15 09:32:59 +00:00
|
|
|
if (!build_count)
|
|
|
|
return;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
user.framenr = cfra;
|
|
|
|
user.render_flag = 0;
|
|
|
|
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ibuf) {
|
2012-03-25 23:19:21 +00:00
|
|
|
ImBuf *tmpibuf = ibuf;
|
2011-11-07 12:55:18 +00:00
|
|
|
int i;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (undistorted)
|
2012-03-25 23:19:21 +00:00
|
|
|
tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (i = 0; i < build_count; i++)
|
2013-03-15 16:57:19 +00:00
|
|
|
movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (tmpibuf != ibuf)
|
2011-11-07 12:55:18 +00:00
|
|
|
IMB_freeImBuf(tmpibuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-15 16:57:19 +00:00
|
|
|
/* note: currently used by proxy job for sequences, threading happens within sequence
|
|
|
|
* (different threads handles different frames, no threading within frame is needed)
|
|
|
|
*/
|
|
|
|
void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion,
|
2014-02-03 18:55:59 +11:00
|
|
|
int cfra, int *build_sizes, int build_count, bool undistorted)
|
2013-03-15 16:57:19 +00:00
|
|
|
{
|
|
|
|
if (!build_count)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ibuf) {
|
|
|
|
ImBuf *tmpibuf = ibuf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (undistorted)
|
|
|
|
tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
|
|
|
|
|
|
|
|
for (i = 0; i < build_count; i++)
|
|
|
|
movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
|
|
|
|
|
|
|
|
if (tmpibuf != ibuf)
|
|
|
|
IMB_freeImBuf(tmpibuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-28 16:49:00 +00:00
|
|
|
void BKE_movieclip_free(MovieClip *clip)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
free_buffers(clip);
|
|
|
|
|
|
|
|
BKE_tracking_free(&clip->tracking);
|
|
|
|
}
|
|
|
|
|
2012-04-28 16:49:00 +00:00
|
|
|
void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
bScreen *scr;
|
|
|
|
ScrArea *area;
|
|
|
|
SpaceLink *sl;
|
|
|
|
Scene *sce;
|
|
|
|
Object *ob;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
|
|
|
|
for (area = scr->areabase.first; area; area = area->next) {
|
|
|
|
for (sl = area->spacedata.first; sl; sl = sl->next) {
|
|
|
|
if (sl->spacetype == SPACE_CLIP) {
|
|
|
|
SpaceClip *sc = (SpaceClip *) sl;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (sc->clip == clip)
|
|
|
|
sc->clip = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else if (sl->spacetype == SPACE_VIEW3D) {
|
|
|
|
View3D *v3d = (View3D *) sl;
|
2011-11-07 12:55:18 +00:00
|
|
|
BGpic *bgpic;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
|
|
|
|
if (bgpic->clip == clip)
|
|
|
|
bgpic->clip = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (sce = bmain->scene.first; sce; sce = sce->id.next) {
|
|
|
|
if (sce->clip == clip)
|
|
|
|
sce->clip = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (ob = bmain->object.first; ob; ob = ob->id.next) {
|
2011-12-22 20:29:44 +00:00
|
|
|
bConstraint *con;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
for (con = ob->constraints.first; con; con = con->next) {
|
2013-08-03 22:03:15 +00:00
|
|
|
if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
|
2012-03-25 23:19:21 +00:00
|
|
|
bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (data->clip == clip)
|
|
|
|
data->clip = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2013-08-03 22:03:15 +00:00
|
|
|
else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
|
2012-03-25 23:19:21 +00:00
|
|
|
bCameraSolverConstraint *data = (bCameraSolverConstraint *) con->data;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-26 09:36:19 +00:00
|
|
|
if (data->clip == clip)
|
|
|
|
data->clip = NULL;
|
|
|
|
}
|
2013-08-03 22:03:15 +00:00
|
|
|
else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
|
2012-03-26 09:36:19 +00:00
|
|
|
bObjectSolverConstraint *data = (bObjectSolverConstraint *) con->data;
|
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (data->clip == clip)
|
|
|
|
data->clip = NULL;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
FOREACH_NODETREE(bmain, ntree, id) {
|
|
|
|
BKE_node_tree_unlink_id((ID *)clip, ntree);
|
|
|
|
} FOREACH_NODETREE_END
|
2012-10-01 07:54:37 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
clip->id.us = 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-06-06 18:58:30 +00:00
|
|
|
|
2012-06-20 10:54:56 +00:00
|
|
|
float BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, float framenr)
|
2012-06-06 18:58:30 +00:00
|
|
|
{
|
2012-06-20 10:54:56 +00:00
|
|
|
return framenr - (float) clip->start_frame + 1.0f;
|
2012-06-06 18:58:30 +00:00
|
|
|
}
|
|
|
|
|
2012-06-20 10:54:56 +00:00
|
|
|
float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr)
|
2012-06-06 18:58:30 +00:00
|
|
|
{
|
2012-06-20 10:54:56 +00:00
|
|
|
return framenr + (float) clip->start_frame - 1.0f;
|
2012-06-06 18:58:30 +00:00
|
|
|
}
|
2013-03-15 16:57:19 +00:00
|
|
|
|
2013-03-20 17:03:20 +00:00
|
|
|
void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char *name)
|
2013-03-15 16:57:19 +00:00
|
|
|
{
|
2013-03-20 17:03:20 +00:00
|
|
|
if (clip->source == MCLIP_SRC_SEQUENCE) {
|
|
|
|
int use_proxy;
|
|
|
|
|
|
|
|
use_proxy = (clip->flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
|
|
|
|
|
|
|
|
if (use_proxy) {
|
|
|
|
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
|
|
|
|
get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
get_sequence_fname(clip, user->framenr, name);
|
|
|
|
}
|
2013-03-15 16:57:19 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_strncpy(name, clip->name, FILE_MAX);
|
|
|
|
BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
|
|
|
|
}
|
|
|
|
}
|
2013-03-20 17:03:20 +00:00
|
|
|
|
|
|
|
ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
|
|
|
|
{
|
|
|
|
ImBuf *ibuf = NULL;
|
|
|
|
|
|
|
|
if (clip->source == MCLIP_SRC_MOVIE) {
|
|
|
|
BLI_lock_thread(LOCK_MOVIECLIP);
|
|
|
|
ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
|
|
|
|
BLI_unlock_thread(LOCK_MOVIECLIP);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
|
2013-03-20 17:03:20 +00:00
|
|
|
{
|
2014-02-03 18:55:59 +11:00
|
|
|
bool has_frame = false;
|
2013-03-20 17:03:20 +00:00
|
|
|
|
|
|
|
BLI_lock_thread(LOCK_MOVIECLIP);
|
|
|
|
has_frame = has_imbuf_cache(clip, user, clip->flag);
|
|
|
|
BLI_unlock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
|
|
|
return has_frame;
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf)
|
2013-03-20 17:03:20 +00:00
|
|
|
{
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
BLI_lock_thread(LOCK_MOVIECLIP);
|
|
|
|
result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
|
|
|
|
BLI_unlock_thread(LOCK_MOVIECLIP);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|