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