Merging r39435 through r39477 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / movieclip.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2011 Blender Foundation.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation,
24  *                 Sergey Sharybin
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/blenkernel/intern/movieclip.c
30  *  \ingroup bke
31  */
32
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <fcntl.h>
37
38 #ifndef WIN32
39 #include <unistd.h>
40 #else
41 #include <io.h>
42 #endif
43
44 #include <time.h>
45
46 #ifdef _WIN32
47 #define open _open
48 #define close _close
49 #endif
50
51 #include "MEM_guardedalloc.h"
52
53 #include "DNA_screen_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_movieclip_types.h"
56 #include "DNA_object_types.h"   /* SELECT */
57
58 #include "BLI_utildefines.h"
59
60 #include "BLI_blenlib.h"
61 #include "BLI_ghash.h"
62 #include "BLI_math.h"
63 #include "BLI_mempool.h"
64 #include "BLI_threads.h"
65
66 #include "BKE_library.h"
67 #include "BKE_global.h"
68 #include "BKE_main.h"
69 #include "BKE_utildefines.h"
70 #include "BKE_movieclip.h"
71 #include "BKE_moviecache.h"
72 #include "BKE_image.h"  /* openanim */
73 #include "BKE_tracking.h"
74 #include "BKE_animsys.h"
75
76 #include "IMB_imbuf_types.h"
77 #include "IMB_imbuf.h"
78
79 /*********************** movieclip buffer loaders *************************/
80
81 static int sequence_guess_offset(const char *full_name, int head_len, int numlen)
82 {
83         char num[FILE_MAX]= {0};
84
85         strncpy(num, full_name+head_len, numlen);
86
87         return atoi(num);
88 }
89
90 static int rendersize_to_proxy(MovieClip *clip, int flag)
91 {
92         if((flag&MCLIP_USE_PROXY)==0)
93                 return IMB_PROXY_NONE;
94
95         switch(clip->render_size) {
96                 case MCLIP_PROXY_RENDER_SIZE_25:
97                         return IMB_PROXY_25;
98
99                 case MCLIP_PROXY_RENDER_SIZE_50:
100                         return IMB_PROXY_50;
101
102                 case MCLIP_PROXY_RENDER_SIZE_75:
103                         return IMB_PROXY_75;
104
105                 case MCLIP_PROXY_RENDER_SIZE_FULL:
106                         return IMB_PROXY_NONE;
107         }
108
109         return IMB_PROXY_NONE;
110 }
111
112 static int rendersize_to_number(int render_size)
113 {
114         switch(render_size) {
115                 case MCLIP_PROXY_RENDER_SIZE_25:
116                         return 25;
117
118                 case MCLIP_PROXY_RENDER_SIZE_50:
119                         return 50;
120
121                 case MCLIP_PROXY_RENDER_SIZE_75:
122                         return 75;
123
124                 case MCLIP_PROXY_RENDER_SIZE_FULL:
125                         return 100;
126         }
127
128         return 100;
129 }
130
131 static int get_timecode(MovieClip *clip, int flag)
132 {
133         if((flag&MCLIP_USE_PROXY)==0)
134                 return IMB_TC_NONE;
135
136         return clip->proxy.tc;
137 }
138
139 static void get_sequence_fname(MovieClip *clip, int framenr, char *name)
140 {
141         unsigned short numlen;
142         char head[FILE_MAX], tail[FILE_MAX];
143         int offset;
144
145         BLI_strncpy(name, clip->name, sizeof(clip->name));
146         BLI_stringdec(name, head, tail, &numlen);
147
148         /* movieclips always points to first image from sequence,
149            autoguess offset for now. could be something smarter in the future */
150         offset= sequence_guess_offset(clip->name, strlen(head), numlen);
151
152         if(numlen) BLI_stringenc(name, head, tail, numlen, offset+framenr-1);
153         else strncpy(name, clip->name, sizeof(name));
154
155         if(clip->id.lib)
156                 BLI_path_abs(name, clip->id.lib->filepath);
157         else
158                 BLI_path_abs(name, G.main->name);
159 }
160
161 /* supposed to work with sequences only */
162 static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int framenr, char *name)
163 {
164         int size= rendersize_to_number(proxy_render_size);
165         char dir[FILE_MAX], curname[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
166
167         get_sequence_fname(clip, framenr, curname);
168         BLI_split_dirfile(curname, clipdir, clipfile);
169
170         if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
171                 strcpy(dir, clip->proxy.dir);
172         } else {
173                 BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
174         }
175
176         BLI_snprintf(name, FILE_MAX, "%s/images/%d/%s_proxy", dir, size,  clipfile);
177
178         BLI_path_abs(name, G.main->name);
179         BLI_path_frame(name, 1, 0);
180
181         strcat(name, ".jpg");
182 }
183
184 static ImBuf *movieclip_load_sequence_file(MovieClip *clip, int framenr, int flag)
185 {
186         struct ImBuf *ibuf;
187         char name[FILE_MAX];
188         int loadflag, size;
189
190         size= rendersize_to_number(clip->render_size);
191
192         if(flag&MCLIP_USE_PROXY && size!=100) get_proxy_fname(clip, clip->render_size, framenr, name);
193         else get_sequence_fname(clip, framenr, name);
194
195         loadflag= IB_rect|IB_multilayer;
196
197         /* read ibuf */
198         ibuf= IMB_loadiffname(name, loadflag);
199
200         return ibuf;
201 }
202
203 static ImBuf *movieclip_load_movie_file(MovieClip *clip, int framenr, int flag)
204 {
205         ImBuf *ibuf= NULL;
206         int tc= get_timecode(clip, flag);
207         int proxy= rendersize_to_proxy(clip, flag);
208         char str[FILE_MAX];
209
210         if(!clip->anim) {
211                 BLI_strncpy(str, clip->name, FILE_MAX);
212
213                 if(clip->id.lib)
214                         BLI_path_abs(str, clip->id.lib->filepath);
215                 else
216                         BLI_path_abs(str, G.main->name);
217
218                 clip->anim= openanim(str, IB_rect);
219
220
221                 if(clip->anim) {
222                         if(clip->flag&MCLIP_USE_PROXY_CUSTOM_DIR) {
223                                 char dir[FILE_MAX];
224                                 strcpy(dir, clip->proxy.dir);
225                                 BLI_path_abs(dir, G.main->name);
226                                 IMB_anim_set_index_dir(clip->anim, dir);
227                         }
228                 }
229         }
230
231         if(clip->anim) {
232                 int dur= IMB_anim_get_duration(clip->anim, tc);
233                 int fra= framenr-1;
234
235                 dur= IMB_anim_get_duration(clip->anim, tc);
236                 fra= framenr-1;
237
238                 if(fra<0)
239                         fra= 0;
240
241                 if(fra>(dur-1))
242                         fra= dur-1;
243
244                 ibuf= IMB_anim_absolute(clip->anim, fra, tc, proxy);
245         }
246
247         return ibuf;
248 }
249
250 /*********************** image buffer cache *************************/
251
252 typedef struct MovieClipCache {
253         /* regular moive cache */
254         struct MovieCache *moviecache;
255
256         /* cache for stable shot */
257         int stable_framenr;
258         float stable_loc[2], stable_scale;
259         ImBuf *stableibuf;
260 } MovieClipCache;
261
262 typedef struct MovieClipImBufCacheKey {
263         int framenr;
264         int proxy;
265 } MovieClipImBufCacheKey;
266
267 static void moviecache_keydata(void *userkey, int *framenr, int *proxy)
268 {
269         MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)userkey;
270
271         *framenr= key->framenr;
272         *proxy= key->proxy;
273 }
274
275 static unsigned int moviecache_hashhash(const void *keyv)
276 {
277         MovieClipImBufCacheKey *key= (MovieClipImBufCacheKey*)keyv;
278         int rval= key->framenr;
279
280         return rval;
281 }
282
283 static int moviecache_hashcmp(const void *av, const void *bv)
284 {
285         const MovieClipImBufCacheKey *a= (MovieClipImBufCacheKey*)av;
286         const MovieClipImBufCacheKey *b= (MovieClipImBufCacheKey*)bv;
287
288         if(a->framenr<b->framenr) return -1;
289         else if(a->framenr>b->framenr) return 1;
290
291         if(a->proxy<b->proxy) return -1;
292         else if(a->proxy>b->proxy) return 1;
293
294         return 0;
295 }
296
297 static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
298 {
299         if(clip->cache) {
300                 MovieClipImBufCacheKey key;
301
302                 key.framenr= user?user->framenr:clip->lastframe;
303
304                 if(flag&MCLIP_USE_PROXY) key.proxy= rendersize_to_proxy(clip, flag);
305                 else key.proxy= IMB_PROXY_NONE;
306
307                 return BKE_moviecache_get(clip->cache->moviecache, &key);
308         }
309
310         return NULL;
311 }
312
313 static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag)
314 {
315         MovieClipImBufCacheKey key;
316
317         if(!clip->cache) {
318                 clip->cache= MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
319
320                 clip->cache->moviecache= BKE_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash,
321                                 moviecache_hashcmp, moviecache_keydata);
322         }
323
324         key.framenr= user?user->framenr:clip->lastframe;
325
326         if(flag&MCLIP_USE_PROXY) key.proxy= rendersize_to_proxy(clip, flag);
327         else key.proxy= IMB_PROXY_NONE;
328
329         BKE_moviecache_put(clip->cache->moviecache, &key, ibuf);
330 }
331
332 /*********************** common functions *************************/
333
334 /* only image block itself */
335 static MovieClip *movieclip_alloc(const char *name)
336 {
337         MovieClip *clip;
338
339         clip= alloc_libblock(&G.main->movieclip, ID_MC, name);
340
341         clip->aspx= clip->aspy= 1.0f;
342
343         clip->tracking.camera.sensor_width= 35.0f;
344         clip->tracking.camera.pixel_aspect= 1.0f;
345         clip->tracking.camera.units= CAMERA_UNITS_MM;
346
347         clip->tracking.settings.frames_limit= 0;
348         clip->tracking.settings.keyframe1= 1;
349         clip->tracking.settings.keyframe2= 30;
350         clip->tracking.settings.dist= 1;
351
352         clip->tracking.stabilization.scaleinf= 1.f;
353         clip->tracking.stabilization.locinf= 1.f;
354
355         clip->proxy.build_size_flags= IMB_PROXY_25;
356         clip->proxy.build_tc_flags= IMB_TC_RECORD_RUN|IMB_TC_FREE_RUN|IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN;
357         clip->proxy.quality= 90;
358         clip->render_size= MCLIP_PROXY_RENDER_SIZE_FULL;
359
360         return clip;
361 }
362
363 /* checks if image was already loaded, then returns same image
364    otherwise creates new.
365    does not load ibuf itself
366    pass on optional frame for #name images */
367 MovieClip *BKE_add_movieclip_file(const char *name)
368 {
369         MovieClip *clip;
370         MovieClipUser user;
371         int file, len, width, height;
372         const char *libname;
373         char str[FILE_MAX], strtest[FILE_MAX];
374
375         BLI_strncpy(str, name, sizeof(str));
376         BLI_path_abs(str, G.main->name);
377
378         /* exists? */
379         file= open(str, O_BINARY|O_RDONLY);
380         if(file== -1) return NULL;
381         close(file);
382
383         /* ** first search an identical clip ** */
384         for(clip= G.main->movieclip.first; clip; clip= clip->id.next) {
385                 BLI_strncpy(strtest, clip->name, sizeof(clip->name));
386                 BLI_path_abs(strtest, G.main->name);
387
388                 if(strcmp(strtest, str)==0) {
389                         BLI_strncpy(clip->name, name, sizeof(clip->name));  /* for stringcode */
390                         clip->id.us++;  /* officially should not, it doesn't link here! */
391
392                         return clip;
393                 }
394         }
395
396         /* ** add new movieclip ** */
397
398         /* create a short library name */
399         len= strlen(name);
400
401         while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
402         libname= name+len;
403
404         clip= movieclip_alloc(libname);
405         BLI_strncpy(clip->name, name, sizeof(clip->name));
406
407         if(BLI_testextensie_array(name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
408         else clip->source= MCLIP_SRC_SEQUENCE;
409
410         user.framenr= 1;
411         BKE_movieclip_acquire_size(clip, &user, &width, &height);
412         if(width && height) {
413                 clip->tracking.camera.principal[0]= ((float)width)/2;
414                 clip->tracking.camera.principal[1]= ((float)height)/2;
415
416                 clip->tracking.camera.focal= 24.f*width/clip->tracking.camera.sensor_width;
417         }
418
419         return clip;
420 }
421
422 static void real_ibuf_size(MovieClip *clip, ImBuf *ibuf, int *width, int *height)
423 {
424         *width= ibuf->x;
425         *height= ibuf->y;
426
427         if(clip->flag&MCLIP_USE_PROXY) {
428                 switch(clip->render_size) {
429                         case MCLIP_PROXY_RENDER_SIZE_25:
430                                 (*width)*= 4;
431                                 (*height)*= 4;
432                                 break;
433
434                         case MCLIP_PROXY_RENDER_SIZE_50:
435                                 (*width)*= 2;
436                                 (*height)*= 2;
437                                 break;
438
439                         case MCLIP_PROXY_RENDER_SIZE_75:
440                                 *width= ((float)*width)*4.f/3.f;
441                                 *height= ((float)*height)*4.f/3.f;
442                                 break;
443                }
444        }
445 }
446
447 ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user)
448 {
449         ImBuf *ibuf= NULL;
450         int framenr= user?user->framenr:clip->lastframe;
451
452         /* cache isn't threadsafe itself and also loading of movies
453            can't happen from concurent threads that's why we use lock here */
454         BLI_lock_thread(LOCK_MOVIECLIP);
455
456         /* cache is supposed to be threadsafe */
457         ibuf= get_imbuf_cache(clip, user, clip->flag);
458
459         if(!ibuf) {
460                 if(clip->source==MCLIP_SRC_SEQUENCE)
461                         ibuf= movieclip_load_sequence_file(clip, framenr, clip->flag);
462                 else {
463                         ibuf= movieclip_load_movie_file(clip, framenr, clip->flag);
464                 }
465
466                 if(ibuf)
467                         put_imbuf_cache(clip, user, ibuf, clip->flag);
468         }
469
470         if(ibuf) {
471                 clip->lastframe= framenr;
472
473                 real_ibuf_size(clip, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
474         }
475
476         BLI_unlock_thread(LOCK_MOVIECLIP);
477
478         return ibuf;
479 }
480
481 ImBuf *BKE_movieclip_acquire_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag)
482 {
483         ImBuf *ibuf= NULL;
484         int framenr= user?user->framenr:clip->lastframe;
485
486         /* cache isn't threadsafe itself and also loading of movies
487            can't happen from concurent threads that's why we use lock here */
488         BLI_lock_thread(LOCK_MOVIECLIP);
489
490         /* cache is supposed to be threadsafe */
491         ibuf= get_imbuf_cache(clip, user, flag);
492
493         if(!ibuf) {
494                 if(clip->source==MCLIP_SRC_SEQUENCE) {
495                         ibuf= movieclip_load_sequence_file(clip, framenr, flag);
496                 } else {
497                         ibuf= movieclip_load_movie_file(clip, framenr, flag);
498                 }
499
500                 if(ibuf) {
501                         int bits= MCLIP_USE_PROXY|MCLIP_USE_PROXY_CUSTOM_DIR;
502
503                         if((flag&bits)==(clip->flag&bits))
504                                 put_imbuf_cache(clip, user, ibuf, clip->flag);
505                 }
506         }
507
508         BLI_unlock_thread(LOCK_MOVIECLIP);
509
510         return ibuf;
511 }
512
513 ImBuf *BKE_movieclip_acquire_stable_ibuf(MovieClip *clip, MovieClipUser *user, float loc[2], float *scale)
514 {
515         ImBuf *ibuf, *stableibuf= NULL;
516         int framenr= user?user->framenr:clip->lastframe;
517
518         ibuf= BKE_movieclip_acquire_ibuf(clip, user);
519
520         if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
521                 float tloc[2], tscale;
522
523                 if(clip->cache->stableibuf && clip->cache->stable_framenr==framenr) {
524                         stableibuf= clip->cache->stableibuf;
525
526                         BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale);
527
528                         if(!equals_v2v2(tloc, clip->cache->stable_loc) || tscale!=clip->cache->stable_scale) {
529                                 stableibuf= NULL;
530                         }
531                 }
532
533                 if(!stableibuf) {
534                         if(clip->cache->stableibuf)
535                                 IMB_freeImBuf(clip->cache->stableibuf);
536
537                         stableibuf= BKE_tracking_stabilize_shot(&clip->tracking, framenr, ibuf, tloc, &tscale);
538
539                         copy_v2_v2(clip->cache->stable_loc, tloc);
540                         clip->cache->stable_scale= tscale;
541                         clip->cache->stable_framenr= framenr;
542                         clip->cache->stableibuf= stableibuf;
543                 }
544
545                 IMB_refImBuf(stableibuf);
546
547                 if(loc)         copy_v2_v2(loc, tloc);
548                 if(scale)       *scale= tscale;
549         } else {
550                 if(loc)         zero_v2(loc);
551                 if(scale)       *scale= 1.f;
552
553                 stableibuf= ibuf;
554         }
555
556         if(stableibuf!=ibuf) {
557                 IMB_freeImBuf(ibuf);
558                 ibuf= stableibuf;
559         }
560
561         return ibuf;
562
563 }
564
565 int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
566 {
567         ImBuf *ibuf= BKE_movieclip_acquire_ibuf(clip, user);
568
569         if(ibuf) {
570                 IMB_freeImBuf(ibuf);
571                 return 1;
572         }
573
574         return 0;
575 }
576
577 void BKE_movieclip_acquire_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
578 {
579         if(!user || user->framenr==clip->lastframe) {
580                 *width= clip->lastsize[0];
581                 *height= clip->lastsize[1];
582         } else {
583                 ImBuf *ibuf= BKE_movieclip_acquire_ibuf(clip, user);
584
585                 if(ibuf && ibuf->x && ibuf->y) {
586                         real_ibuf_size(clip, ibuf, width, height);
587                 } else {
588                         *width= 0;
589                         *height= 0;
590                 }
591
592                 if(ibuf)
593                         IMB_freeImBuf(ibuf);
594         }
595 }
596
597 void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy)
598 {
599         *aspx= *aspy= 1.0;
600
601         /* x is always 1 */
602         *aspy = clip->aspy/clip->aspx/clip->tracking.camera.pixel_aspect;
603 }
604
605 /* get segments of cached frames. useful for debugging cache policies */
606 void BKE_movieclip_get_cache_segments(MovieClip *clip, int *totseg_r, int **points_r)
607 {
608         *totseg_r= 0;
609         *points_r= NULL;
610
611         if(clip->cache) {
612                 int proxy= rendersize_to_proxy(clip, clip->flag);
613
614                 BKE_moviecache_get_cache_segments(clip->cache->moviecache, proxy, totseg_r, points_r);
615         }
616 }
617
618 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
619 {
620         /* TODO: clamp framenr here? */
621
622         iuser->framenr= framenr;
623 }
624
625 static void free_buffers(MovieClip *clip)
626 {
627         if(clip->cache) {
628                 BKE_moviecache_free(clip->cache->moviecache);
629
630                 if(clip->cache->stableibuf)
631                         IMB_freeImBuf(clip->cache->stableibuf);
632
633                 MEM_freeN(clip->cache);
634                 clip->cache= NULL;
635         }
636
637         if(clip->anim) {
638                 IMB_free_anim(clip->anim);
639                 clip->anim= FALSE;
640         }
641 }
642
643 void BKE_movieclip_reload(MovieClip *clip)
644 {
645         /* clear cache */
646         free_buffers(clip);
647
648         clip->tracking.stabilization.ok= 0;
649
650         /* update clip source */
651         if(BLI_testextensie_array(clip->name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
652         else clip->source= MCLIP_SRC_SEQUENCE;
653 }
654
655 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
656 void BKE_movieclip_select_track(MovieClip *clip, MovieTrackingTrack *track, int area, int extend)
657 {
658         if(extend) {
659                 BKE_tracking_track_flag(track, area, SELECT, 0);
660         } else {
661                 MovieTrackingTrack *cur= clip->tracking.tracks.first;
662
663                 while(cur) {
664                         if(cur==track) {
665                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
666                                 BKE_tracking_track_flag(cur, area, SELECT, 0);
667                         }
668                         else {
669                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
670                         }
671
672                         cur= cur->next;
673                 }
674         }
675 }
676
677 void BKE_movieclip_deselect_track(MovieClip *clip, MovieTrackingTrack *track, int area)
678 {
679         BKE_tracking_track_flag(track, area, SELECT, 1);
680 }
681
682 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
683 {
684         if(scopes->ok) return;
685
686         if(scopes->track_preview) {
687                 IMB_freeImBuf(scopes->track_preview);
688                 scopes->track_preview= NULL;
689         }
690
691         scopes->marker= NULL;
692         scopes->track= NULL;
693
694         if(clip) {
695                 if(clip->tracking.act_track) {
696                         MovieTrackingTrack *track= clip->tracking.act_track;
697                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
698
699                         if(marker->flag&MARKER_DISABLED) {
700                                 scopes->track_disabled= 1;
701                         } else {
702                                 ImBuf *ibuf= BKE_movieclip_acquire_ibuf(clip, user);
703
704                                 scopes->track_disabled= 0;
705
706                                 if(ibuf && ibuf->rect) {
707                                         ImBuf *tmpibuf;
708
709                                         tmpibuf= BKE_tracking_acquire_pattern_imbuf(ibuf, track, marker, 1, scopes->track_pos, NULL);
710
711                                         if(tmpibuf->rect_float)
712                                                 IMB_rect_from_float(tmpibuf);
713
714                                         if(tmpibuf->rect)
715                                                 scopes->track_preview= tmpibuf;
716                                         else
717                                                 IMB_freeImBuf(tmpibuf);
718                                 }
719
720                                 IMB_freeImBuf(ibuf);
721                         }
722
723                         if((track->flag&TRACK_LOCKED)==0) {
724                                 scopes->marker= marker;
725                                 scopes->track= track;
726                                 scopes->slide_scale[0]= track->pat_max[0]-track->pat_min[0];
727                                 scopes->slide_scale[1]= track->pat_max[1]-track->pat_min[1];
728                         }
729                 }
730         }
731
732         scopes->framenr= user->framenr;
733         scopes->ok= 1;
734 }
735
736 void BKE_movieclip_build_proxy_frame(MovieClip *clip, int cfra, int proxy_render_size)
737 {
738         char name[FILE_MAXFILE+FILE_MAXDIR];
739         int quality, rectx, recty, size;
740         ImBuf *ibuf;
741         MovieClipUser user;
742
743         size= rendersize_to_number(proxy_render_size);
744         user.framenr= cfra;
745
746         get_proxy_fname(clip, proxy_render_size, cfra, name);
747
748         ibuf= BKE_movieclip_acquire_ibuf_flag(clip, &user, 0);
749
750         if(ibuf) {
751                 ImBuf *scaleibuf= ibuf;
752
753                 rectx= ibuf->x*size/100.f;
754                 recty= ibuf->y*size/100.f;
755
756                 if (ibuf->x != rectx || ibuf->y != recty) {
757                         if(ibuf->refcounter)    /* means buffer came from cache and shouldn't be modified */
758                                 scaleibuf= IMB_dupImBuf(ibuf);
759
760                         IMB_scalefastImBuf(scaleibuf, (short)rectx, (short)recty);
761                 }
762
763                 quality= clip->proxy.quality;
764                 scaleibuf->ftype= JPG | quality;
765
766                 /* unsupported feature only confuses other s/w */
767                 if(scaleibuf->depth==32)
768                         scaleibuf->depth= 24;
769
770                 BLI_lock_thread(LOCK_MOVIECLIP);
771
772                 BLI_make_existing_file(name);
773                 if(IMB_saveiff(scaleibuf, name, IB_rect)==0)
774                         perror(name);
775
776                 BLI_unlock_thread(LOCK_MOVIECLIP);
777
778                 IMB_freeImBuf(ibuf);
779                 if(scaleibuf!=ibuf) IMB_freeImBuf(scaleibuf);
780         }
781 }
782
783 void free_movieclip(MovieClip *clip)
784 {
785         free_buffers(clip);
786
787         BKE_tracking_free(&clip->tracking);
788 }
789
790 void unlink_movieclip(Main *bmain, MovieClip *clip)
791 {
792         bScreen *scr;
793         ScrArea *area;
794         SpaceLink *sl;
795
796         /* text space */
797         for(scr= bmain->screen.first; scr; scr= scr->id.next) {
798                 for(area= scr->areabase.first; area; area= area->next) {
799                         for(sl= area->spacedata.first; sl; sl= sl->next) {
800                                 if(sl->spacetype==SPACE_CLIP) {
801                                         SpaceClip *sc= (SpaceClip*) sl;
802
803                                         if(sc->clip==clip) {
804                                                 sc->clip= NULL;
805                                         }
806                                 }
807                         }
808                 }
809         }
810
811         clip->id.us= 0;
812 }