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