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
49
#include "MEM_guardedalloc.h"
51
#include "DNA_constraint_types.h"
52
#include "DNA_screen_types.h"
53
#include "DNA_space_types.h"
54
#include "DNA_movieclip_types.h"
55
#include "DNA_object_types.h"
56
#include "DNA_scene_types.h"
57
#include "DNA_view3d_types.h"
59
#include "BLI_utildefines.h"
61
#include "BLI_blenlib.h"
62
#include "BLI_ghash.h"
64
#include "BLI_mempool.h"
65
#include "BLI_threads.h"
67
#include "BKE_animsys.h"
68
#include "BKE_constraint.h"
69
#include "BKE_library.h"
70
#include "BKE_global.h"
72
#include "BKE_utildefines.h"
73
#include "BKE_movieclip.h"
74
#include "BKE_image.h" /* openanim */
75
#include "BKE_tracking.h"
77
#include "IMB_imbuf_types.h"
78
#include "IMB_imbuf.h"
79
#include "IMB_moviecache.h"
81
/*********************** movieclip buffer loaders *************************/
83
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
85
char num[FILE_MAX] = {0};
87
BLI_strncpy(num, full_name + head_len, numlen + 1);
92
static int rendersize_to_proxy(MovieClipUser *user, int flag)
94
if ((flag & MCLIP_USE_PROXY) == 0)
95
return IMB_PROXY_NONE;
97
switch (user->render_size) {
98
case MCLIP_PROXY_RENDER_SIZE_25:
101
case MCLIP_PROXY_RENDER_SIZE_50:
104
case MCLIP_PROXY_RENDER_SIZE_75:
107
case MCLIP_PROXY_RENDER_SIZE_100:
108
return IMB_PROXY_100;
110
case MCLIP_PROXY_RENDER_SIZE_FULL:
111
return IMB_PROXY_NONE;
114
return IMB_PROXY_NONE;
117
static int rendersize_to_number(int render_size)
119
switch (render_size) {
120
case MCLIP_PROXY_RENDER_SIZE_25:
123
case MCLIP_PROXY_RENDER_SIZE_50:
126
case MCLIP_PROXY_RENDER_SIZE_75:
129
case MCLIP_PROXY_RENDER_SIZE_100:
132
case MCLIP_PROXY_RENDER_SIZE_FULL:
139
static int get_timecode(MovieClip *clip, int flag)
141
if ((flag & MCLIP_USE_PROXY) == 0)
144
return clip->proxy.tc;
147
static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
149
unsigned short numlen;
150
char head[FILE_MAX], tail[FILE_MAX];
153
BLI_strncpy(name, clip->name, sizeof(clip->name));
154
BLI_stringdec(name, head, tail, &numlen);
156
/* movieclips always points to first image from sequence,
157
* 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 - 1);
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, int 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];
174
BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
176
if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
177
BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
180
BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
184
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, framenr);
186
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, framenr);
188
BLI_path_abs(name, G.main->name);
189
BLI_path_frame(name, 1, 0);
191
strcat(name, ".jpg");
194
static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
198
int loadflag, use_proxy= 0;
200
use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
202
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
203
get_proxy_fname(clip, user->render_size, undistort, framenr, name);
206
get_sequence_fname(clip, framenr, name);
208
loadflag = IB_rect|IB_multilayer;
211
ibuf = IMB_loadiffname(name, loadflag);
216
static void movieclip_open_anim_file(MovieClip *clip)
221
BLI_strncpy(str, clip->name, FILE_MAX);
222
BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
224
/* FIXME: make several stream accessible in image editor, too */
225
clip->anim = openanim(str, IB_rect, 0);
228
if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
230
BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
231
BLI_path_abs(dir, G.main->name);
232
IMB_anim_set_index_dir(clip->anim, dir);
238
static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
241
int tc = get_timecode(clip, flag);
242
int proxy = rendersize_to_proxy(user, flag);
244
movieclip_open_anim_file(clip);
250
dur = IMB_anim_get_duration(clip->anim, tc);
259
ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
265
static void movieclip_calc_length(MovieClip *clip)
267
if (clip->source == MCLIP_SRC_MOVIE) {
268
movieclip_open_anim_file(clip);
271
clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
274
else if (clip->source == MCLIP_SRC_SEQUENCE) {
276
unsigned short numlen;
277
char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
279
BLI_stringdec(clip->name, head, tail, &numlen);
282
/* there's no number group in file name, assume it's single framed sequence */
283
clip->len = framenr + 1;
287
get_sequence_fname(clip, framenr, name);
289
if (!BLI_exists(name)) {
290
clip->len = framenr + 1;
300
/*********************** image buffer cache *************************/
302
typedef struct MovieClipCache {
303
/* regular movie cache */
304
struct MovieCache *moviecache;
306
/* cached postprocessed shot */
312
/* cache for undistorted shot */
315
short undistoriton_used;
321
/* cache for stable shot */
325
int postprocess_flag;
327
float loc[2], scale, angle, aspect;
333
typedef struct MovieClipImBufCacheKey {
337
} MovieClipImBufCacheKey;
339
static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
341
MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey*)userkey;
343
*framenr = key->framenr;
345
*render_flags = key->render_flag;
348
static unsigned int moviecache_hashhash(const void *keyv)
350
MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey*)keyv;
351
int rval = key->framenr;
356
static int moviecache_hashcmp(const void *av, const void *bv)
358
const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey*)av;
359
const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey*)bv;
361
if (a->framenr < b->framenr)
363
else if (a->framenr > b->framenr)
366
if (a->proxy < b->proxy)
368
else if (a->proxy > b->proxy)
371
if (a->render_flag < b->render_flag)
373
else if (a->render_flag > b->render_flag)
379
static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
382
MovieClipImBufCacheKey key;
384
key.framenr = user->framenr;
386
if (flag & MCLIP_USE_PROXY) {
387
key.proxy = rendersize_to_proxy(user, flag);
388
key.render_flag = user->render_flag;
391
key.proxy = IMB_PROXY_NONE;
395
return IMB_moviecache_get(clip->cache->moviecache, &key);
401
static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag)
403
MovieClipImBufCacheKey key;
406
clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
408
clip->cache->moviecache = IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash,
409
moviecache_hashcmp, moviecache_keydata);
412
key.framenr = user->framenr;
414
if (flag & MCLIP_USE_PROXY) {
415
key.proxy = rendersize_to_proxy(user, flag);
416
key.render_flag = user->render_flag;
419
key.proxy = IMB_PROXY_NONE;
423
IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
426
/*********************** common functions *************************/
428
/* only image block itself */
429
static MovieClip *movieclip_alloc(const char *name)
433
clip = alloc_libblock(&G.main->movieclip, ID_MC, name);
435
clip->aspx = clip->aspy= 1.0f;
437
BKE_tracking_init_settings(&clip->tracking);
439
clip->proxy.build_size_flag = IMB_PROXY_25;
440
clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
442
IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
443
IMB_TC_RECORD_RUN_NO_GAPS;
444
clip->proxy.quality = 90;
449
/* checks if image was already loaded, then returns same image
450
* otherwise creates new.
451
* does not load ibuf itself
452
* pass on optional frame for #name images */
453
MovieClip *BKE_add_movieclip_file(const char *name)
457
int file, len, width, height;
459
char str[FILE_MAX], strtest[FILE_MAX];
461
BLI_strncpy(str, name, sizeof(str));
462
BLI_path_abs(str, G.main->name);
465
file = BLI_open(str, O_BINARY|O_RDONLY,0);
470
/* ** first search an identical clip ** */
471
for (clip = G.main->movieclip.first; clip; clip = clip->id.next) {
472
BLI_strncpy(strtest, clip->name, sizeof(clip->name));
473
BLI_path_abs(strtest, G.main->name);
475
if (strcmp(strtest, str) == 0) {
476
BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */
477
clip->id.us++; /* officially should not, it doesn't link here! */
483
/* ** add new movieclip ** */
485
/* create a short library name */
488
while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
490
libname = name + len;
492
clip = movieclip_alloc(libname);
493
BLI_strncpy(clip->name, name, sizeof(clip->name));
495
if (BLI_testextensie_array(name, imb_ext_movie))
496
clip->source = MCLIP_SRC_MOVIE;
498
clip->source = MCLIP_SRC_SEQUENCE;
501
BKE_movieclip_get_size(clip, &user, &width, &height);
502
if (width && height) {
503
clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
504
clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
506
clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
509
movieclip_calc_length(clip);
514
static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
519
if (clip->flag & MCLIP_USE_PROXY) {
520
switch(user->render_size) {
521
case MCLIP_PROXY_RENDER_SIZE_25:
526
case MCLIP_PROXY_RENDER_SIZE_50:
531
case MCLIP_PROXY_RENDER_SIZE_75:
532
*width = ((float)*width)*4.0f/3.0f;
533
*height = ((float)*height)*4.0f/3.0f;
539
static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
543
/* XXX: because of #27997 do not use float buffers to undistort,
544
* otherwise, undistorted proxy can be darker than it should */
545
imb_freerectfloatImBuf(ibuf);
548
undistibuf = BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
550
undistibuf = BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
552
if (undistibuf->userflags & IB_RECT_INVALID) {
553
ibuf->userflags &= ~IB_RECT_INVALID;
554
IMB_rect_from_float(undistibuf);
557
IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
562
static int need_undistortion_postprocess(MovieClipUser *user, int flag)
566
/* only full undistorted render can be used as on-fly undistorting image */
567
if (flag & MCLIP_USE_PROXY) {
568
result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
569
(user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
575
static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag)
577
int result = postprocess_flag;
579
result |= need_undistortion_postprocess(user, flag);
584
static int check_undistortion_cache_flags(MovieClip *clip)
586
MovieClipCache *cache = clip->cache;
587
MovieTrackingCamera *camera = &clip->tracking.camera;
589
/* check for distortion model changes */
590
if (!equals_v2v2(camera->principal, cache->postprocessed.principal))
593
if (!equals_v3v3(&camera->k1, &cache->postprocessed.k1))
599
static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
601
MovieClipCache *cache = clip->cache;
602
int framenr = user->framenr;
603
short proxy = IMB_PROXY_NONE;
606
if (flag & MCLIP_USE_PROXY) {
607
proxy = rendersize_to_proxy(user, flag);
608
render_flag = user->render_flag;
611
/* no cache or no cached postprocessed image */
612
if (!clip->cache || !clip->cache->postprocessed.ibuf)
615
/* postprocessing happened for other frame */
616
if (cache->postprocessed.framenr != framenr)
619
/* cached ibuf used different proxy settings */
620
if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
623
if (cache->postprocessed.flag != postprocess_flag)
626
if (need_undistortion_postprocess(user, flag)) {
627
if (!check_undistortion_cache_flags(clip))
630
else if (cache->postprocessed.undistoriton_used)
633
IMB_refImBuf(cache->postprocessed.ibuf);
635
return cache->postprocessed.ibuf;
638
static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
640
MovieClipCache *cache = clip->cache;
641
MovieTrackingCamera *camera = &clip->tracking.camera;
642
ImBuf *postproc_ibuf = NULL;
644
if (cache->postprocessed.ibuf)
645
IMB_freeImBuf(cache->postprocessed.ibuf);
647
cache->postprocessed.framenr = user->framenr;
648
cache->postprocessed.flag = postprocess_flag;
650
if (flag & MCLIP_USE_PROXY) {
651
cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
652
cache->postprocessed.render_flag = user->render_flag;
655
cache->postprocessed.proxy = IMB_PROXY_NONE;
656
cache->postprocessed.render_flag = 0;
659
if (need_undistortion_postprocess(user, flag)) {
660
copy_v2_v2(cache->postprocessed.principal, camera->principal);
661
copy_v3_v3(&cache->postprocessed.k1, &camera->k1);
662
cache->postprocessed.undistoriton_used = TRUE;
663
postproc_ibuf= get_undistorted_ibuf(clip, NULL, ibuf);
666
cache->postprocessed.undistoriton_used = FALSE;
669
if (postprocess_flag) {
670
int disable_red = postprocess_flag & MOVIECLIP_DISABLE_RED,
671
disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN,
672
disable_blue = postprocess_flag & MOVIECLIP_DISABLE_BLUE,
673
grayscale = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE;
676
postproc_ibuf = IMB_dupImBuf(ibuf);
678
if (disable_red || disable_green || disable_blue || grayscale)
679
BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
682
IMB_refImBuf(postproc_ibuf);
684
cache->postprocessed.ibuf = postproc_ibuf;
686
if (cache->stabilized.ibuf) {
687
/* force stable buffer be re-calculated */
688
IMB_freeImBuf(cache->stabilized.ibuf);
689
cache->stabilized.ibuf = NULL;
692
return postproc_ibuf;
695
static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
696
int postprocess_flag, int cache_flag)
699
int framenr = user->framenr, need_postprocess = FALSE;
701
/* cache isn't threadsafe itself and also loading of movies
702
* can't happen from concurent threads that's why we use lock here */
703
BLI_lock_thread(LOCK_MOVIECLIP);
705
/* try to obtain cached postprocessed frame first */
706
if (need_postprocessed_frame(user, flag, postprocess_flag)) {
707
ibuf= get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
710
need_postprocess = TRUE;
714
ibuf= get_imbuf_cache(clip, user, flag);
717
int use_sequence = FALSE;
719
/* undistorted proxies for movies should be read as image sequence */
720
use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
721
(user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
723
if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
724
ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
727
ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
730
if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
731
put_imbuf_cache(clip, user, ibuf, flag);
735
clip->lastframe = framenr;
736
real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
738
/* postprocess frame and put to cache */
739
if (need_postprocess) {
740
ImBuf *tmpibuf = ibuf;
741
ibuf = put_postprocessed_frame_to_cache(clip, user, tmpibuf, flag, postprocess_flag);
742
IMB_freeImBuf(tmpibuf);
746
BLI_unlock_thread(LOCK_MOVIECLIP);
751
ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
753
return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
756
ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
758
return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
761
ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
763
return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
766
static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int framenr, int postprocess_flag)
768
MovieClipCache *cache = clip->cache;
769
MovieTracking *tracking = &clip->tracking;
771
float tloc[2], tscale, tangle;
772
short proxy = IMB_PROXY_NONE;
775
if (clip->flag & MCLIP_USE_PROXY) {
776
proxy = rendersize_to_proxy(user, clip->flag);
777
render_flag = user->render_flag;
780
/* there's no cached frame or it was calculated for another frame */
781
if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
784
/* cached ibuf used different proxy settings */
785
if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy)
788
if (cache->stabilized.postprocess_flag != postprocess_flag)
791
/* stabilization also depends on pixel aspect ratio */
792
if (cache->stabilized.aspect != tracking->camera.pixel_aspect)
795
if (cache->stabilized.filter != tracking->stabilization.filter)
798
stableibuf = cache->stabilized.ibuf;
800
BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
802
/* check for stabilization parameters */
803
if (tscale != cache->stabilized.scale ||
804
tangle != cache->stabilized.angle ||
805
!equals_v2v2(tloc, cache->stabilized.loc))
810
IMB_refImBuf(stableibuf);
815
static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
816
int framenr, int postprocess_flag)
818
MovieClipCache *cache = clip->cache;
819
MovieTracking *tracking = &clip->tracking;
821
float tloc[2], tscale, tangle;
823
if (cache->stabilized.ibuf)
824
IMB_freeImBuf(cache->stabilized.ibuf);
826
stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle);
828
cache->stabilized.ibuf= stableibuf;
830
copy_v2_v2(cache->stabilized.loc, tloc);
832
cache->stabilized.scale = tscale;
833
cache->stabilized.angle = tangle;
834
cache->stabilized.framenr = framenr;
835
cache->stabilized.aspect = tracking->camera.pixel_aspect;
836
cache->stabilized.filter = tracking->stabilization.filter;
838
if (clip->flag & MCLIP_USE_PROXY) {
839
cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
840
cache->stabilized.render_flag = user->render_flag;
843
cache->stabilized.proxy = IMB_PROXY_NONE;
844
cache->stabilized.render_flag = 0;
847
cache->stabilized.postprocess_flag = postprocess_flag;
849
IMB_refImBuf(stableibuf);
854
ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag)
856
ImBuf *ibuf, *stableibuf = NULL;
857
int framenr = user->framenr;
859
ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
864
if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
865
MovieClipCache *cache= clip->cache;
867
stableibuf = get_stable_cached_frame(clip, user, framenr, postprocess_flag);
870
stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
873
copy_v2_v2(loc, cache->stabilized.loc);
876
*scale= cache->stabilized.scale;
879
*angle= cache->stabilized.angle;
894
if (stableibuf != ibuf) {
903
int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
905
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
915
void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
917
if (user->framenr == clip->lastframe) {
918
*width = clip->lastsize[0];
919
*height = clip->lastsize[1];
922
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
924
if (ibuf && ibuf->x && ibuf->y) {
925
real_ibuf_size(clip, user, ibuf, width, height);
937
int BKE_movieclip_get_duration(MovieClip *clip)
940
movieclip_calc_length(clip);
946
void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy)
951
*aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
954
/* get segments of cached frames. useful for debugging cache policies */
955
void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
961
int proxy = rendersize_to_proxy(user, clip->flag);
963
IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
967
void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
969
/* TODO: clamp framenr here? */
971
iuser->framenr = framenr;
974
static void free_buffers(MovieClip *clip)
977
IMB_moviecache_free(clip->cache->moviecache);
979
if (clip->cache->postprocessed.ibuf)
980
IMB_freeImBuf(clip->cache->postprocessed.ibuf);
982
if (clip->cache->stabilized.ibuf)
983
IMB_freeImBuf(clip->cache->stabilized.ibuf);
985
MEM_freeN(clip->cache);
990
IMB_free_anim(clip->anim);
994
BKE_free_animdata((ID *) clip);
997
void BKE_movieclip_reload(MovieClip *clip)
1002
clip->tracking.stabilization.ok = FALSE;
1004
/* update clip source */
1005
if (BLI_testextensie_array(clip->name, imb_ext_movie))
1006
clip->source = MCLIP_SRC_MOVIE;
1008
clip->source = MCLIP_SRC_SEQUENCE;
1010
movieclip_calc_length(clip);
1013
void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
1018
if (scopes->track_preview) {
1019
IMB_freeImBuf(scopes->track_preview);
1020
scopes->track_preview = NULL;
1023
scopes->marker = NULL;
1024
scopes->track = NULL;
1027
MovieTrackingTrack *act_track = BKE_tracking_active_track(&clip->tracking);
1030
MovieTrackingTrack *track = act_track;
1031
MovieTrackingMarker *marker = BKE_tracking_get_marker(track, user->framenr);
1033
if (marker->flag & MARKER_DISABLED) {
1034
scopes->track_disabled = TRUE;
1037
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1039
scopes->track_disabled = FALSE;
1041
if (ibuf && (ibuf->rect || ibuf->rect_float)) {
1043
MovieTrackingMarker undist_marker = *marker;
1045
if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1047
float aspy= 1.0f / clip->tracking.camera.pixel_aspect;
1049
BKE_movieclip_get_size(clip, user, &width, &height);
1051
undist_marker.pos[0] *= width;
1052
undist_marker.pos[1] *= height*aspy;
1054
BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos);
1056
undist_marker.pos[0] /= width;
1057
undist_marker.pos[1] /= height*aspy;
1060
/* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */
1061
tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */,
1062
1 /* anchor */, scopes->track_pos, NULL);
1064
if (tmpibuf->rect_float)
1065
IMB_rect_from_float(tmpibuf);
1068
scopes->track_preview= tmpibuf;
1070
IMB_freeImBuf(tmpibuf);
1073
IMB_freeImBuf(ibuf);
1076
if ((track->flag & TRACK_LOCKED)==0) {
1077
scopes->marker = marker;
1078
scopes->track = track;
1079
scopes->slide_scale[0] = track->pat_max[0]-track->pat_min[0];
1080
scopes->slide_scale[1] = track->pat_max[1]-track->pat_min[1];
1085
scopes->framenr = user->framenr;
1089
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
1091
char name[FILE_MAX];
1092
int quality, rectx, recty;
1093
int size = rendersize_to_number(proxy_render_size);
1096
get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
1098
rectx = ibuf->x * size / 100.0f;
1099
recty = ibuf->y * size / 100.0f;
1101
scaleibuf = IMB_dupImBuf(ibuf);
1103
IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
1105
quality = clip->proxy.quality;
1106
scaleibuf->ftype = JPG | quality;
1108
/* unsupported feature only confuses other s/w */
1109
if (scaleibuf->planes == 32)
1110
scaleibuf->planes = 24;
1112
BLI_lock_thread(LOCK_MOVIECLIP);
1114
BLI_make_existing_file(name);
1115
if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
1118
BLI_unlock_thread(LOCK_MOVIECLIP);
1120
IMB_freeImBuf(scaleibuf);
1123
void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
1124
int cfra, int *build_sizes, int build_count, int undistorted)
1129
user.framenr = cfra;
1130
user.render_flag = 0;
1131
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1133
ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1136
ImBuf *tmpibuf = ibuf;
1140
tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1142
for (i = 0; i < build_count; i++)
1143
movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
1145
IMB_freeImBuf(ibuf);
1147
if (tmpibuf != ibuf)
1148
IMB_freeImBuf(tmpibuf);
1152
void free_movieclip(MovieClip *clip)
1156
BKE_tracking_free(&clip->tracking);
1159
void unlink_movieclip(Main *bmain, MovieClip *clip)
1167
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
1168
for (area = scr->areabase.first; area; area = area->next) {
1169
for (sl = area->spacedata.first; sl; sl = sl->next) {
1170
if (sl->spacetype == SPACE_CLIP) {
1171
SpaceClip *sc = (SpaceClip *) sl;
1173
if (sc->clip == clip)
1176
else if (sl->spacetype == SPACE_VIEW3D) {
1177
View3D *v3d = (View3D *) sl;
1180
for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1181
if (bgpic->clip == clip)
1189
for (sce = bmain->scene.first; sce; sce = sce->id.next) {
1190
if (sce->clip == clip)
1194
for (ob = bmain->object.first; ob; ob = ob->id.next) {
1197
for (con = ob->constraints.first; con; con = con->next) {
1198
bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
1200
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
1201
bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
1203
if (data->clip == clip)
1206
else if (cti->type == CONSTRAINT_TYPE_CAMERASOLVER) {
1207
bCameraSolverConstraint *data = (bCameraSolverConstraint *) con->data;
1209
if (data->clip == clip)
1212
else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
1213
bObjectSolverConstraint *data = (bObjectSolverConstraint *) con->data;
1215
if (data->clip == clip)