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