ed92c942b57e4dfab20d804ffb88bce4b4c85982
[blender.git] / source / blender / blenkernel / intern / movieclip.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenkernel/intern/movieclip.c
28  *  \ingroup bke
29  */
30
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <fcntl.h>
35
36 #ifndef WIN32
37 #  include <unistd.h>
38 #else
39 #  include <io.h>
40 #endif
41
42 #include <time.h>
43
44 #include "MEM_guardedalloc.h"
45
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"
54
55 #include "BLI_utildefines.h"
56
57 #include "BLI_blenlib.h"
58 #include "BLI_ghash.h"
59 #include "BLI_math.h"
60 #include "BLI_threads.h"
61
62 #include "BKE_animsys.h"
63 #include "BKE_colortools.h"
64 #include "BKE_library.h"
65 #include "BKE_global.h"
66 #include "BKE_main.h"
67 #include "BKE_movieclip.h"
68 #include "BKE_node.h"
69 #include "BKE_image.h"  /* openanim */
70 #include "BKE_tracking.h"
71
72 #include "IMB_imbuf_types.h"
73 #include "IMB_imbuf.h"
74 #include "IMB_moviecache.h"
75
76 #ifdef WITH_OPENEXR
77 #  include "intern/openexr/openexr_multi.h"
78 #endif
79
80 /*********************** movieclip buffer loaders *************************/
81
82 static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
83 {
84         char num[FILE_MAX] = {0};
85
86         BLI_strncpy(num, full_name + head_len, numlen + 1);
87
88         return atoi(num);
89 }
90
91 static int rendersize_to_proxy(MovieClipUser *user, int flag)
92 {
93         if ((flag & MCLIP_USE_PROXY) == 0)
94                 return IMB_PROXY_NONE;
95
96         switch (user->render_size) {
97                 case MCLIP_PROXY_RENDER_SIZE_25:
98                         return IMB_PROXY_25;
99
100                 case MCLIP_PROXY_RENDER_SIZE_50:
101                         return IMB_PROXY_50;
102
103                 case MCLIP_PROXY_RENDER_SIZE_75:
104                         return IMB_PROXY_75;
105
106                 case MCLIP_PROXY_RENDER_SIZE_100:
107                         return IMB_PROXY_100;
108
109                 case MCLIP_PROXY_RENDER_SIZE_FULL:
110                         return IMB_PROXY_NONE;
111         }
112
113         return IMB_PROXY_NONE;
114 }
115
116 static int rendersize_to_number(int render_size)
117 {
118         switch (render_size) {
119                 case MCLIP_PROXY_RENDER_SIZE_25:
120                         return 25;
121
122                 case MCLIP_PROXY_RENDER_SIZE_50:
123                         return 50;
124
125                 case MCLIP_PROXY_RENDER_SIZE_75:
126                         return 75;
127
128                 case MCLIP_PROXY_RENDER_SIZE_100:
129                         return 100;
130
131                 case MCLIP_PROXY_RENDER_SIZE_FULL:
132                         return 100;
133         }
134
135         return 100;
136 }
137
138 static int get_timecode(MovieClip *clip, int flag)
139 {
140         if ((flag & MCLIP_USE_PROXY) == 0)
141                 return IMB_TC_NONE;
142
143         return clip->proxy.tc;
144 }
145
146 static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
147 {
148         unsigned short numlen;
149         char head[FILE_MAX], tail[FILE_MAX];
150         int offset;
151
152         BLI_strncpy(name, clip->name, sizeof(clip->name));
153         BLI_stringdec(name, head, tail, &numlen);
154
155         /* movieclips always points to first image from sequence,
156          * autoguess offset for now. could be something smarter in the future
157          */
158         offset = sequence_guess_offset(clip->name, strlen(head), numlen);
159
160         if (numlen)
161                 BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
162         else
163                 BLI_strncpy(name, clip->name, sizeof(clip->name));
164
165         BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
166 }
167
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)
170 {
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;
174
175         BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
176
177         if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
178                 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
179         }
180         else {
181                 BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
182         }
183
184         if (undistorted)
185                 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
186         else
187                 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
188
189         BLI_path_abs(name, G.main->name);
190         BLI_path_frame(name, 1, 0);
191
192         strcat(name, ".jpg");
193 }
194
195 static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
196 {
197         struct ImBuf *ibuf;
198         char name[FILE_MAX];
199         int loadflag;
200         bool use_proxy = false;
201         char *colorspace;
202
203         use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
204         if (use_proxy) {
205                 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
206                 get_proxy_fname(clip, user->render_size, undistort, framenr, name);
207
208                 /* Well, this is a bit weird, but proxies for movie sources
209                  * are built in the same exact color space as the input,
210                  *
211                  * But image sequences are built in the display space.
212                  */
213                 if (clip->source == MCLIP_SRC_MOVIE) {
214                         colorspace = clip->colorspace_settings.name;
215                 }
216                 else {
217                         colorspace = NULL;
218                 }
219         }
220         else {
221                 get_sequence_fname(clip, framenr, name);
222                 colorspace = clip->colorspace_settings.name;
223         }
224
225         loadflag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
226
227         /* read ibuf */
228         ibuf = IMB_loadiffname(name, loadflag, colorspace);
229
230 #ifdef WITH_OPENEXR
231         if (ibuf) {
232                 if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
233                         IMB_exr_close(ibuf->userdata);
234                         ibuf->userdata = NULL;
235                 }
236         }
237 #endif
238
239         return ibuf;
240 }
241
242 static void movieclip_open_anim_file(MovieClip *clip)
243 {
244         char str[FILE_MAX];
245
246         if (!clip->anim) {
247                 BLI_strncpy(str, clip->name, FILE_MAX);
248                 BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
249
250                 /* FIXME: make several stream accessible in image editor, too */
251                 clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name);
252
253                 if (clip->anim) {
254                         if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
255                                 char dir[FILE_MAX];
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);
259                         }
260                 }
261         }
262 }
263
264 static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
265 {
266         ImBuf *ibuf = NULL;
267         int tc = get_timecode(clip, flag);
268         int proxy = rendersize_to_proxy(user, flag);
269
270         movieclip_open_anim_file(clip);
271
272         if (clip->anim) {
273                 int fra = framenr - clip->start_frame + clip->frame_offset;
274
275                 ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
276         }
277
278         return ibuf;
279 }
280
281 static void movieclip_calc_length(MovieClip *clip)
282 {
283         if (clip->source == MCLIP_SRC_MOVIE) {
284                 movieclip_open_anim_file(clip);
285
286                 if (clip->anim) {
287                         clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
288                 }
289         }
290         else if (clip->source == MCLIP_SRC_SEQUENCE) {
291                 unsigned short numlen;
292                 char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
293
294                 BLI_stringdec(clip->name, head, tail, &numlen);
295
296                 if (numlen == 0) {
297                         /* there's no number group in file name, assume it's single framed sequence */
298                         clip->len = 1;
299                 }
300                 else {
301                         clip->len = 0;
302                         for (;;) {
303                                 get_sequence_fname(clip, clip->len + clip->start_frame, name);
304
305                                 if (BLI_exists(name))
306                                         clip->len++;
307                                 else
308                                         break;
309                         }
310                 }
311         }
312 }
313
314 /*********************** image buffer cache *************************/
315
316 typedef struct MovieClipCache {
317         /* regular movie cache */
318         struct MovieCache *moviecache;
319
320         /* cached postprocessed shot */
321         struct {
322                 ImBuf *ibuf;
323                 int framenr;
324                 int flag;
325
326                 /* cache for undistorted shot */
327                 float principal[2];
328                 float polynomial_k1, polynomial_k2, polynomial_k3;
329                 float division_k1, division_k2;
330                 short distortion_model;
331                 bool undistortion_used;
332
333                 int proxy;
334                 short render_flag;
335         } postprocessed;
336
337         /* cache for stable shot */
338         struct {
339                 ImBuf *reference_ibuf;
340
341                 ImBuf *ibuf;
342                 int framenr;
343                 int postprocess_flag;
344
345                 float loc[2], scale, angle, aspect;
346                 int proxy, filter;
347                 short render_flag;
348         } stabilized;
349
350         int sequence_offset;
351 } MovieClipCache;
352
353 typedef struct MovieClipImBufCacheKey {
354         int framenr;
355         int proxy;
356         short render_flag;
357 } MovieClipImBufCacheKey;
358
359 typedef struct MovieClipCachePriorityData {
360         int framenr;
361 } MovieClipCachePriorityData;
362
363 static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
364 {
365         int index;
366
367         index = framenr - clip->start_frame + clip->frame_offset;
368
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];
373
374                         BLI_stringdec(clip->name, head, tail, &numlen);
375
376                         /* see comment in get_sequence_fname */
377                         clip->cache->sequence_offset = sequence_guess_offset(clip->name, strlen(head), numlen);
378                 }
379
380                 index += clip->cache->sequence_offset;
381         }
382
383         if (index < 0)
384                 return framenr - index;
385
386         return framenr;
387 }
388
389 static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
390 {
391         const MovieClipImBufCacheKey *key = userkey;
392
393         *framenr = key->framenr;
394         *proxy = key->proxy;
395         *render_flags = key->render_flag;
396 }
397
398 static unsigned int moviecache_hashhash(const void *keyv)
399 {
400         const MovieClipImBufCacheKey *key = keyv;
401         int rval = key->framenr;
402
403         return rval;
404 }
405
406 static bool moviecache_hashcmp(const void *av, const void *bv)
407 {
408         const MovieClipImBufCacheKey *a = av;
409         const MovieClipImBufCacheKey *b = bv;
410
411         return ((a->framenr != b->framenr) ||
412                 (a->proxy != b->proxy) ||
413                 (a->render_flag != b->render_flag));
414 }
415
416 static void *moviecache_getprioritydata(void *key_v)
417 {
418         MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *) key_v;
419         MovieClipCachePriorityData *priority_data;
420
421         priority_data = MEM_callocN(sizeof(*priority_data), "movie cache clip priority data");
422         priority_data->framenr = key->framenr;
423
424         return priority_data;
425 }
426
427 static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
428 {
429         MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *) last_userkey_v;
430         MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
431
432         return -abs(last_userkey->framenr - priority_data->framenr);
433 }
434
435 static void moviecache_prioritydeleter(void *priority_data_v)
436 {
437         MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v;
438
439         MEM_freeN(priority_data);
440 }
441
442 static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
443 {
444         if (clip->cache) {
445                 MovieClipImBufCacheKey key;
446
447                 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
448
449                 if (flag & MCLIP_USE_PROXY) {
450                         key.proxy = rendersize_to_proxy(user, flag);
451                         key.render_flag = user->render_flag;
452                 }
453                 else {
454                         key.proxy = IMB_PROXY_NONE;
455                         key.render_flag = 0;
456                 }
457
458                 return IMB_moviecache_get(clip->cache->moviecache, &key);
459         }
460
461         return NULL;
462 }
463
464 static bool has_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
465 {
466         if (clip->cache) {
467                 MovieClipImBufCacheKey key;
468
469                 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
470
471                 if (flag & MCLIP_USE_PROXY) {
472                         key.proxy = rendersize_to_proxy(user, flag);
473                         key.render_flag = user->render_flag;
474                 }
475                 else {
476                         key.proxy = IMB_PROXY_NONE;
477                         key.render_flag = 0;
478                 }
479
480                 return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
481         }
482
483         return false;
484 }
485
486 static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
487 {
488         MovieClipImBufCacheKey key;
489
490         if (!clip->cache) {
491                 struct MovieCache *moviecache;
492
493                 // char cache_name[64];
494                 // BLI_snprintf(cache_name, sizeof(cache_name), "movie %s", clip->id.name);
495
496                 clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
497
498                 moviecache = IMB_moviecache_create("movieclip", sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
499
500                 IMB_moviecache_set_getdata_callback(moviecache, moviecache_keydata);
501                 IMB_moviecache_set_priority_callback(moviecache, moviecache_getprioritydata, moviecache_getitempriority,
502                                                      moviecache_prioritydeleter);
503
504                 clip->cache->moviecache = moviecache;
505                 clip->cache->sequence_offset = -1;
506         }
507
508         key.framenr = user_frame_to_cache_frame(clip, user->framenr);
509
510         if (flag & MCLIP_USE_PROXY) {
511                 key.proxy = rendersize_to_proxy(user, flag);
512                 key.render_flag = user->render_flag;
513         }
514         else {
515                 key.proxy = IMB_PROXY_NONE;
516                 key.render_flag = 0;
517         }
518
519         if (destructive) {
520                 IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
521                 return true;
522         }
523         else {
524                 return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
525         }
526 }
527
528 static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf),
529                                         void *userkey,
530                                         void *UNUSED(userdata))
531 {
532         MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
533
534         return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
535 }
536
537 /*********************** common functions *************************/
538
539 /* only image block itself */
540 static MovieClip *movieclip_alloc(Main *bmain, const char *name)
541 {
542         MovieClip *clip;
543
544         clip = BKE_libblock_alloc(bmain, ID_MC, name);
545
546         clip->aspx = clip->aspy = 1.0f;
547
548         BKE_tracking_settings_init(&clip->tracking);
549         BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings);
550
551         clip->proxy.build_size_flag = IMB_PROXY_25;
552         clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
553                                     IMB_TC_FREE_RUN |
554                                     IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
555                                     IMB_TC_RECORD_RUN_NO_GAPS;
556         clip->proxy.quality = 90;
557
558         clip->start_frame = 1;
559         clip->frame_offset = 0;
560
561         return clip;
562 }
563
564 static void movieclip_load_get_szie(MovieClip *clip)
565 {
566         int width, height;
567         MovieClipUser user = {0};
568
569         user.framenr = 1;
570         BKE_movieclip_get_size(clip, &user, &width, &height);
571
572         if (width && height) {
573                 clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
574                 clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
575         }
576         else {
577                 clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
578         }
579 }
580
581 static void detect_clip_source(MovieClip *clip)
582 {
583         ImBuf *ibuf;
584         char name[FILE_MAX];
585
586         BLI_strncpy(name, clip->name, sizeof(name));
587         BLI_path_abs(name, G.main->name);
588
589         ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
590         if (ibuf) {
591                 clip->source = MCLIP_SRC_SEQUENCE;
592                 IMB_freeImBuf(ibuf);
593         }
594         else {
595                 clip->source = MCLIP_SRC_MOVIE;
596         }
597 }
598
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)
604 {
605         MovieClip *clip;
606         int file, len;
607         const char *libname;
608         char str[FILE_MAX];
609
610         BLI_strncpy(str, name, sizeof(str));
611         BLI_path_abs(str, bmain->name);
612
613         /* exists? */
614         file = BLI_open(str, O_BINARY | O_RDONLY, 0);
615         if (file == -1)
616                 return NULL;
617         close(file);
618
619         /* ** add new movieclip ** */
620
621         /* create a short library name */
622         len = strlen(name);
623
624         while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
625                 len--;
626         libname = name + len;
627
628         clip = movieclip_alloc(bmain, libname);
629         BLI_strncpy(clip->name, name, sizeof(clip->name));
630
631         detect_clip_source(clip);
632
633         movieclip_load_get_szie(clip);
634         if (clip->lastsize[0]) {
635                 int width = clip->lastsize[0];
636
637                 clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
638         }
639
640         movieclip_calc_length(clip);
641
642         return clip;
643 }
644
645 MovieClip *BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
646 {
647         MovieClip *clip;
648         char str[FILE_MAX], strtest[FILE_MAX];
649
650         BLI_strncpy(str, filepath, sizeof(str));
651         BLI_path_abs(str, bmain->name);
652
653         /* first search an identical filepath */
654         for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
655                 BLI_strncpy(strtest, clip->name, sizeof(clip->name));
656                 BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &clip->id));
657
658                 if (BLI_path_cmp(strtest, str) == 0) {
659                         clip->id.us++;  /* officially should not, it doesn't link here! */
660                         if (r_exists)
661                                 *r_exists = true;
662                         return clip;
663                 }
664         }
665
666         if (r_exists)
667                 *r_exists = false;
668         return BKE_movieclip_file_add(bmain, filepath);
669 }
670
671 MovieClip *BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
672 {
673         return BKE_movieclip_file_add_exists_ex(bmain, filepath, NULL);
674 }
675
676 static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
677 {
678         *width = ibuf->x;
679         *height = ibuf->y;
680
681         if (clip->flag & MCLIP_USE_PROXY) {
682                 switch (user->render_size) {
683                         case MCLIP_PROXY_RENDER_SIZE_25:
684                                 (*width) *= 4;
685                                 (*height) *= 4;
686                                 break;
687
688                         case MCLIP_PROXY_RENDER_SIZE_50:
689                                 (*width) *= 2.0f;
690                                 (*height) *= 2.0f;
691                                 break;
692
693                         case MCLIP_PROXY_RENDER_SIZE_75:
694                                 *width = ((float)*width) * 4.0f / 3.0f;
695                                 *height = ((float)*height) * 4.0f / 3.0f;
696                                 break;
697                 }
698         }
699 }
700
701 static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
702 {
703         ImBuf *undistibuf;
704
705         if (distortion)
706                 undistibuf = BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
707         else
708                 undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
709
710         IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
711
712         return undistibuf;
713 }
714
715 static int need_undistortion_postprocess(MovieClipUser *user)
716 {
717         int result = 0;
718
719         /* only full undistorted render can be used as on-fly undistorting image */
720         result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
721                   (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
722
723         return result;
724 }
725
726 static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag)
727 {
728         int result = postprocess_flag;
729
730         result |= need_undistortion_postprocess(user);
731
732         return result;
733 }
734
735 static bool check_undistortion_cache_flags(MovieClip *clip)
736 {
737         MovieClipCache *cache = clip->cache;
738         MovieTrackingCamera *camera = &clip->tracking.camera;
739
740         /* check for distortion model changes */
741         if (!equals_v2v2(camera->principal, cache->postprocessed.principal)) {
742                 return false;
743         }
744
745         if (camera->distortion_model != cache->postprocessed.distortion_model) {
746                 return false;
747         }
748
749         if (!equals_v3v3(&camera->k1, &cache->postprocessed.polynomial_k1)) {
750                 return false;
751         }
752
753         if (!equals_v2v2(&camera->division_k1, &cache->postprocessed.division_k1)) {
754                 return false;
755         }
756
757         return true;
758 }
759
760 static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
761 {
762         MovieClipCache *cache = clip->cache;
763         int framenr = user->framenr;
764         short proxy = IMB_PROXY_NONE;
765         int render_flag = 0;
766
767         if (flag & MCLIP_USE_PROXY) {
768                 proxy = rendersize_to_proxy(user, flag);
769                 render_flag = user->render_flag;
770         }
771
772         /* no cache or no cached postprocessed image */
773         if (!clip->cache || !clip->cache->postprocessed.ibuf)
774                 return NULL;
775
776         /* postprocessing happened for other frame */
777         if (cache->postprocessed.framenr != framenr)
778                 return NULL;
779
780         /* cached ibuf used different proxy settings */
781         if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
782                 return NULL;
783
784         if (cache->postprocessed.flag != postprocess_flag)
785                 return NULL;
786
787         if (need_undistortion_postprocess(user)) {
788                 if (!check_undistortion_cache_flags(clip))
789                         return NULL;
790         }
791         else if (cache->postprocessed.undistortion_used)
792                 return NULL;
793
794         IMB_refImBuf(cache->postprocessed.ibuf);
795
796         return cache->postprocessed.ibuf;
797 }
798
799 static ImBuf *postprocess_frame(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int postprocess_flag)
800 {
801         ImBuf *postproc_ibuf = NULL;
802
803         if (need_undistortion_postprocess(user)) {
804                 postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
805         }
806         else {
807                 postproc_ibuf = IMB_dupImBuf(ibuf);
808         }
809
810         if (postprocess_flag) {
811                 bool disable_red   = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
812                 bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
813                 bool disable_blue  = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
814                 bool grayscale     = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
815
816                 if (disable_red || disable_green || disable_blue || grayscale)
817                         BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
818         }
819
820         return postproc_ibuf;
821 }
822
823 static void put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
824                                                int flag, int postprocess_flag)
825 {
826         MovieClipCache *cache = clip->cache;
827         MovieTrackingCamera *camera = &clip->tracking.camera;
828
829         cache->postprocessed.framenr = user->framenr;
830         cache->postprocessed.flag = postprocess_flag;
831
832         if (flag & MCLIP_USE_PROXY) {
833                 cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
834                 cache->postprocessed.render_flag = user->render_flag;
835         }
836         else {
837                 cache->postprocessed.proxy = IMB_PROXY_NONE;
838                 cache->postprocessed.render_flag = 0;
839         }
840
841         if (need_undistortion_postprocess(user)) {
842                 cache->postprocessed.distortion_model = camera->distortion_model;
843                 copy_v2_v2(cache->postprocessed.principal, camera->principal);
844                 copy_v3_v3(&cache->postprocessed.polynomial_k1, &camera->k1);
845                 copy_v2_v2(&cache->postprocessed.division_k1, &camera->division_k1);
846                 cache->postprocessed.undistortion_used = true;
847         }
848         else {
849                 cache->postprocessed.undistortion_used = false;
850         }
851
852         IMB_refImBuf(ibuf);
853
854         if (cache->postprocessed.ibuf)
855                 IMB_freeImBuf(cache->postprocessed.ibuf);
856
857         cache->postprocessed.ibuf = ibuf;
858 }
859
860 static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
861                                                int postprocess_flag, int cache_flag)
862 {
863         ImBuf *ibuf = NULL;
864         int framenr = user->framenr;
865         bool need_postprocess = false;
866
867         /* cache isn't threadsafe itself and also loading of movies
868          * can't happen from concurent threads that's why we use lock here */
869         BLI_lock_thread(LOCK_MOVIECLIP);
870
871         /* try to obtain cached postprocessed frame first */
872         if (need_postprocessed_frame(user, postprocess_flag)) {
873                 ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
874
875                 if (!ibuf)
876                         need_postprocess = true;
877         }
878
879         if (!ibuf)
880                 ibuf = get_imbuf_cache(clip, user, flag);
881
882         if (!ibuf) {
883                 bool use_sequence = false;
884
885                 /* undistorted proxies for movies should be read as image sequence */
886                 use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
887                                (user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
888
889                 if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
890                         ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
891                 }
892                 else {
893                         ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
894                 }
895
896                 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
897                         put_imbuf_cache(clip, user, ibuf, flag, true);
898         }
899
900         if (ibuf) {
901                 clip->lastframe = framenr;
902                 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
903
904                 /* postprocess frame and put to cache if needed*/
905                 if (need_postprocess) {
906                         ImBuf *tmpibuf = ibuf;
907                         ibuf = postprocess_frame(clip, user, tmpibuf, postprocess_flag);
908                         IMB_freeImBuf(tmpibuf);
909                         if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
910                                 put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
911                         }
912                 }
913         }
914
915         BLI_unlock_thread(LOCK_MOVIECLIP);
916
917         return ibuf;
918 }
919
920 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
921 {
922         return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
923 }
924
925 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
926 {
927         return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
928 }
929
930 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
931 {
932         return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
933 }
934
935 static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBuf *reference_ibuf,
936                                       int framenr, int postprocess_flag)
937 {
938         MovieClipCache *cache = clip->cache;
939         MovieTracking *tracking = &clip->tracking;
940         ImBuf *stableibuf;
941         float tloc[2], tscale, tangle;
942         short proxy = IMB_PROXY_NONE;
943         int render_flag = 0;
944         int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
945
946         if (clip->flag & MCLIP_USE_PROXY) {
947                 proxy = rendersize_to_proxy(user, clip->flag);
948                 render_flag = user->render_flag;
949         }
950
951         /* there's no cached frame or it was calculated for another frame */
952         if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
953                 return NULL;
954
955         if (cache->stabilized.reference_ibuf != reference_ibuf)
956                 return NULL;
957
958         /* cached ibuf used different proxy settings */
959         if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy)
960                 return NULL;
961
962         if (cache->stabilized.postprocess_flag != postprocess_flag)
963                 return NULL;
964
965         /* stabilization also depends on pixel aspect ratio */
966         if (cache->stabilized.aspect != tracking->camera.pixel_aspect)
967                 return NULL;
968
969         if (cache->stabilized.filter != tracking->stabilization.filter)
970                 return NULL;
971
972         stableibuf = cache->stabilized.ibuf;
973
974         BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
975
976         /* check for stabilization parameters */
977         if (tscale != cache->stabilized.scale ||
978             tangle != cache->stabilized.angle ||
979             !equals_v2v2(tloc, cache->stabilized.loc))
980         {
981                 return NULL;
982         }
983
984         IMB_refImBuf(stableibuf);
985
986         return stableibuf;
987 }
988
989 static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf,
990                                             int framenr, int postprocess_flag)
991 {
992         MovieClipCache *cache = clip->cache;
993         MovieTracking *tracking = &clip->tracking;
994         ImBuf *stableibuf;
995         float tloc[2], tscale, tangle;
996         int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
997
998         stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle);
999
1000         copy_v2_v2(cache->stabilized.loc, tloc);
1001
1002         cache->stabilized.reference_ibuf = ibuf;
1003         cache->stabilized.scale = tscale;
1004         cache->stabilized.angle = tangle;
1005         cache->stabilized.framenr = framenr;
1006         cache->stabilized.aspect = tracking->camera.pixel_aspect;
1007         cache->stabilized.filter = tracking->stabilization.filter;
1008
1009         if (clip->flag & MCLIP_USE_PROXY) {
1010                 cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
1011                 cache->stabilized.render_flag = user->render_flag;
1012         }
1013         else {
1014                 cache->stabilized.proxy = IMB_PROXY_NONE;
1015                 cache->stabilized.render_flag = 0;
1016         }
1017
1018         cache->stabilized.postprocess_flag = postprocess_flag;
1019
1020         if (cache->stabilized.ibuf)
1021                 IMB_freeImBuf(cache->stabilized.ibuf);
1022
1023         cache->stabilized.ibuf = stableibuf;
1024
1025         IMB_refImBuf(stableibuf);
1026
1027         return stableibuf;
1028 }
1029
1030 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle,
1031                                      int postprocess_flag)
1032 {
1033         ImBuf *ibuf, *stableibuf = NULL;
1034         int framenr = user->framenr;
1035
1036         ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
1037
1038         if (!ibuf)
1039                 return NULL;
1040
1041         if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
1042                 MovieClipCache *cache = clip->cache;
1043
1044                 stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
1045
1046                 if (!stableibuf)
1047                         stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
1048
1049                 if (loc)
1050                         copy_v2_v2(loc, cache->stabilized.loc);
1051
1052                 if (scale)
1053                         *scale = cache->stabilized.scale;
1054
1055                 if (angle)
1056                         *angle = cache->stabilized.angle;
1057         }
1058         else {
1059                 if (loc)
1060                         zero_v2(loc);
1061
1062                 if (scale)
1063                         *scale = 1.0f;
1064
1065                 if (angle)
1066                         *angle = 0.0f;
1067
1068                 stableibuf = ibuf;
1069         }
1070
1071         if (stableibuf != ibuf) {
1072                 IMB_freeImBuf(ibuf);
1073                 ibuf = stableibuf;
1074         }
1075
1076         return ibuf;
1077
1078 }
1079
1080 bool BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
1081 {
1082         ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1083
1084         if (ibuf) {
1085                 IMB_freeImBuf(ibuf);
1086                 return true;
1087         }
1088
1089         return false;
1090 }
1091
1092 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
1093 {
1094 #if 0
1095         /* originally was needed to support image sequences with different image dimensions,
1096          * which might be useful for such things as reconstruction of unordered image sequence,
1097          * or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded
1098          * cache lookups and even unwanted non-proxied files loading when doing mask parenting,
1099          * so let's disable this for now and assume image sequence consists of images with
1100          * equal sizes (sergey)
1101          */
1102         if (user->framenr == clip->lastframe) {
1103 #endif
1104         if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
1105                 *width = clip->lastsize[0];
1106                 *height = clip->lastsize[1];
1107         }
1108         else {
1109                 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1110
1111                 if (ibuf && ibuf->x && ibuf->y) {
1112                         real_ibuf_size(clip, user, ibuf, width, height);
1113                 }
1114                 else {
1115                         *width = clip->lastsize[0];
1116                         *height = clip->lastsize[1];
1117                 }
1118
1119                 if (ibuf)
1120                         IMB_freeImBuf(ibuf);
1121         }
1122 }
1123 void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2])
1124 {
1125         int width, height;
1126         BKE_movieclip_get_size(clip, user, &width, &height);
1127
1128         size[0] = (float)width;
1129         size[1] = (float)height;
1130 }
1131
1132 int BKE_movieclip_get_duration(MovieClip *clip)
1133 {
1134         if (!clip->len) {
1135                 movieclip_calc_length(clip);
1136         }
1137
1138         return clip->len;
1139 }
1140
1141 void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
1142 {
1143         *aspx = 1.0;
1144
1145         /* x is always 1 */
1146         *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
1147 }
1148
1149 /* get segments of cached frames. useful for debugging cache policies */
1150 void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *r_totseg, int **r_points)
1151 {
1152         *r_totseg = 0;
1153         *r_points = NULL;
1154
1155         if (clip->cache) {
1156                 int proxy = rendersize_to_proxy(user, clip->flag);
1157
1158                 IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
1159         }
1160 }
1161
1162 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
1163 {
1164         /* TODO: clamp framenr here? */
1165
1166         iuser->framenr = framenr;
1167 }
1168
1169 static void free_buffers(MovieClip *clip)
1170 {
1171         if (clip->cache) {
1172                 IMB_moviecache_free(clip->cache->moviecache);
1173
1174                 if (clip->cache->postprocessed.ibuf)
1175                         IMB_freeImBuf(clip->cache->postprocessed.ibuf);
1176
1177                 if (clip->cache->stabilized.ibuf)
1178                         IMB_freeImBuf(clip->cache->stabilized.ibuf);
1179
1180                 MEM_freeN(clip->cache);
1181                 clip->cache = NULL;
1182         }
1183
1184         if (clip->anim) {
1185                 IMB_free_anim(clip->anim);
1186                 clip->anim = NULL;
1187         }
1188
1189         BKE_animdata_free((ID *) clip);
1190 }
1191
1192 void BKE_movieclip_clear_cache(MovieClip *clip)
1193 {
1194         free_buffers(clip);
1195 }
1196
1197 void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
1198 {
1199         if (clip->cache && clip->cache->moviecache) {
1200                 IMB_moviecache_cleanup(clip->cache->moviecache,
1201                                        moviecache_check_free_proxy,
1202                                        NULL);
1203         }
1204 }
1205
1206 void BKE_movieclip_reload(MovieClip *clip)
1207 {
1208         /* clear cache */
1209         free_buffers(clip);
1210
1211         clip->tracking.stabilization.ok = false;
1212
1213         /* update clip source */
1214         detect_clip_source(clip);
1215
1216         clip->lastsize[0] = clip->lastsize[1] = 0;
1217         movieclip_load_get_szie(clip);
1218
1219         movieclip_calc_length(clip);
1220
1221         /* same as for image update -- don't use notifiers because they are not 100% sure to succeeded
1222          * (node trees which are not currently visible wouldn't be refreshed)
1223          */
1224         {
1225                 Scene *scene;
1226                 for (scene = G.main->scene.first; scene; scene = scene->id.next) {
1227                         if (scene->nodetree) {
1228                                 nodeUpdateID(scene->nodetree, &clip->id);
1229                         }
1230                 }
1231         }
1232 }
1233
1234 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
1235 {
1236         if (scopes->ok)
1237                 return;
1238
1239         if (scopes->track_preview) {
1240                 IMB_freeImBuf(scopes->track_preview);
1241                 scopes->track_preview = NULL;
1242         }
1243
1244         if (scopes->track_search) {
1245                 IMB_freeImBuf(scopes->track_search);
1246                 scopes->track_search = NULL;
1247         }
1248
1249         scopes->marker = NULL;
1250         scopes->track = NULL;
1251         scopes->track_locked = true;
1252
1253         if (clip) {
1254                 MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
1255
1256                 if (act_track) {
1257                         MovieTrackingTrack *track = act_track;
1258                         int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1259                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1260
1261                         scopes->marker = marker;
1262                         scopes->track = track;
1263
1264                         if (marker->flag & MARKER_DISABLED) {
1265                                 scopes->track_disabled = true;
1266                         }
1267                         else {
1268                                 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1269
1270                                 scopes->track_disabled = false;
1271
1272                                 if (ibuf && (ibuf->rect || ibuf->rect_float)) {
1273                                         MovieTrackingMarker undist_marker = *marker;
1274
1275                                         if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1276                                                 int width, height;
1277                                                 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1278
1279                                                 BKE_movieclip_get_size(clip, user, &width, &height);
1280
1281                                                 undist_marker.pos[0] *= width;
1282                                                 undist_marker.pos[1] *= height * aspy;
1283
1284                                                 BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos);
1285
1286                                                 undist_marker.pos[0] /= width;
1287                                                 undist_marker.pos[1] /= height * aspy;
1288                                         }
1289
1290                                         scopes->track_search = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, true, true);
1291
1292                                         scopes->undist_marker = undist_marker;
1293
1294                                         scopes->frame_width = ibuf->x;
1295                                         scopes->frame_height = ibuf->y;
1296
1297                                         scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
1298                                 }
1299
1300                                 IMB_freeImBuf(ibuf);
1301                         }
1302
1303                         if ((track->flag & TRACK_LOCKED) == 0) {
1304                                 float pat_min[2], pat_max[2];
1305
1306                                 scopes->track_locked = false;
1307
1308                                 /* XXX: would work fine with non-transformed patterns, but would likely fail
1309                                  *      with transformed patterns, but that would be easier to debug when
1310                                  *      we'll have real pattern sampling (at least to test) */
1311                                 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1312
1313                                 scopes->slide_scale[0] = pat_max[0] - pat_min[0];
1314                                 scopes->slide_scale[1] = pat_max[1] - pat_min[1];
1315                         }
1316                 }
1317         }
1318
1319         scopes->framenr = user->framenr;
1320         scopes->ok = true;
1321 }
1322
1323 static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
1324 {
1325         char name[FILE_MAX];
1326         int quality, rectx, recty;
1327         int size = rendersize_to_number(proxy_render_size);
1328         ImBuf *scaleibuf;
1329
1330         get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
1331
1332         rectx = ibuf->x * size / 100.0f;
1333         recty = ibuf->y * size / 100.0f;
1334
1335         scaleibuf = IMB_dupImBuf(ibuf);
1336
1337         if (threaded)
1338                 IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
1339         else
1340                 IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
1341
1342         quality = clip->proxy.quality;
1343         scaleibuf->ftype = IMB_FTYPE_JPG;
1344         scaleibuf->foptions.quality = quality;
1345         /* unsupported feature only confuses other s/w */
1346         if (scaleibuf->planes == 32)
1347                 scaleibuf->planes = 24;
1348
1349         /* TODO: currently the most weak part of multithreaded proxies,
1350          *       could be solved in a way that thread only prepares memory
1351          *       buffer and write to disk happens separately
1352          */
1353         BLI_lock_thread(LOCK_MOVIECLIP);
1354
1355         BLI_make_existing_file(name);
1356         if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
1357                 perror(name);
1358
1359         BLI_unlock_thread(LOCK_MOVIECLIP);
1360
1361         IMB_freeImBuf(scaleibuf);
1362 }
1363
1364 /* note: currently used by proxy job for movies, threading happens within single frame
1365  * (meaning scaling shall be threaded)
1366  */
1367 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
1368                                      int cfra, int *build_sizes, int build_count, bool undistorted)
1369 {
1370         ImBuf *ibuf;
1371         MovieClipUser user;
1372
1373         if (!build_count)
1374                 return;
1375
1376         user.framenr = cfra;
1377         user.render_flag = 0;
1378         user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1379
1380         ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1381
1382         if (ibuf) {
1383                 ImBuf *tmpibuf = ibuf;
1384                 int i;
1385
1386                 if (undistorted)
1387                         tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1388
1389                 for (i = 0; i < build_count; i++)
1390                         movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
1391
1392                 IMB_freeImBuf(ibuf);
1393
1394                 if (tmpibuf != ibuf)
1395                         IMB_freeImBuf(tmpibuf);
1396         }
1397 }
1398
1399 /* note: currently used by proxy job for sequences, threading happens within sequence
1400  * (different threads handles different frames, no threading within frame is needed)
1401  */
1402 void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion,
1403                                               int cfra, int *build_sizes, int build_count, bool undistorted)
1404 {
1405         if (!build_count)
1406                 return;
1407
1408         if (ibuf) {
1409                 ImBuf *tmpibuf = ibuf;
1410                 int i;
1411
1412                 if (undistorted)
1413                         tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1414
1415                 for (i = 0; i < build_count; i++)
1416                         movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
1417
1418                 if (tmpibuf != ibuf)
1419                         IMB_freeImBuf(tmpibuf);
1420         }
1421 }
1422
1423 void BKE_movieclip_free(MovieClip *clip)
1424 {
1425         free_buffers(clip);
1426
1427         BKE_tracking_free(&clip->tracking);
1428 }
1429
1430 void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
1431 {
1432         bScreen *scr;
1433         ScrArea *area;
1434         SpaceLink *sl;
1435         Scene *sce;
1436         Object *ob;
1437
1438         for (scr = bmain->screen.first; scr; scr = scr->id.next) {
1439                 for (area = scr->areabase.first; area; area = area->next) {
1440                         for (sl = area->spacedata.first; sl; sl = sl->next) {
1441                                 if (sl->spacetype == SPACE_CLIP) {
1442                                         SpaceClip *sc = (SpaceClip *) sl;
1443
1444                                         if (sc->clip == clip)
1445                                                 sc->clip = NULL;
1446                                 }
1447                                 else if (sl->spacetype == SPACE_VIEW3D) {
1448                                         View3D *v3d = (View3D *) sl;
1449                                         BGpic *bgpic;
1450
1451                                         for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1452                                                 if (bgpic->clip == clip)
1453                                                         bgpic->clip = NULL;
1454                                         }
1455                                 }
1456                         }
1457                 }
1458         }
1459
1460         for (sce = bmain->scene.first; sce; sce = sce->id.next) {
1461                 if (sce->clip == clip)
1462                         sce->clip = NULL;
1463         }
1464
1465         for (ob = bmain->object.first; ob; ob = ob->id.next) {
1466                 bConstraint *con;
1467
1468                 for (con = ob->constraints.first; con; con = con->next) {
1469                         if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
1470                                 bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
1471
1472                                 if (data->clip == clip)
1473                                         data->clip = NULL;
1474                         }
1475                         else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
1476                                 bCameraSolverConstraint *data = (bCameraSolverConstraint *) con->data;
1477
1478                                 if (data->clip == clip)
1479                                         data->clip = NULL;
1480                         }
1481                         else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
1482                                 bObjectSolverConstraint *data = (bObjectSolverConstraint *) con->data;
1483
1484                                 if (data->clip == clip)
1485                                         data->clip = NULL;
1486                         }
1487                 }
1488         }
1489
1490         FOREACH_NODETREE(bmain, ntree, id) {
1491                 BKE_node_tree_unlink_id((ID *)clip, ntree);
1492         } FOREACH_NODETREE_END
1493
1494         clip->id.us = 0;
1495 }
1496
1497 float BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, float framenr)
1498 {
1499         return framenr - (float) clip->start_frame + 1.0f;
1500 }
1501
1502 float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr)
1503 {
1504         return framenr + (float) clip->start_frame - 1.0f;
1505 }
1506
1507 void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char *name)
1508 {
1509         if (clip->source == MCLIP_SRC_SEQUENCE) {
1510                 int use_proxy;
1511
1512                 use_proxy = (clip->flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
1513
1514                 if (use_proxy) {
1515                         int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1516                         get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
1517                 }
1518                 else {
1519                         get_sequence_fname(clip, user->framenr, name);
1520                 }
1521         }
1522         else {
1523                 BLI_strncpy(name, clip->name, FILE_MAX);
1524                 BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
1525         }
1526 }
1527
1528 ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
1529 {
1530         ImBuf *ibuf = NULL;
1531
1532         if (clip->source == MCLIP_SRC_MOVIE) {
1533                 BLI_lock_thread(LOCK_MOVIECLIP);
1534                 ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
1535                 BLI_unlock_thread(LOCK_MOVIECLIP);
1536         }
1537
1538         return ibuf;
1539 }
1540
1541 bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
1542 {
1543         bool has_frame = false;
1544
1545         BLI_lock_thread(LOCK_MOVIECLIP);
1546         has_frame = has_imbuf_cache(clip, user, clip->flag);
1547         BLI_unlock_thread(LOCK_MOVIECLIP);
1548
1549         return has_frame;
1550 }
1551
1552 bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf)
1553 {
1554         bool result;
1555
1556         BLI_lock_thread(LOCK_MOVIECLIP);
1557         result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
1558         BLI_unlock_thread(LOCK_MOVIECLIP);
1559
1560         return result;
1561 }