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