2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2011 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation,
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/blenkernel/intern/movieclip.c
44 #include "MEM_guardedalloc.h"
46 #include "DNA_constraint_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_space_types.h"
49 #include "DNA_movieclip_types.h"
50 #include "DNA_node_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_view3d_types.h"
55 #include "BLI_utildefines.h"
57 #include "BLI_blenlib.h"
58 #include "BLI_ghash.h"
60 #include "BLI_threads.h"
62 #include "BKE_animsys.h"
63 #include "BKE_colortools.h"
64 #include "BKE_library.h"
65 #include "BKE_global.h"
67 #include "BKE_movieclip.h"
69 #include "BKE_image.h" /* openanim */
70 #include "BKE_tracking.h"
72 #include "IMB_imbuf_types.h"
73 #include "IMB_imbuf.h"
74 #include "IMB_moviecache.h"
77 # include "intern/openexr/openexr_multi.h"
80 /*********************** movieclip buffer loaders *************************/
82 static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
84 char num[FILE_MAX] = {0};
86 BLI_strncpy(num, full_name + head_len, numlen + 1);
91 static int rendersize_to_proxy(MovieClipUser *user, int flag)
93 if ((flag & MCLIP_USE_PROXY) == 0)
94 return IMB_PROXY_NONE;
96 switch (user->render_size) {
97 case MCLIP_PROXY_RENDER_SIZE_25:
100 case MCLIP_PROXY_RENDER_SIZE_50:
103 case MCLIP_PROXY_RENDER_SIZE_75:
106 case MCLIP_PROXY_RENDER_SIZE_100:
107 return IMB_PROXY_100;
109 case MCLIP_PROXY_RENDER_SIZE_FULL:
110 return IMB_PROXY_NONE;
113 return IMB_PROXY_NONE;
116 static int rendersize_to_number(int render_size)
118 switch (render_size) {
119 case MCLIP_PROXY_RENDER_SIZE_25:
122 case MCLIP_PROXY_RENDER_SIZE_50:
125 case MCLIP_PROXY_RENDER_SIZE_75:
128 case MCLIP_PROXY_RENDER_SIZE_100:
131 case MCLIP_PROXY_RENDER_SIZE_FULL:
138 static int get_timecode(MovieClip *clip, int flag)
140 if ((flag & MCLIP_USE_PROXY) == 0)
143 return clip->proxy.tc;
146 static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
148 unsigned short numlen;
149 char head[FILE_MAX], tail[FILE_MAX];
152 BLI_strncpy(name, clip->name, sizeof(clip->name));
153 BLI_stringdec(name, head, tail, &numlen);
155 /* movieclips always points to first image from sequence,
156 * autoguess offset for now. could be something smarter in the future
158 offset = sequence_guess_offset(clip->name, strlen(head), numlen);
161 BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
163 BLI_strncpy(name, clip->name, sizeof(clip->name));
165 BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
168 /* supposed to work with sequences only */
169 static void get_proxy_fname(MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *name)
171 int size = rendersize_to_number(proxy_render_size);
172 char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
173 int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset;
175 BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
177 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
178 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
181 BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
185 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
187 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
189 BLI_path_abs(name, G.main->name);
190 BLI_path_frame(name, 1, 0);
192 strcat(name, ".jpg");
195 static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
200 bool use_proxy = false;
203 use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
205 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
206 get_proxy_fname(clip, user->render_size, undistort, framenr, name);
208 /* Well, this is a bit weird, but proxies for movie sources
209 * are built in the same exact color space as the input,
211 * But image sequences are built in the display space.
213 if (clip->source == MCLIP_SRC_MOVIE) {
214 colorspace = clip->colorspace_settings.name;
221 get_sequence_fname(clip, framenr, name);
222 colorspace = clip->colorspace_settings.name;
225 loadflag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
228 ibuf = IMB_loadiffname(name, loadflag, colorspace);
232 if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
233 IMB_exr_close(ibuf->userdata);
234 ibuf->userdata = NULL;
242 static void movieclip_open_anim_file(MovieClip *clip)
247 BLI_strncpy(str, clip->name, FILE_MAX);
248 BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
250 /* FIXME: make several stream accessible in image editor, too */
251 clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name);
254 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
256 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
257 BLI_path_abs(dir, G.main->name);
258 IMB_anim_set_index_dir(clip->anim, dir);
264 static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
267 int tc = get_timecode(clip, flag);
268 int proxy = rendersize_to_proxy(user, flag);
270 movieclip_open_anim_file(clip);
273 int fra = framenr - clip->start_frame + clip->frame_offset;
275 ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
281 static void movieclip_calc_length(MovieClip *clip)
283 if (clip->source == MCLIP_SRC_MOVIE) {
284 movieclip_open_anim_file(clip);
287 clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
290 else if (clip->source == MCLIP_SRC_SEQUENCE) {
291 unsigned short numlen;
292 char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
294 BLI_stringdec(clip->name, head, tail, &numlen);
297 /* there's no number group in file name, assume it's single framed sequence */
303 get_sequence_fname(clip, clip->len + clip->start_frame, name);
305 if (BLI_exists(name))
314 /*********************** image buffer cache *************************/
316 typedef struct MovieClipCache {
317 /* regular movie cache */
318 struct MovieCache *moviecache;
320 /* cached postprocessed shot */
326 /* cache for undistorted shot */
328 float polynomial_k1, polynomial_k2, polynomial_k3;
329 float division_k1, division_k2;
330 short distortion_model;
331 bool undistortion_used;
337 /* cache for stable shot */
339 ImBuf *reference_ibuf;
343 int postprocess_flag;
345 float loc[2], scale, angle, aspect;
353 typedef struct MovieClipImBufCacheKey {
357 } MovieClipImBufCacheKey;
359 typedef struct MovieClipCachePriorityData {
361 } MovieClipCachePriorityData;
363 static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
367 index = framenr - clip->start_frame + clip->frame_offset;
369 if (clip->source == MCLIP_SRC_SEQUENCE) {
370 if (clip->cache->sequence_offset == -1) {
371 unsigned short numlen;
372 char head[FILE_MAX], tail[FILE_MAX];
374 BLI_stringdec(clip->name, head, tail, &numlen);
376 /* see comment in get_sequence_fname */
377 clip->cache->sequence_offset = sequence_guess_offset(clip->name, strlen(head), numlen);
380 index += clip->cache->sequence_offset;
384 return framenr - index;
389 static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
391 const MovieClipImBufCacheKey *key = userkey;
393 *framenr = key->framenr;
395 *render_flags = key->render_flag;
398 static unsigned int moviecache_hashhash(const void *keyv)
400 const MovieClipImBufCacheKey *key = keyv;
401 int rval = key->framenr;
406 static bool moviecache_hashcmp(const void *av, const void *bv)
408 const MovieClipImBufCacheKey *a = av;
409 const MovieClipImBufCacheKey *b = bv;
411 return ((a->framenr != b->framenr) ||
412 (a->proxy != b->proxy) ||
413 (a->render_flag != b->render_flag));
416 static void *moviecache_getprioritydata(void *key_v)
418 MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *) key_v;
419 MovieClipCachePriorityData *priority_data;
421 priority_data = MEM_callocN(sizeof(*priority_data), "movie cache clip priority data");
422 priority_data->framenr = key->framenr;
424 return priority_data;
427 static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
429 MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *) last_userkey_v;
430 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
432 return -abs(last_userkey->framenr - priority_data->framenr);
435 static void moviecache_prioritydeleter(void *priority_data_v)
437 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
439 MEM_freeN(priority_data);
442 static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
445 MovieClipImBufCacheKey key;
447 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
449 if (flag & MCLIP_USE_PROXY) {
450 key.proxy = rendersize_to_proxy(user, flag);
451 key.render_flag = user->render_flag;
454 key.proxy = IMB_PROXY_NONE;
458 return IMB_moviecache_get(clip->cache->moviecache, &key);
464 static bool has_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
467 MovieClipImBufCacheKey key;
469 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
471 if (flag & MCLIP_USE_PROXY) {
472 key.proxy = rendersize_to_proxy(user, flag);
473 key.render_flag = user->render_flag;
476 key.proxy = IMB_PROXY_NONE;
480 return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
486 static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
488 MovieClipImBufCacheKey key;
491 struct MovieCache *moviecache;
493 // char cache_name[64];
494 // BLI_snprintf(cache_name, sizeof(cache_name), "movie %s", clip->id.name);
496 clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
498 moviecache = IMB_moviecache_create("movieclip", sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
500 IMB_moviecache_set_getdata_callback(moviecache, moviecache_keydata);
501 IMB_moviecache_set_priority_callback(moviecache, moviecache_getprioritydata, moviecache_getitempriority,
502 moviecache_prioritydeleter);
504 clip->cache->moviecache = moviecache;
505 clip->cache->sequence_offset = -1;
508 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
510 if (flag & MCLIP_USE_PROXY) {
511 key.proxy = rendersize_to_proxy(user, flag);
512 key.render_flag = user->render_flag;
515 key.proxy = IMB_PROXY_NONE;
520 IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
524 return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
528 static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf),
530 void *UNUSED(userdata))
532 MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
534 return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
537 /*********************** common functions *************************/
539 /* only image block itself */
540 static MovieClip *movieclip_alloc(Main *bmain, const char *name)
544 clip = BKE_libblock_alloc(bmain, ID_MC, name);
546 clip->aspx = clip->aspy = 1.0f;
548 BKE_tracking_settings_init(&clip->tracking);
549 BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings);
551 clip->proxy.build_size_flag = IMB_PROXY_25;
552 clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
554 IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
555 IMB_TC_RECORD_RUN_NO_GAPS;
556 clip->proxy.quality = 90;
558 clip->start_frame = 1;
559 clip->frame_offset = 0;
564 static void movieclip_load_get_szie(MovieClip *clip)
567 MovieClipUser user = {0};
570 BKE_movieclip_get_size(clip, &user, &width, &height);
572 if (width && height) {
573 clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
574 clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
577 clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
581 static void detect_clip_source(MovieClip *clip)
586 BLI_strncpy(name, clip->name, sizeof(name));
587 BLI_path_abs(name, G.main->name);
589 ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
591 clip->source = MCLIP_SRC_SEQUENCE;
595 clip->source = MCLIP_SRC_MOVIE;
599 /* checks if image was already loaded, then returns same image
600 * otherwise creates new.
601 * does not load ibuf itself
602 * pass on optional frame for #name images */
603 MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
608 char str[FILE_MAX], strtest[FILE_MAX];
610 BLI_strncpy(str, name, sizeof(str));
611 BLI_path_abs(str, bmain->name);
614 file = BLI_open(str, O_BINARY | O_RDONLY, 0);
619 /* ** first search an identical clip ** */
620 for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
621 BLI_strncpy(strtest, clip->name, sizeof(clip->name));
622 BLI_path_abs(strtest, G.main->name);
624 if (STREQ(strtest, str)) {
625 BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */
626 clip->id.us++; /* officially should not, it doesn't link here! */
632 /* ** add new movieclip ** */
634 /* create a short library name */
637 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
639 libname = name + len;
641 clip = movieclip_alloc(bmain, libname);
642 BLI_strncpy(clip->name, name, sizeof(clip->name));
644 detect_clip_source(clip);
646 movieclip_load_get_szie(clip);
647 if (clip->lastsize[0]) {
648 int width = clip->lastsize[0];
650 clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
653 movieclip_calc_length(clip);
658 static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
663 if (clip->flag & MCLIP_USE_PROXY) {
664 switch (user->render_size) {
665 case MCLIP_PROXY_RENDER_SIZE_25:
670 case MCLIP_PROXY_RENDER_SIZE_50:
675 case MCLIP_PROXY_RENDER_SIZE_75:
676 *width = ((float)*width) * 4.0f / 3.0f;
677 *height = ((float)*height) * 4.0f / 3.0f;
683 static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
688 undistibuf = BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
690 undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
692 IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
697 static int need_undistortion_postprocess(MovieClipUser *user)
701 /* only full undistorted render can be used as on-fly undistorting image */
702 result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
703 (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
708 static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag)
710 int result = postprocess_flag;
712 result |= need_undistortion_postprocess(user);
717 static bool check_undistortion_cache_flags(MovieClip *clip)
719 MovieClipCache *cache = clip->cache;
720 MovieTrackingCamera *camera = &clip->tracking.camera;
722 /* check for distortion model changes */
723 if (!equals_v2v2(camera->principal, cache->postprocessed.principal)) {
727 if (camera->distortion_model != cache->postprocessed.distortion_model) {
731 if (!equals_v3v3(&camera->k1, &cache->postprocessed.polynomial_k1)) {
735 if (!equals_v2v2(&camera->division_k1, &cache->postprocessed.division_k1)) {
742 static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
744 MovieClipCache *cache = clip->cache;
745 int framenr = user->framenr;
746 short proxy = IMB_PROXY_NONE;
749 if (flag & MCLIP_USE_PROXY) {
750 proxy = rendersize_to_proxy(user, flag);
751 render_flag = user->render_flag;
754 /* no cache or no cached postprocessed image */
755 if (!clip->cache || !clip->cache->postprocessed.ibuf)
758 /* postprocessing happened for other frame */
759 if (cache->postprocessed.framenr != framenr)
762 /* cached ibuf used different proxy settings */
763 if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
766 if (cache->postprocessed.flag != postprocess_flag)
769 if (need_undistortion_postprocess(user)) {
770 if (!check_undistortion_cache_flags(clip))
773 else if (cache->postprocessed.undistortion_used)
776 IMB_refImBuf(cache->postprocessed.ibuf);
778 return cache->postprocessed.ibuf;
781 static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int postprocess_flag)
783 ImBuf *postproc_ibuf = NULL;
785 if (need_undistortion_postprocess(user)) {
786 postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
789 postproc_ibuf = IMB_dupImBuf(ibuf);
792 if (postprocess_flag) {
793 bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
794 bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
795 bool disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
796 bool grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
798 if (disable_red || disable_green || disable_blue || grayscale)
799 BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
802 return postproc_ibuf;
805 static void put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
806 int flag, int postprocess_flag)
808 MovieClipCache *cache = clip->cache;
809 MovieTrackingCamera *camera = &clip->tracking.camera;
811 cache->postprocessed.framenr = user->framenr;
812 cache->postprocessed.flag = postprocess_flag;
814 if (flag & MCLIP_USE_PROXY) {
815 cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
816 cache->postprocessed.render_flag = user->render_flag;
819 cache->postprocessed.proxy = IMB_PROXY_NONE;
820 cache->postprocessed.render_flag = 0;
823 if (need_undistortion_postprocess(user)) {
824 cache->postprocessed.distortion_model = camera->distortion_model;
825 copy_v2_v2(cache->postprocessed.principal, camera->principal);
826 copy_v3_v3(&cache->postprocessed.polynomial_k1, &camera->k1);
827 copy_v2_v2(&cache->postprocessed.division_k1, &camera->division_k1);
828 cache->postprocessed.undistortion_used = true;
831 cache->postprocessed.undistortion_used = false;
836 if (cache->postprocessed.ibuf)
837 IMB_freeImBuf(cache->postprocessed.ibuf);
839 cache->postprocessed.ibuf = ibuf;
842 static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
843 int postprocess_flag, int cache_flag)
846 int framenr = user->framenr;
847 bool need_postprocess = false;
849 /* cache isn't threadsafe itself and also loading of movies
850 * can't happen from concurent threads that's why we use lock here */
851 BLI_lock_thread(LOCK_MOVIECLIP);
853 /* try to obtain cached postprocessed frame first */
854 if (need_postprocessed_frame(user, postprocess_flag)) {
855 ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
858 need_postprocess = true;
862 ibuf = get_imbuf_cache(clip, user, flag);
865 bool use_sequence = false;
867 /* undistorted proxies for movies should be read as image sequence */
868 use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
869 (user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
871 if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
872 ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
875 ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
878 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
879 put_imbuf_cache(clip, user, ibuf, flag, true);
883 clip->lastframe = framenr;
884 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
886 /* postprocess frame and put to cache if needed*/
887 if (need_postprocess) {
888 ImBuf *tmpibuf = ibuf;
889 ibuf = postprocess_frame(clip, user, tmpibuf, postprocess_flag);
890 IMB_freeImBuf(tmpibuf);
891 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
892 put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
897 BLI_unlock_thread(LOCK_MOVIECLIP);
902 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
904 return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
907 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
909 return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
912 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
914 return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
917 static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBuf *reference_ibuf,
918 int framenr, int postprocess_flag)
920 MovieClipCache *cache = clip->cache;
921 MovieTracking *tracking = &clip->tracking;
923 float tloc[2], tscale, tangle;
924 short proxy = IMB_PROXY_NONE;
926 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
928 if (clip->flag & MCLIP_USE_PROXY) {
929 proxy = rendersize_to_proxy(user, clip->flag);
930 render_flag = user->render_flag;
933 /* there's no cached frame or it was calculated for another frame */
934 if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
937 if (cache->stabilized.reference_ibuf != reference_ibuf)
940 /* cached ibuf used different proxy settings */
941 if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy)
944 if (cache->stabilized.postprocess_flag != postprocess_flag)
947 /* stabilization also depends on pixel aspect ratio */
948 if (cache->stabilized.aspect != tracking->camera.pixel_aspect)
951 if (cache->stabilized.filter != tracking->stabilization.filter)
954 stableibuf = cache->stabilized.ibuf;
956 BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
958 /* check for stabilization parameters */
959 if (tscale != cache->stabilized.scale ||
960 tangle != cache->stabilized.angle ||
961 !equals_v2v2(tloc, cache->stabilized.loc))
966 IMB_refImBuf(stableibuf);
971 static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
972 int framenr, int postprocess_flag)
974 MovieClipCache *cache = clip->cache;
975 MovieTracking *tracking = &clip->tracking;
977 float tloc[2], tscale, tangle;
978 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
980 stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle);
982 copy_v2_v2(cache->stabilized.loc, tloc);
984 cache->stabilized.reference_ibuf = ibuf;
985 cache->stabilized.scale = tscale;
986 cache->stabilized.angle = tangle;
987 cache->stabilized.framenr = framenr;
988 cache->stabilized.aspect = tracking->camera.pixel_aspect;
989 cache->stabilized.filter = tracking->stabilization.filter;
991 if (clip->flag & MCLIP_USE_PROXY) {
992 cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
993 cache->stabilized.render_flag = user->render_flag;
996 cache->stabilized.proxy = IMB_PROXY_NONE;
997 cache->stabilized.render_flag = 0;
1000 cache->stabilized.postprocess_flag = postprocess_flag;
1002 if (cache->stabilized.ibuf)
1003 IMB_freeImBuf(cache->stabilized.ibuf);
1005 cache->stabilized.ibuf = stableibuf;
1007 IMB_refImBuf(stableibuf);
1012 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle,
1013 int postprocess_flag)
1015 ImBuf *ibuf, *stableibuf = NULL;
1016 int framenr = user->framenr;
1018 ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
1023 if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
1024 MovieClipCache *cache = clip->cache;
1026 stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
1029 stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
1032 copy_v2_v2(loc, cache->stabilized.loc);
1035 *scale = cache->stabilized.scale;
1038 *angle = cache->stabilized.angle;
1053 if (stableibuf != ibuf) {
1054 IMB_freeImBuf(ibuf);
1062 bool BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
1064 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1067 IMB_freeImBuf(ibuf);
1074 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
1077 /* originally was needed to support image sequences with different image dimensions,
1078 * which might be useful for such things as reconstruction of unordered image sequence,
1079 * or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded
1080 * cache lookups and even unwanted non-proxied files loading when doing mask parenting,
1081 * so let's disable this for now and assume image sequence consists of images with
1082 * equal sizes (sergey)
1084 if (user->framenr == clip->lastframe) {
1086 if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
1087 *width = clip->lastsize[0];
1088 *height = clip->lastsize[1];
1091 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1093 if (ibuf && ibuf->x && ibuf->y) {
1094 real_ibuf_size(clip, user, ibuf, width, height);
1097 *width = clip->lastsize[0];
1098 *height = clip->lastsize[1];
1102 IMB_freeImBuf(ibuf);
1105 void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2])
1108 BKE_movieclip_get_size(clip, user, &width, &height);
1110 size[0] = (float)width;
1111 size[1] = (float)height;
1114 int BKE_movieclip_get_duration(MovieClip *clip)
1117 movieclip_calc_length(clip);
1123 void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
1128 *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
1131 /* get segments of cached frames. useful for debugging cache policies */
1132 void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *r_totseg, int **r_points)
1138 int proxy = rendersize_to_proxy(user, clip->flag);
1140 IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
1144 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
1146 /* TODO: clamp framenr here? */
1148 iuser->framenr = framenr;
1151 static void free_buffers(MovieClip *clip)
1154 IMB_moviecache_free(clip->cache->moviecache);
1156 if (clip->cache->postprocessed.ibuf)
1157 IMB_freeImBuf(clip->cache->postprocessed.ibuf);
1159 if (clip->cache->stabilized.ibuf)
1160 IMB_freeImBuf(clip->cache->stabilized.ibuf);
1162 MEM_freeN(clip->cache);
1167 IMB_free_anim(clip->anim);
1171 BKE_animdata_free((ID *) clip);
1174 void BKE_movieclip_clear_cache(MovieClip *clip)
1179 void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
1181 if (clip->cache && clip->cache->moviecache) {
1182 IMB_moviecache_cleanup(clip->cache->moviecache,
1183 moviecache_check_free_proxy,
1188 void BKE_movieclip_reload(MovieClip *clip)
1193 clip->tracking.stabilization.ok = false;
1195 /* update clip source */
1196 detect_clip_source(clip);
1198 clip->lastsize[0] = clip->lastsize[1] = 0;
1199 movieclip_load_get_szie(clip);
1201 movieclip_calc_length(clip);
1203 /* same as for image update -- don't use notifiers because they are not 100% sure to succeeded
1204 * (node trees which are not currently visible wouldn't be refreshed)
1208 for (scene = G.main->scene.first; scene; scene = scene->id.next) {
1209 if (scene->nodetree) {
1210 nodeUpdateID(scene->nodetree, &clip->id);
1216 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
1221 if (scopes->track_preview) {
1222 IMB_freeImBuf(scopes->track_preview);
1223 scopes->track_preview = NULL;
1226 if (scopes->track_search) {
1227 IMB_freeImBuf(scopes->track_search);
1228 scopes->track_search = NULL;
1231 scopes->marker = NULL;
1232 scopes->track = NULL;
1233 scopes->track_locked = true;
1236 MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
1239 MovieTrackingTrack *track = act_track;
1240 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1241 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1243 scopes->marker = marker;
1244 scopes->track = track;
1246 if (marker->flag & MARKER_DISABLED) {
1247 scopes->track_disabled = true;
1250 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1252 scopes->track_disabled = false;
1254 if (ibuf && (ibuf->rect || ibuf->rect_float)) {
1255 MovieTrackingMarker undist_marker = *marker;
1257 if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1259 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1261 BKE_movieclip_get_size(clip, user, &width, &height);
1263 undist_marker.pos[0] *= width;
1264 undist_marker.pos[1] *= height * aspy;
1266 BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos);
1268 undist_marker.pos[0] /= width;
1269 undist_marker.pos[1] /= height * aspy;
1272 scopes->track_search = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, true, true);
1274 scopes->undist_marker = undist_marker;
1276 scopes->frame_width = ibuf->x;
1277 scopes->frame_height = ibuf->y;
1279 scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
1282 IMB_freeImBuf(ibuf);
1285 if ((track->flag & TRACK_LOCKED) == 0) {
1286 float pat_min[2], pat_max[2];
1288 scopes->track_locked = false;
1290 /* XXX: would work fine with non-transformed patterns, but would likely fail
1291 * with transformed patterns, but that would be easier to debug when
1292 * we'll have real pattern sampling (at least to test) */
1293 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1295 scopes->slide_scale[0] = pat_max[0] - pat_min[0];
1296 scopes->slide_scale[1] = pat_max[1] - pat_min[1];
1301 scopes->framenr = user->framenr;
1305 static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
1307 char name[FILE_MAX];
1308 int quality, rectx, recty;
1309 int size = rendersize_to_number(proxy_render_size);
1312 get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
1314 rectx = ibuf->x * size / 100.0f;
1315 recty = ibuf->y * size / 100.0f;
1317 scaleibuf = IMB_dupImBuf(ibuf);
1320 IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
1322 IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
1324 quality = clip->proxy.quality;
1325 scaleibuf->ftype = IMB_FTYPE_JPG;
1326 scaleibuf->foptions.quality = quality;
1327 /* unsupported feature only confuses other s/w */
1328 if (scaleibuf->planes == 32)
1329 scaleibuf->planes = 24;
1331 /* TODO: currently the most weak part of multithreaded proxies,
1332 * could be solved in a way that thread only prepares memory
1333 * buffer and write to disk happens separately
1335 BLI_lock_thread(LOCK_MOVIECLIP);
1337 BLI_make_existing_file(name);
1338 if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
1341 BLI_unlock_thread(LOCK_MOVIECLIP);
1343 IMB_freeImBuf(scaleibuf);
1346 /* note: currently used by proxy job for movies, threading happens within single frame
1347 * (meaning scaling shall be threaded)
1349 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
1350 int cfra, int *build_sizes, int build_count, bool undistorted)
1358 user.framenr = cfra;
1359 user.render_flag = 0;
1360 user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1362 ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1365 ImBuf *tmpibuf = ibuf;
1369 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1371 for (i = 0; i < build_count; i++)
1372 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
1374 IMB_freeImBuf(ibuf);
1376 if (tmpibuf != ibuf)
1377 IMB_freeImBuf(tmpibuf);
1381 /* note: currently used by proxy job for sequences, threading happens within sequence
1382 * (different threads handles different frames, no threading within frame is needed)
1384 void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion,
1385 int cfra, int *build_sizes, int build_count, bool undistorted)
1391 ImBuf *tmpibuf = ibuf;
1395 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1397 for (i = 0; i < build_count; i++)
1398 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
1400 if (tmpibuf != ibuf)
1401 IMB_freeImBuf(tmpibuf);
1405 void BKE_movieclip_free(MovieClip *clip)
1409 BKE_tracking_free(&clip->tracking);
1412 void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
1420 for (scr = bmain->screen.first; scr; scr = scr->id.next) {
1421 for (area = scr->areabase.first; area; area = area->next) {
1422 for (sl = area->spacedata.first; sl; sl = sl->next) {
1423 if (sl->spacetype == SPACE_CLIP) {
1424 SpaceClip *sc = (SpaceClip *) sl;
1426 if (sc->clip == clip)
1429 else if (sl->spacetype == SPACE_VIEW3D) {
1430 View3D *v3d = (View3D *) sl;
1433 for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1434 if (bgpic->clip == clip)
1442 for (sce = bmain->scene.first; sce; sce = sce->id.next) {
1443 if (sce->clip == clip)
1447 for (ob = bmain->object.first; ob; ob = ob->id.next) {
1450 for (con = ob->constraints.first; con; con = con->next) {
1451 if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
1452 bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
1454 if (data->clip == clip)
1457 else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
1458 bCameraSolverConstraint *data = (bCameraSolverConstraint *) con->data;
1460 if (data->clip == clip)
1463 else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
1464 bObjectSolverConstraint *data = (bObjectSolverConstraint *) con->data;
1466 if (data->clip == clip)
1472 FOREACH_NODETREE(bmain, ntree, id) {
1473 BKE_node_tree_unlink_id((ID *)clip, ntree);
1474 } FOREACH_NODETREE_END
1479 float BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, float framenr)
1481 return framenr - (float) clip->start_frame + 1.0f;
1484 float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr)
1486 return framenr + (float) clip->start_frame - 1.0f;
1489 void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char *name)
1491 if (clip->source == MCLIP_SRC_SEQUENCE) {
1494 use_proxy = (clip->flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
1497 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1498 get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
1501 get_sequence_fname(clip, user->framenr, name);
1505 BLI_strncpy(name, clip->name, FILE_MAX);
1506 BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
1510 ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
1514 if (clip->source == MCLIP_SRC_MOVIE) {
1515 BLI_lock_thread(LOCK_MOVIECLIP);
1516 ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
1517 BLI_unlock_thread(LOCK_MOVIECLIP);
1523 bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
1525 bool has_frame = false;
1527 BLI_lock_thread(LOCK_MOVIECLIP);
1528 has_frame = has_imbuf_cache(clip, user, clip->flag);
1529 BLI_unlock_thread(LOCK_MOVIECLIP);
1534 bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf)
1538 BLI_lock_thread(LOCK_MOVIECLIP);
1539 result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
1540 BLI_unlock_thread(LOCK_MOVIECLIP);