Camera tracking: regression fixed after recent frame postprocessing refactor
[blender-staging.git] / source / blender / blenkernel / intern / movieclip.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenkernel/intern/movieclip.c
28  *  \ingroup bke
29  */
30
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <fcntl.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #endif
41
42 #include <time.h>
43
44 #ifdef _WIN32
45 #define open _open
46 #define close _close
47 #endif
48
49 #include "MEM_guardedalloc.h"
50
51 #include "DNA_constraint_types.h"
52 #include "DNA_screen_types.h"
53 #include "DNA_space_types.h"
54 #include "DNA_movieclip_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_view3d_types.h"
58
59 #include "BLI_utildefines.h"
60
61 #include "BLI_blenlib.h"
62 #include "BLI_ghash.h"
63 #include "BLI_math.h"
64 #include "BLI_mempool.h"
65 #include "BLI_threads.h"
66
67 #include "BKE_constraint.h"
68 #include "BKE_library.h"
69 #include "BKE_global.h"
70 #include "BKE_main.h"
71 #include "BKE_utildefines.h"
72 #include "BKE_movieclip.h"
73 #include "BKE_image.h"  /* openanim */
74 #include "BKE_tracking.h"
75
76 #include "IMB_imbuf_types.h"
77 #include "IMB_imbuf.h"
78 #include "IMB_moviecache.h"
79
80 /*********************** movieclip buffer loaders *************************/
81
82 static int sequence_guess_offset(const char *full_name, int head_len, int numlen)
83 {
84         char num[FILE_MAX]= {0};
85
86         BLI_strncpy(num, full_name+head_len, numlen+1);
87
88         return atoi(num);
89 }
90
91 static int rendersize_to_proxy(MovieClipUser *user, int flag)
92 {
93         if((flag&MCLIP_USE_PROXY)==0)
94                 return IMB_PROXY_NONE;
95
96         switch(user->render_size) {
97                 case MCLIP_PROXY_RENDER_SIZE_25:
98                         return IMB_PROXY_25;
99
100                 case MCLIP_PROXY_RENDER_SIZE_50:
101                         return IMB_PROXY_50;
102
103                 case MCLIP_PROXY_RENDER_SIZE_75:
104                         return IMB_PROXY_75;
105
106                 case MCLIP_PROXY_RENDER_SIZE_100:
107                         return IMB_PROXY_100;
108
109                 case MCLIP_PROXY_RENDER_SIZE_FULL:
110                         return IMB_PROXY_NONE;
111         }
112
113         return IMB_PROXY_NONE;
114 }
115
116 static int rendersize_to_number(int render_size)
117 {
118         switch(render_size) {
119                 case MCLIP_PROXY_RENDER_SIZE_25:
120                         return 25;
121
122                 case MCLIP_PROXY_RENDER_SIZE_50:
123                         return 50;
124
125                 case MCLIP_PROXY_RENDER_SIZE_75:
126                         return 75;
127
128                 case MCLIP_PROXY_RENDER_SIZE_100:
129                         return 100;
130
131                 case MCLIP_PROXY_RENDER_SIZE_FULL:
132                         return 100;
133         }
134
135         return 100;
136 }
137
138 static int get_timecode(MovieClip *clip, int flag)
139 {
140         if((flag&MCLIP_USE_PROXY)==0)
141                 return IMB_TC_NONE;
142
143         return clip->proxy.tc;
144 }
145
146 static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
147 {
148         unsigned short numlen;
149         char head[FILE_MAX], tail[FILE_MAX];
150         int offset;
151
152         BLI_strncpy(name, clip->name, sizeof(clip->name));
153         BLI_stringdec(name, head, tail, &numlen);
154
155         /* movieclips always points to first image from sequence,
156            autoguess offset for now. could be something smarter in the future */
157         offset= sequence_guess_offset(clip->name, strlen(head), numlen);
158
159         if (numlen) BLI_stringenc(name, head, tail, numlen, offset+framenr-1);
160         else        BLI_strncpy(name, clip->name, sizeof(clip->name));
161
162         BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
163 }
164
165 /* supposed to work with sequences only */
166 static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int undistorted, int framenr, char *name)
167 {
168         int size= rendersize_to_number(proxy_render_size);
169         char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
170
171         BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX);
172
173         if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
174                 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
175         } else {
176                 BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
177         }
178
179         if(undistorted)
180                 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, framenr);
181         else
182                 BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, framenr);
183
184         BLI_path_abs(name, G.main->name);
185         BLI_path_frame(name, 1, 0);
186
187         strcat(name, ".jpg");
188 }
189
190 static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
191 {
192         struct ImBuf *ibuf;
193         char name[FILE_MAX];
194         int loadflag, use_proxy= 0;
195
196         use_proxy= (flag&MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
197         if(use_proxy) {
198                 int undistort= user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT;
199                 get_proxy_fname(clip, user->render_size, undistort, framenr, name);
200         } else
201                 get_sequence_fname(clip, framenr, name);
202
203         loadflag= IB_rect|IB_multilayer;
204
205         /* read ibuf */
206         ibuf= IMB_loadiffname(name, loadflag);
207
208         return ibuf;
209 }
210
211 static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, int framenr, int flag)
212 {
213         ImBuf *ibuf= NULL;
214         int tc= get_timecode(clip, flag);
215         int proxy= rendersize_to_proxy(user, flag);
216         char str[FILE_MAX];
217
218         if(!clip->anim) {
219                 BLI_strncpy(str, clip->name, FILE_MAX);
220                 BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
221
222                 /* FIXME: make several stream accessible in image editor, too */
223                 clip->anim= openanim(str, IB_rect, 0);
224
225                 if(clip->anim) {
226                         if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
227                                 char dir[FILE_MAX];
228                                 BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
229                                 BLI_path_abs(dir, G.main->name);
230                                 IMB_anim_set_index_dir(clip->anim, dir);
231                         }
232                 }
233         }
234
235         if(clip->anim) {
236                 int dur;
237                 int fra;
238
239                 dur= IMB_anim_get_duration(clip->anim, tc);
240                 fra= framenr-1;
241
242                 if(fra<0)
243                         fra= 0;
244
245                 if(fra>(dur-1))
246                         fra= dur-1;
247
248                 ibuf= IMB_anim_absolute(clip->anim, fra, tc, proxy);
249         }
250
251         return ibuf;
252 }
253
254 /*********************** image buffer cache *************************/
255
256 typedef struct MovieClipCache {
257         /* regular movie cache */
258         struct MovieCache *moviecache;
259
260         /* cached postprocessed shot */
261         struct {
262                 ImBuf *ibuf;
263                 int framenr;
264                 int flag;
265
266                 /* cache for undistorted shot */
267                 float principal[2];
268                 float k1, k2, k3;
269                 short undistoriton_used;
270
271                 int proxy;
272                 short render_flag;
273         } postprocessed;
274
275         /* cache for stable shot */
276         struct {
277                 ImBuf *ibuf;
278                 int framenr;
279
280                 float loc[2], scale, angle;
281                 int proxy;
282                 short render_flag;
283         } stabilized;
284 } MovieClipCache;
285
286 typedef struct MovieClipImBufCacheKey {
287         int framenr;
288         int proxy;
289         short render_flag;
290 } MovieClipImBufCacheKey;
291
292 static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
293 {
294         MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)userkey;
295
296         *framenr= key->framenr;
297         *proxy= key->proxy;
298         *render_flags= key->render_flag;
299 }
300
301 static unsigned int moviecache_hashhash(const void *keyv)
302 {
303         MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)keyv;
304         int rval= key->framenr;
305
306         return rval;
307 }
308
309 static int moviecache_hashcmp(const void *av, const void *bv)
310 {
311         const MovieClipImBufCacheKey *a= (MovieClipImBufCacheKey*)av;
312         const MovieClipImBufCacheKey *b= (MovieClipImBufCacheKey*)bv;
313
314         if(a->framenr<b->framenr) return -1;
315         else if(a->framenr>b->framenr) return 1;
316
317         if(a->proxy<b->proxy) return -1;
318         else if(a->proxy>b->proxy) return 1;
319
320         if(a->render_flag<b->render_flag) return -1;
321         else if(a->render_flag>b->render_flag) return 1;
322
323         return 0;
324 }
325
326 static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
327 {
328         if(clip->cache) {
329                 MovieClipImBufCacheKey key;
330
331                 key.framenr= user->framenr;
332
333                 if(flag&MCLIP_USE_PROXY) {
334                         key.proxy= rendersize_to_proxy(user, flag);
335                         key.render_flag= user->render_flag;
336                 }
337                 else {
338                         key.proxy= IMB_PROXY_NONE;
339                         key.render_flag= 0;
340                 }
341
342                 return IMB_moviecache_get(clip->cache->moviecache, &key);
343         }
344
345         return NULL;
346 }
347
348 static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag)
349 {
350         MovieClipImBufCacheKey key;
351
352         if(!clip->cache) {
353                 clip->cache= MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
354
355                 clip->cache->moviecache= IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash,
356                                 moviecache_hashcmp, moviecache_keydata);
357         }
358
359         key.framenr= user->framenr;
360
361         if(flag&MCLIP_USE_PROXY) {
362                 key.proxy= rendersize_to_proxy(user, flag);
363                 key.render_flag= user->render_flag;
364         }
365         else {
366                 key.proxy= IMB_PROXY_NONE;
367                 key.render_flag= 0;
368         }
369
370         IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
371 }
372
373 /*********************** common functions *************************/
374
375 /* only image block itself */
376 static MovieClip *movieclip_alloc(const char *name)
377 {
378         MovieClip *clip;
379
380         clip= alloc_libblock(&G.main->movieclip, ID_MC, name);
381
382         clip->aspx= clip->aspy= 1.0f;
383
384         BKE_tracking_init_settings(&clip->tracking);
385
386         clip->proxy.build_size_flag= IMB_PROXY_25;
387         clip->proxy.build_tc_flag= IMB_TC_RECORD_RUN |
388                                    IMB_TC_FREE_RUN |
389                                    IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN |
390                                    IMB_TC_RECORD_RUN_NO_GAPS;
391         clip->proxy.quality= 90;
392
393         return clip;
394 }
395
396 /* checks if image was already loaded, then returns same image
397    otherwise creates new.
398    does not load ibuf itself
399    pass on optional frame for #name images */
400 MovieClip *BKE_add_movieclip_file(const char *name)
401 {
402         MovieClip *clip;
403         MovieClipUser user;
404         int file, len, width, height;
405         const char *libname;
406         char str[FILE_MAX], strtest[FILE_MAX];
407
408         BLI_strncpy(str, name, sizeof(str));
409         BLI_path_abs(str, G.main->name);
410
411         /* exists? */
412         file= open(str, O_BINARY|O_RDONLY);
413         if(file== -1) return NULL;
414         close(file);
415
416         /* ** first search an identical clip ** */
417         for(clip= G.main->movieclip.first; clip; clip= clip->id.next) {
418                 BLI_strncpy(strtest, clip->name, sizeof(clip->name));
419                 BLI_path_abs(strtest, G.main->name);
420
421                 if(strcmp(strtest, str)==0) {
422                         BLI_strncpy(clip->name, name, sizeof(clip->name));  /* for stringcode */
423                         clip->id.us++;  /* officially should not, it doesn't link here! */
424
425                         return clip;
426                 }
427         }
428
429         /* ** add new movieclip ** */
430
431         /* create a short library name */
432         len= strlen(name);
433
434         while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
435         libname= name+len;
436
437         clip= movieclip_alloc(libname);
438         BLI_strncpy(clip->name, name, sizeof(clip->name));
439
440         if(BLI_testextensie_array(name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
441         else clip->source= MCLIP_SRC_SEQUENCE;
442
443         user.framenr= 1;
444         BKE_movieclip_get_size(clip, &user, &width, &height);
445         if(width && height) {
446                 clip->tracking.camera.principal[0]= ((float)width)/2;
447                 clip->tracking.camera.principal[1]= ((float)height)/2;
448
449                 clip->tracking.camera.focal= 24.0f*width/clip->tracking.camera.sensor_width;
450         }
451
452         return clip;
453 }
454
455 static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
456 {
457         *width= ibuf->x;
458         *height= ibuf->y;
459
460         if(clip->flag&MCLIP_USE_PROXY) {
461                 switch(user->render_size) {
462                         case MCLIP_PROXY_RENDER_SIZE_25:
463                                 (*width)*= 4;
464                                 (*height)*= 4;
465                                 break;
466
467                         case MCLIP_PROXY_RENDER_SIZE_50:
468                                 (*width)*= 2.0f;
469                                 (*height)*= 2.0f;
470                                 break;
471
472                         case MCLIP_PROXY_RENDER_SIZE_75:
473                                 *width= ((float)*width)*4.0f/3.0f;
474                                 *height= ((float)*height)*4.0f/3.0f;
475                                 break;
476                 }
477         }
478 }
479
480 static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *distortion, ImBuf *ibuf)
481 {
482         ImBuf *undistibuf;
483
484         /* XXX: because of #27997 do not use float buffers to undistort,
485                 otherwise, undistorted proxy can be darker than it should */
486         imb_freerectfloatImBuf(ibuf);
487
488         if(distortion)
489                 undistibuf= BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
490         else
491                 undistibuf= BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
492
493         if(undistibuf->userflags&IB_RECT_INVALID) {
494                 ibuf->userflags&= ~IB_RECT_INVALID;
495                 IMB_rect_from_float(undistibuf);
496         }
497
498         IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
499
500         return undistibuf;
501 }
502
503 static int need_undistortion_postprocess(MovieClipUser *user, int flag)
504 {
505         int result = 0;
506
507         /* only full undistorted render can be used as on-fly undistorting image */
508         if(flag & MCLIP_USE_PROXY) {
509                 result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) &&
510                           (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
511         }
512
513         return result;
514 }
515
516 static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag)
517 {
518         int result = postprocess_flag;
519
520         result |= need_undistortion_postprocess(user, flag);
521
522         return result;
523 }
524
525 static int check_undistortion_cache_flags(MovieClip *clip)
526 {
527         MovieClipCache *cache= clip->cache;
528         MovieTrackingCamera *camera= &clip->tracking.camera;
529
530         /* check for distortion model changes */
531         if(!equals_v2v2(camera->principal, cache->postprocessed.principal))
532                 return 0;
533
534         if(!equals_v3v3(&camera->k1, &cache->postprocessed.k1))
535                 return 0;
536
537         return 1;
538 }
539
540 static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *user, int flag, int postprocess_flag)
541 {
542         MovieClipCache *cache= clip->cache;
543         int framenr= user->framenr;
544         short proxy= IMB_PROXY_NONE;
545         int render_flag= 0;
546
547         if(flag&MCLIP_USE_PROXY) {
548                 proxy= rendersize_to_proxy(user, flag);
549                 render_flag= user->render_flag;
550         }
551
552         /* no cache or no cached postprocessed image */
553         if(!clip->cache || !clip->cache->postprocessed.ibuf)
554                 return NULL;
555
556         /* postprocessing happened for other frame */
557         if(cache->postprocessed.framenr != framenr)
558                 return NULL;
559
560         /* cached ibuf used different proxy settings */
561         if(cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy)
562                 return NULL;
563
564         if(cache->postprocessed.flag != postprocess_flag)
565                 return NULL;
566
567         if(need_undistortion_postprocess(user, flag)) {
568                 if(!check_undistortion_cache_flags(clip))
569                         return NULL;
570         }
571         else if(cache->postprocessed.undistoriton_used)
572                 return NULL;
573
574         IMB_refImBuf(cache->postprocessed.ibuf);
575
576         return cache->postprocessed.ibuf;
577 }
578
579 static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
580 {
581         MovieClipCache *cache= clip->cache;
582         MovieTrackingCamera *camera= &clip->tracking.camera;
583         ImBuf *postproc_ibuf = NULL;
584
585         if(cache->postprocessed.ibuf)
586                 IMB_freeImBuf(cache->postprocessed.ibuf);
587
588         cache->postprocessed.framenr= user->framenr;
589         cache->postprocessed.flag = postprocess_flag;
590
591         if(flag&MCLIP_USE_PROXY) {
592                 cache->postprocessed.proxy= rendersize_to_proxy(user, flag);
593                 cache->postprocessed.render_flag= user->render_flag;
594         }
595         else {
596                 cache->postprocessed.proxy = IMB_PROXY_NONE;
597                 cache->postprocessed.render_flag = 0;
598         }
599
600         if(need_undistortion_postprocess(user, flag)) {
601                 copy_v2_v2(cache->postprocessed.principal, camera->principal);
602                 copy_v3_v3(&cache->postprocessed.k1, &camera->k1);
603                 cache->postprocessed.undistoriton_used = 1;
604                 postproc_ibuf= get_undistorted_ibuf(clip, NULL, ibuf);
605         }
606         else cache->postprocessed.undistoriton_used = 0;
607
608         if(postprocess_flag) {
609                 int disable_red   = postprocess_flag & MOVIECLIP_DISABLE_RED,
610                     disable_green = postprocess_flag & MOVIECLIP_DISABLE_GREEN,
611                         disable_blue  = postprocess_flag & MOVIECLIP_DISABLE_BLUE,
612                         grayscale     = postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE;
613
614                 if(!postproc_ibuf)
615                         postproc_ibuf = IMB_dupImBuf(ibuf);
616
617                 if(disable_red || disable_green || disable_blue || grayscale)
618                         BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
619         }
620
621         IMB_refImBuf(postproc_ibuf);
622
623         cache->postprocessed.ibuf= postproc_ibuf;
624
625         if(cache->stabilized.ibuf) {
626                 /* force stable buffer be re-calculated */
627                 IMB_freeImBuf(cache->stabilized.ibuf);
628                 cache->stabilized.ibuf= NULL;
629         }
630
631         return postproc_ibuf;
632 }
633
634 static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int flag,
635                                                int postprocess_flag, int cache_flag)
636 {
637         ImBuf *ibuf= NULL;
638         int framenr= user->framenr, need_postprocess= 0;
639
640         /* cache isn't threadsafe itself and also loading of movies
641            can't happen from concurent threads that's why we use lock here */
642         BLI_lock_thread(LOCK_MOVIECLIP);
643
644         /* try to obtain cached postprocessed frame first */
645         if(need_postprocessed_frame(user, flag, postprocess_flag)) {
646                 ibuf= get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
647
648                 if(!ibuf)
649                         need_postprocess= 1;
650         }
651
652         if(!ibuf)
653                 ibuf= get_imbuf_cache(clip, user, flag);
654
655         if(!ibuf) {
656                 int use_sequence= 0;
657
658                 /* undistorted proxies for movies should be read as image sequence */
659                 use_sequence= (user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) &&
660                         (user->render_size!=MCLIP_PROXY_RENDER_SIZE_FULL);
661
662                 if(clip->source==MCLIP_SRC_SEQUENCE || use_sequence)
663                         ibuf= movieclip_load_sequence_file(clip, user, framenr, flag);
664                 else {
665                         ibuf= movieclip_load_movie_file(clip, user, framenr, flag);
666                 }
667
668                 if(ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
669                         put_imbuf_cache(clip, user, ibuf, flag);
670         }
671
672         if(ibuf) {
673                 clip->lastframe= framenr;
674                 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
675
676                 /* postprocess frame and put to cache */
677                 if(need_postprocess) {
678                         ImBuf *tmpibuf= ibuf;
679                         ibuf= put_postprocessed_frame_to_cache(clip, user, tmpibuf, flag, postprocess_flag);
680                         IMB_freeImBuf(tmpibuf);
681                 }
682         }
683
684         BLI_unlock_thread(LOCK_MOVIECLIP);
685
686         return ibuf;
687 }
688
689 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
690 {
691         return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
692 }
693
694 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
695 {
696         return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
697 }
698
699 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
700 {
701         return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
702 }
703
704 static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int framenr)
705 {
706         MovieClipCache *cache = clip->cache;
707         ImBuf *stableibuf;
708         float tloc[2], tscale, tangle;
709         short proxy = IMB_PROXY_NONE;
710         int render_flag = 0;
711
712         if(clip->flag&MCLIP_USE_PROXY) {
713                 proxy = rendersize_to_proxy(user, clip->flag);
714                 render_flag = user->render_flag;
715         }
716
717         /* there's no cached frame or it was calculated for another frame */
718         if(!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
719                 return NULL;
720
721         /* cached ibuf used different proxy settings */
722         if(cache->stabilized.render_flag!=render_flag || cache->stabilized.proxy!=proxy)
723                 return NULL;
724
725         stableibuf = cache->stabilized.ibuf;
726
727         BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
728
729         /* check for stabilization parameters */
730         if(tscale != cache->stabilized.scale ||
731            tangle != cache->stabilized.angle ||
732            !equals_v2v2(tloc, cache->stabilized.loc))
733         {
734                 return NULL;
735         }
736
737         IMB_refImBuf(stableibuf);
738
739         return stableibuf;
740 }
741
742 static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int framenr)
743 {
744         MovieClipCache *cache = clip->cache;
745         ImBuf *stableibuf;
746         float tloc[2], tscale, tangle;
747
748         if(cache->stabilized.ibuf)
749                 IMB_freeImBuf(cache->stabilized.ibuf);
750
751         stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle);
752
753         cache->stabilized.ibuf= stableibuf;
754
755         copy_v2_v2(cache->stabilized.loc, tloc);
756
757         cache->stabilized.scale = tscale;
758         cache->stabilized.angle = tangle;
759         cache->stabilized.framenr = framenr;
760
761         if(clip->flag&MCLIP_USE_PROXY) {
762                 cache->stabilized.proxy= rendersize_to_proxy(user, clip->flag);
763                 cache->stabilized.render_flag= user->render_flag;
764         }
765         else {
766                 cache->stabilized.proxy = IMB_PROXY_NONE;
767                 cache->stabilized.render_flag = 0;
768         }
769
770         IMB_refImBuf(stableibuf);
771
772         return stableibuf;
773 }
774
775 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag)
776 {
777         ImBuf *ibuf, *stableibuf= NULL;
778         int framenr= user->framenr;
779
780         ibuf= BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
781
782         if(!ibuf)
783                 return NULL;
784
785         if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
786                 MovieClipCache *cache= clip->cache;
787
788                 stableibuf= get_stable_cached_frame(clip, user, framenr);
789
790                 if(!stableibuf)
791                         stableibuf= put_stabilized_frame_to_cache(clip, user, ibuf, framenr);
792
793                 if(loc)         copy_v2_v2(loc, cache->stabilized.loc);
794                 if(scale)       *scale= cache->stabilized.scale;
795                 if(angle)       *angle= cache->stabilized.angle;
796         } else {
797                 if(loc)         zero_v2(loc);
798                 if(scale)       *scale= 1.0f;
799                 if(angle)       *angle= 0.0f;
800
801                 stableibuf= ibuf;
802         }
803
804         if(stableibuf!=ibuf) {
805                 IMB_freeImBuf(ibuf);
806                 ibuf= stableibuf;
807         }
808
809         return ibuf;
810
811 }
812
813 int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
814 {
815         ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
816
817         if(ibuf) {
818                 IMB_freeImBuf(ibuf);
819                 return 1;
820         }
821
822         return 0;
823 }
824
825 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
826 {
827         if(user->framenr==clip->lastframe) {
828                 *width= clip->lastsize[0];
829                 *height= clip->lastsize[1];
830         } else {
831                 ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
832
833                 if(ibuf && ibuf->x && ibuf->y) {
834                         real_ibuf_size(clip, user, ibuf, width, height);
835                 } else {
836                         *width= 0;
837                         *height= 0;
838                 }
839
840                 if(ibuf)
841                         IMB_freeImBuf(ibuf);
842         }
843 }
844
845 void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy)
846 {
847         *aspx= *aspy= 1.0;
848
849         /* x is always 1 */
850         *aspy = clip->aspy/clip->aspx/clip->tracking.camera.pixel_aspect;
851 }
852
853 /* get segments of cached frames. useful for debugging cache policies */
854 void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
855 {
856         *totseg_r= 0;
857         *points_r= NULL;
858
859         if(clip->cache) {
860                 int proxy= rendersize_to_proxy(user, clip->flag);
861
862                 IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
863         }
864 }
865
866 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
867 {
868         /* TODO: clamp framenr here? */
869
870         iuser->framenr= framenr;
871 }
872
873 static void free_buffers(MovieClip *clip)
874 {
875         if(clip->cache) {
876                 IMB_moviecache_free(clip->cache->moviecache);
877
878                 if(clip->cache->postprocessed.ibuf)
879                         IMB_freeImBuf(clip->cache->postprocessed.ibuf);
880
881                 if(clip->cache->stabilized.ibuf)
882                         IMB_freeImBuf(clip->cache->stabilized.ibuf);
883
884                 MEM_freeN(clip->cache);
885                 clip->cache= NULL;
886         }
887
888         if(clip->anim) {
889                 IMB_free_anim(clip->anim);
890                 clip->anim= FALSE;
891         }
892 }
893
894 void BKE_movieclip_reload(MovieClip *clip)
895 {
896         /* clear cache */
897         free_buffers(clip);
898
899         clip->tracking.stabilization.ok= 0;
900
901         /* update clip source */
902         if(BLI_testextensie_array(clip->name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
903         else clip->source= MCLIP_SRC_SEQUENCE;
904 }
905
906 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
907 {
908         if(scopes->ok)
909                 return;
910
911         if(scopes->track_preview) {
912                 IMB_freeImBuf(scopes->track_preview);
913                 scopes->track_preview= NULL;
914         }
915
916         scopes->marker= NULL;
917         scopes->track= NULL;
918
919         if(clip) {
920                 MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
921
922                 if(act_track) {
923                         MovieTrackingTrack *track= act_track;
924                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
925
926                         if(marker->flag&MARKER_DISABLED) {
927                                 scopes->track_disabled= 1;
928                         } else {
929                                 ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
930
931                                 scopes->track_disabled= 0;
932
933                                 if(ibuf && ibuf->rect) {
934                                         ImBuf *tmpibuf;
935                                         MovieTrackingMarker undist_marker= *marker;
936
937                                         if(user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) {
938                                                 int width, height;
939                                                 float aspy= 1.0f/clip->tracking.camera.pixel_aspect;;
940
941                                                 BKE_movieclip_get_size(clip, user, &width, &height);
942
943                                                 undist_marker.pos[0]*= width;
944                                                 undist_marker.pos[1]*= height*aspy;
945
946                                                 BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos);
947
948                                                 undist_marker.pos[0]/= width;
949                                                 undist_marker.pos[1]/= height*aspy;
950                                         }
951
952                                         /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */
953                                         tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */,
954                                                         1 /* anchor */, scopes->track_pos, NULL);
955
956                                         if(tmpibuf->rect_float)
957                                                 IMB_rect_from_float(tmpibuf);
958
959                                         if(tmpibuf->rect)
960                                                 scopes->track_preview= tmpibuf;
961                                         else
962                                                 IMB_freeImBuf(tmpibuf);
963                                 }
964
965                                 IMB_freeImBuf(ibuf);
966                         }
967
968                         if((track->flag&TRACK_LOCKED)==0) {
969                                 scopes->marker= marker;
970                                 scopes->track= track;
971                                 scopes->slide_scale[0]= track->pat_max[0]-track->pat_min[0];
972                                 scopes->slide_scale[1]= track->pat_max[1]-track->pat_min[1];
973                         }
974                 }
975         }
976
977         scopes->framenr= user->framenr;
978         scopes->ok= 1;
979 }
980
981 static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
982 {
983         char name[FILE_MAX];
984         int quality, rectx, recty;
985         int size= rendersize_to_number(proxy_render_size);
986         ImBuf *scaleibuf;
987
988         get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
989
990         rectx= ibuf->x*size/100.0f;
991         recty= ibuf->y*size/100.0f;
992
993         scaleibuf= IMB_dupImBuf(ibuf);
994
995         IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
996
997         quality= clip->proxy.quality;
998         scaleibuf->ftype= JPG | quality;
999
1000         /* unsupported feature only confuses other s/w */
1001         if(scaleibuf->planes==32)
1002                 scaleibuf->planes= 24;
1003
1004         BLI_lock_thread(LOCK_MOVIECLIP);
1005
1006         BLI_make_existing_file(name);
1007         if(IMB_saveiff(scaleibuf, name, IB_rect)==0)
1008                 perror(name);
1009
1010         BLI_unlock_thread(LOCK_MOVIECLIP);
1011
1012         IMB_freeImBuf(scaleibuf);
1013 }
1014
1015 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
1016                         int cfra, int *build_sizes, int build_count, int undistorted)
1017 {
1018         ImBuf *ibuf;
1019         MovieClipUser user;
1020
1021         user.framenr= cfra;
1022         user.render_flag= 0;
1023         user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL;
1024
1025         ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1026
1027         if(ibuf) {
1028                 ImBuf *tmpibuf= ibuf;
1029                 int i;
1030
1031                 if(undistorted)
1032                         tmpibuf= get_undistorted_ibuf(clip, distortion, ibuf);
1033
1034                 for(i= 0; i<build_count; i++)
1035                         movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
1036
1037                 IMB_freeImBuf(ibuf);
1038
1039                 if(tmpibuf!=ibuf)
1040                         IMB_freeImBuf(tmpibuf);
1041         }
1042 }
1043
1044 void free_movieclip(MovieClip *clip)
1045 {
1046         free_buffers(clip);
1047
1048         BKE_tracking_free(&clip->tracking);
1049 }
1050
1051 void unlink_movieclip(Main *bmain, MovieClip *clip)
1052 {
1053         bScreen *scr;
1054         ScrArea *area;
1055         SpaceLink *sl;
1056         Scene *sce;
1057         Object *ob;
1058
1059         for(scr= bmain->screen.first; scr; scr= scr->id.next) {
1060                 for(area= scr->areabase.first; area; area= area->next) {
1061                         for(sl= area->spacedata.first; sl; sl= sl->next) {
1062                                 if(sl->spacetype==SPACE_CLIP) {
1063                                         SpaceClip *sc= (SpaceClip *) sl;
1064
1065                                         if(sc->clip==clip)
1066                                                 sc->clip= NULL;
1067                                 }
1068                                 else if(sl->spacetype==SPACE_VIEW3D) {
1069                                         View3D *v3d= (View3D *) sl;
1070                                         BGpic *bgpic;
1071
1072                                         for(bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
1073                                                 if(bgpic->clip==clip)
1074                                                         bgpic->clip= NULL;
1075                                         }
1076                                 }
1077                         }
1078                 }
1079         }
1080
1081         for(sce= bmain->scene.first; sce; sce= sce->id.next) {
1082                 if(sce->clip==clip)
1083                         sce->clip= NULL;
1084         }
1085
1086         for(ob= bmain->object.first; ob; ob= ob->id.next) {
1087                 bConstraint *con;
1088
1089                 for(con= ob->constraints.first; con; con= con->next) {
1090                         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
1091
1092                         if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
1093                                 bFollowTrackConstraint *data= (bFollowTrackConstraint *) con->data;
1094
1095                                 if(data->clip==clip)
1096                                         data->clip= NULL;
1097                         }
1098                         else if(cti->type==CONSTRAINT_TYPE_CAMERASOLVER) {
1099                                 bCameraSolverConstraint *data= (bCameraSolverConstraint *) con->data;
1100
1101                                 if(data->clip==clip)
1102                                         data->clip= NULL;
1103                         }
1104                 }
1105         }
1106
1107         clip->id.us= 0;
1108 }