bb8e420451fc55062fc9f289a2acd753de18f0a5
[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, int postprocess_flag)
635 {
636         ImBuf *ibuf= NULL;
637         int framenr= user->framenr, need_postprocess= 0;
638
639         /* cache isn't threadsafe itself and also loading of movies
640            can't happen from concurent threads that's why we use lock here */
641         BLI_lock_thread(LOCK_MOVIECLIP);
642
643         /* try to obtain cached postprocessed frame first */
644         if(need_postprocessed_frame(user, flag, postprocess_flag)) {
645                 ibuf= get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
646
647                 if(!ibuf)
648                         need_postprocess= 1;
649         }
650
651         if(!ibuf)
652                 ibuf= get_imbuf_cache(clip, user, flag);
653
654         if(!ibuf) {
655                 int use_sequence= 0;
656
657                 /* undistorted proxies for movies should be read as image sequence */
658                 use_sequence= (user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) &&
659                         (user->render_size!=MCLIP_PROXY_RENDER_SIZE_FULL);
660
661                 if(clip->source==MCLIP_SRC_SEQUENCE || use_sequence)
662                         ibuf= movieclip_load_sequence_file(clip, user, framenr, flag);
663                 else {
664                         ibuf= movieclip_load_movie_file(clip, user, framenr, flag);
665                 }
666
667                 if(ibuf)
668                         put_imbuf_cache(clip, user, ibuf, flag);
669         }
670
671         if(ibuf) {
672                 clip->lastframe= framenr;
673                 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
674
675                 /* postprocess frame and put to cache */
676                 if(need_postprocess) {
677                         ImBuf *tmpibuf= ibuf;
678                         ibuf= put_postprocessed_frame_to_cache(clip, user, tmpibuf, flag, postprocess_flag);
679                         IMB_freeImBuf(tmpibuf);
680                 }
681         }
682
683         BLI_unlock_thread(LOCK_MOVIECLIP);
684
685         return ibuf;
686 }
687
688 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
689 {
690         return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag);
691 }
692
693 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag)
694 {
695         return movieclip_get_postprocessed_ibuf(clip, user, flag, 0);
696 }
697
698 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *user, int postprocess_flag)
699 {
700         return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag);
701 }
702
703 static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int framenr)
704 {
705         MovieClipCache *cache = clip->cache;
706         ImBuf *stableibuf;
707         float tloc[2], tscale, tangle;
708         short proxy = IMB_PROXY_NONE;
709         int render_flag = 0;
710
711         if(clip->flag&MCLIP_USE_PROXY) {
712                 proxy = rendersize_to_proxy(user, clip->flag);
713                 render_flag = user->render_flag;
714         }
715
716         /* there's no cached frame or it was calculated for another frame */
717         if(!cache->stabilized.ibuf || cache->stabilized.framenr != framenr)
718                 return NULL;
719
720         /* cached ibuf used different proxy settings */
721         if(cache->stabilized.render_flag!=render_flag || cache->stabilized.proxy!=proxy)
722                 return NULL;
723
724         stableibuf = cache->stabilized.ibuf;
725
726         BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
727
728         /* check for stabilization parameters */
729         if(tscale != cache->stabilized.scale ||
730            tangle != cache->stabilized.angle ||
731            !equals_v2v2(tloc, cache->stabilized.loc))
732         {
733                 return NULL;
734         }
735
736         IMB_refImBuf(stableibuf);
737
738         return stableibuf;
739 }
740
741 static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int framenr)
742 {
743         MovieClipCache *cache = clip->cache;
744         ImBuf *stableibuf;
745         float tloc[2], tscale, tangle;
746
747         if(cache->stabilized.ibuf)
748                 IMB_freeImBuf(cache->stabilized.ibuf);
749
750         stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle);
751
752         cache->stabilized.ibuf= stableibuf;
753
754         copy_v2_v2(cache->stabilized.loc, tloc);
755
756         cache->stabilized.scale = tscale;
757         cache->stabilized.angle = tangle;
758         cache->stabilized.framenr = framenr;
759
760         if(clip->flag&MCLIP_USE_PROXY) {
761                 cache->stabilized.proxy= rendersize_to_proxy(user, clip->flag);
762                 cache->stabilized.render_flag= user->render_flag;
763         }
764         else {
765                 cache->stabilized.proxy = IMB_PROXY_NONE;
766                 cache->stabilized.render_flag = 0;
767         }
768
769         IMB_refImBuf(stableibuf);
770
771         return stableibuf;
772 }
773
774 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag)
775 {
776         ImBuf *ibuf, *stableibuf= NULL;
777         int framenr= user->framenr;
778
779         ibuf= BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
780
781         if(!ibuf)
782                 return NULL;
783
784         if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
785                 MovieClipCache *cache= clip->cache;
786
787                 stableibuf= get_stable_cached_frame(clip, user, framenr);
788
789                 if(!stableibuf)
790                         stableibuf= put_stabilized_frame_to_cache(clip, user, ibuf, framenr);
791
792                 if(loc)         copy_v2_v2(loc, cache->stabilized.loc);
793                 if(scale)       *scale= cache->stabilized.scale;
794                 if(angle)       *angle= cache->stabilized.angle;
795         } else {
796                 if(loc)         zero_v2(loc);
797                 if(scale)       *scale= 1.0f;
798                 if(angle)       *angle= 0.0f;
799
800                 stableibuf= ibuf;
801         }
802
803         if(stableibuf!=ibuf) {
804                 IMB_freeImBuf(ibuf);
805                 ibuf= stableibuf;
806         }
807
808         return ibuf;
809
810 }
811
812 int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
813 {
814         ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
815
816         if(ibuf) {
817                 IMB_freeImBuf(ibuf);
818                 return 1;
819         }
820
821         return 0;
822 }
823
824 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
825 {
826         if(user->framenr==clip->lastframe) {
827                 *width= clip->lastsize[0];
828                 *height= clip->lastsize[1];
829         } else {
830                 ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
831
832                 if(ibuf && ibuf->x && ibuf->y) {
833                         real_ibuf_size(clip, user, ibuf, width, height);
834                 } else {
835                         *width= 0;
836                         *height= 0;
837                 }
838
839                 if(ibuf)
840                         IMB_freeImBuf(ibuf);
841         }
842 }
843
844 void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy)
845 {
846         *aspx= *aspy= 1.0;
847
848         /* x is always 1 */
849         *aspy = clip->aspy/clip->aspx/clip->tracking.camera.pixel_aspect;
850 }
851
852 /* get segments of cached frames. useful for debugging cache policies */
853 void BKE_movieclip_get_cache_segments(MovieClip *clip, MovieClipUser *user, int *totseg_r, int **points_r)
854 {
855         *totseg_r= 0;
856         *points_r= NULL;
857
858         if(clip->cache) {
859                 int proxy= rendersize_to_proxy(user, clip->flag);
860
861                 IMB_moviecache_get_cache_segments(clip->cache->moviecache, proxy, user->render_flag, totseg_r, points_r);
862         }
863 }
864
865 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
866 {
867         /* TODO: clamp framenr here? */
868
869         iuser->framenr= framenr;
870 }
871
872 static void free_buffers(MovieClip *clip)
873 {
874         if(clip->cache) {
875                 IMB_moviecache_free(clip->cache->moviecache);
876
877                 if(clip->cache->postprocessed.ibuf)
878                         IMB_freeImBuf(clip->cache->postprocessed.ibuf);
879
880                 if(clip->cache->stabilized.ibuf)
881                         IMB_freeImBuf(clip->cache->stabilized.ibuf);
882
883                 MEM_freeN(clip->cache);
884                 clip->cache= NULL;
885         }
886
887         if(clip->anim) {
888                 IMB_free_anim(clip->anim);
889                 clip->anim= FALSE;
890         }
891 }
892
893 void BKE_movieclip_reload(MovieClip *clip)
894 {
895         /* clear cache */
896         free_buffers(clip);
897
898         clip->tracking.stabilization.ok= 0;
899
900         /* update clip source */
901         if(BLI_testextensie_array(clip->name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
902         else clip->source= MCLIP_SRC_SEQUENCE;
903 }
904
905 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
906 {
907         if(scopes->ok)
908                 return;
909
910         if(scopes->track_preview) {
911                 IMB_freeImBuf(scopes->track_preview);
912                 scopes->track_preview= NULL;
913         }
914
915         scopes->marker= NULL;
916         scopes->track= NULL;
917
918         if(clip) {
919                 MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
920
921                 if(act_track) {
922                         MovieTrackingTrack *track= act_track;
923                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
924
925                         if(marker->flag&MARKER_DISABLED) {
926                                 scopes->track_disabled= 1;
927                         } else {
928                                 ImBuf *ibuf= BKE_movieclip_get_ibuf(clip, user);
929
930                                 scopes->track_disabled= 0;
931
932                                 if(ibuf && ibuf->rect) {
933                                         ImBuf *tmpibuf;
934                                         MovieTrackingMarker undist_marker= *marker;
935
936                                         if(user->render_flag&MCLIP_PROXY_RENDER_UNDISTORT) {
937                                                 int width, height;
938                                                 float aspy= 1.0f/clip->tracking.camera.pixel_aspect;;
939
940                                                 BKE_movieclip_get_size(clip, user, &width, &height);
941
942                                                 undist_marker.pos[0]*= width;
943                                                 undist_marker.pos[1]*= height*aspy;
944
945                                                 BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos);
946
947                                                 undist_marker.pos[0]/= width;
948                                                 undist_marker.pos[1]/= height*aspy;
949                                         }
950
951                                         /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */
952                                         tmpibuf= BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */,
953                                                         1 /* anchor */, scopes->track_pos, NULL);
954
955                                         if(tmpibuf->rect_float)
956                                                 IMB_rect_from_float(tmpibuf);
957
958                                         if(tmpibuf->rect)
959                                                 scopes->track_preview= tmpibuf;
960                                         else
961                                                 IMB_freeImBuf(tmpibuf);
962                                 }
963
964                                 IMB_freeImBuf(ibuf);
965                         }
966
967                         if((track->flag&TRACK_LOCKED)==0) {
968                                 scopes->marker= marker;
969                                 scopes->track= track;
970                                 scopes->slide_scale[0]= track->pat_max[0]-track->pat_min[0];
971                                 scopes->slide_scale[1]= track->pat_max[1]-track->pat_min[1];
972                         }
973                 }
974         }
975
976         scopes->framenr= user->framenr;
977         scopes->ok= 1;
978 }
979
980 static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
981 {
982         char name[FILE_MAX];
983         int quality, rectx, recty;
984         int size= rendersize_to_number(proxy_render_size);
985         ImBuf *scaleibuf;
986
987         get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
988
989         rectx= ibuf->x*size/100.0f;
990         recty= ibuf->y*size/100.0f;
991
992         scaleibuf= IMB_dupImBuf(ibuf);
993
994         IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
995
996         quality= clip->proxy.quality;
997         scaleibuf->ftype= JPG | quality;
998
999         /* unsupported feature only confuses other s/w */
1000         if(scaleibuf->planes==32)
1001                 scaleibuf->planes= 24;
1002
1003         BLI_lock_thread(LOCK_MOVIECLIP);
1004
1005         BLI_make_existing_file(name);
1006         if(IMB_saveiff(scaleibuf, name, IB_rect)==0)
1007                 perror(name);
1008
1009         BLI_unlock_thread(LOCK_MOVIECLIP);
1010
1011         IMB_freeImBuf(scaleibuf);
1012 }
1013
1014 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
1015                         int cfra, int *build_sizes, int build_count, int undistorted)
1016 {
1017         ImBuf *ibuf;
1018         MovieClipUser user;
1019
1020         user.framenr= cfra;
1021         user.render_flag= 0;
1022         user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL;
1023
1024         ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag);
1025
1026         if(ibuf) {
1027                 ImBuf *tmpibuf= ibuf;
1028                 int i;
1029
1030                 if(undistorted)
1031                         tmpibuf= get_undistorted_ibuf(clip, distortion, ibuf);
1032
1033                 for(i= 0; i<build_count; i++)
1034                         movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
1035
1036                 IMB_freeImBuf(ibuf);
1037
1038                 if(tmpibuf!=ibuf)
1039                         IMB_freeImBuf(tmpibuf);
1040         }
1041 }
1042
1043 void free_movieclip(MovieClip *clip)
1044 {
1045         free_buffers(clip);
1046
1047         BKE_tracking_free(&clip->tracking);
1048 }
1049
1050 void unlink_movieclip(Main *bmain, MovieClip *clip)
1051 {
1052         bScreen *scr;
1053         ScrArea *area;
1054         SpaceLink *sl;
1055         Scene *sce;
1056         Object *ob;
1057
1058         for(scr= bmain->screen.first; scr; scr= scr->id.next) {
1059                 for(area= scr->areabase.first; area; area= area->next) {
1060                         for(sl= area->spacedata.first; sl; sl= sl->next) {
1061                                 if(sl->spacetype==SPACE_CLIP) {
1062                                         SpaceClip *sc= (SpaceClip *) sl;
1063
1064                                         if(sc->clip==clip)
1065                                                 sc->clip= NULL;
1066                                 }
1067                                 else if(sl->spacetype==SPACE_VIEW3D) {
1068                                         View3D *v3d= (View3D *) sl;
1069                                         BGpic *bgpic;
1070
1071                                         for(bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
1072                                                 if(bgpic->clip==clip)
1073                                                         bgpic->clip= NULL;
1074                                         }
1075                                 }
1076                         }
1077                 }
1078         }
1079
1080         for(sce= bmain->scene.first; sce; sce= sce->id.next) {
1081                 if(sce->clip==clip)
1082                         sce->clip= NULL;
1083         }
1084
1085         for(ob= bmain->object.first; ob; ob= ob->id.next) {
1086                 bConstraint *con;
1087
1088                 for(con= ob->constraints.first; con; con= con->next) {
1089                         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
1090
1091                         if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
1092                                 bFollowTrackConstraint *data= (bFollowTrackConstraint *) con->data;
1093
1094                                 if(data->clip==clip)
1095                                         data->clip= NULL;
1096                         }
1097                         else if(cti->type==CONSTRAINT_TYPE_CAMERASOLVER) {
1098                                 bCameraSolverConstraint *data= (bCameraSolverConstraint *) con->data;
1099
1100                                 if(data->clip==clip)
1101                                         data->clip= NULL;
1102                         }
1103                 }
1104         }
1105
1106         clip->id.us= 0;
1107 }