Camera tracking integration
[blender.git] / source / blender / blenkernel / intern / tracking.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/tracking.c
30  *  \ingroup bke
31  */
32
33 #include <stddef.h>
34 #include <limits.h>
35 #include <math.h>
36 #include <memory.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_movieclip_types.h"
41 #include "DNA_object_types.h"   /* SELECT */
42 #include "DNA_scene_types.h"
43
44 #include "BLI_utildefines.h"
45 #include "BLI_math.h"
46 #include "BLI_listbase.h"
47 #include "BLI_ghash.h"
48
49 #include "BKE_global.h"
50 #include "BKE_tracking.h"
51 #include "BKE_movieclip.h"
52 #include "BKE_object.h"
53 #include "BKE_scene.h"
54
55 #include "IMB_imbuf_types.h"
56 #include "IMB_imbuf.h"
57
58 #ifdef WITH_LIBMV
59 #include "libmv-capi.h"
60 #endif
61
62 /*********************** common functions *************************/
63
64 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
65 {
66         int a;
67
68         /* sort */
69         for(a= 0; a<2; a++) {
70                 if(track->pat_min[a]>track->pat_max[a])
71                         SWAP(float, track->pat_min[a], track->pat_max[a]);
72
73                 if(track->search_min[a]>track->search_max[a])
74                         SWAP(float, track->search_min[a], track->search_max[a]);
75         }
76
77         if(event==CLAMP_PAT_DIM) {
78                 for(a= 0; a<2; a++) {
79                         /* pattern shouldn't be resized bigger than search */
80                         track->pat_min[a]= MAX2(track->pat_min[a], track->search_min[a]);
81                         track->pat_max[a]= MIN2(track->pat_max[a], track->search_max[a]);
82                 }
83         }
84         else if(event==CLAMP_PAT_POS) {
85                 float dim[2];
86                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
87
88                 for(a= 0; a<2; a++) {
89                         /* pattern shouldn't be moved outside of search */
90                         if(track->pat_min[a] < track->search_min[a]) {
91                                 track->pat_min[a]= track->search_min[a];
92                                 track->pat_max[a]= track->pat_min[a]+dim[a];
93                         }
94                         if(track->pat_max[a] > track->search_max[a]) {
95                                 track->pat_max[a]= track->search_max[a];
96                                 track->pat_min[a]= track->pat_max[a]-dim[a];
97                         }
98                 }
99         }
100         else if(event==CLAMP_SEARCH_DIM) {
101                 for(a= 0; a<2; a++) {
102                         /* search shouldn't be resized smaller than pattern */
103                         track->search_min[a]= MIN2(track->pat_min[a], track->search_min[a]);
104                         track->search_max[a]= MAX2(track->pat_max[a], track->search_max[a]);
105                 }
106         }
107         else if(event==CLAMP_SEARCH_POS) {
108                 float dim[2];
109                 sub_v2_v2v2(dim, track->search_max, track->search_min);
110
111                 for(a= 0; a<2; a++) {
112                         /* search shouldn't be moved inside pattern */
113                         if(track->search_min[a] > track->pat_min[a]) {
114                                 track->search_min[a]= track->pat_min[a];
115                                 track->search_max[a]= track->search_min[a]+dim[a];
116                         }
117                         if(track->search_max[a] < track->pat_max[a]) {
118                                 track->search_max[a]= track->pat_max[a];
119                                 track->search_min[a]= track->search_max[a]-dim[a];
120                         }
121                 }
122         }
123
124         /* marker's center should be in center of pattern */
125         if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
126                 float dim[2];
127                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
128
129                 for(a= 0; a<2; a++) {
130                         track->pat_min[a]= -dim[a]/2.f;
131                         track->pat_max[a]= dim[a]/2.f;
132                 }
133         }
134 }
135
136 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
137 {
138         if(area==TRACK_AREA_NONE)
139                 return;
140
141         if(clear) {
142                 if(area&TRACK_AREA_POINT)       track->flag&= ~flag;
143                 if(area&TRACK_AREA_PAT)         track->pat_flag&= ~flag;
144                 if(area&TRACK_AREA_SEARCH)      track->search_flag&= ~flag;
145         } else {
146                 if(area&TRACK_AREA_POINT)       track->flag|= flag;
147                 if(area&TRACK_AREA_PAT)         track->pat_flag|= flag;
148                 if(area&TRACK_AREA_SEARCH)      track->search_flag|= flag;
149         }
150 }
151
152 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y,
153                         int framenr, int width, int height)
154 {
155         MovieTrackingTrack *track;
156         MovieTrackingMarker marker;
157         float pat[2]= {5.5f, 5.5f}, search[2]= {80.5f, 80.5f}; /* TODO: move to default setting? */
158
159         pat[0] /= (float)width;
160         pat[1] /= (float)height;
161
162         search[0] /= (float)width;
163         search[1] /= (float)height;
164
165         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
166         strcpy(track->name, "Track");
167
168         memset(&marker, 0, sizeof(marker));
169         marker.pos[0]= x;
170         marker.pos[1]= y;
171         marker.framenr= framenr;
172
173         copy_v2_v2(track->pat_max, pat);
174         negate_v2_v2(track->pat_min, pat);
175
176         copy_v2_v2(track->search_max, search);
177         negate_v2_v2(track->search_min, search);
178
179         BKE_tracking_insert_marker(track, &marker);
180
181         BLI_addtail(&tracking->tracks, track);
182         BKE_track_unique_name(tracking, track);
183
184         return track;
185 }
186
187 void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
188 {
189         MovieTrackingMarker *old_marker= BKE_tracking_get_marker(track, marker->framenr);
190
191         if(old_marker && old_marker->framenr==marker->framenr) {
192                 *old_marker= *marker;
193         } else {
194                 int a= track->markersnr;
195
196                 while(a--) {
197                         if(track->markers[a].framenr<marker->framenr)
198                                 break;
199                 }
200
201                 track->markersnr++;
202
203                 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
204                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
205
206                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
207                 track->markers[a+1]= *marker;
208
209                 track->last_marker= a+1;
210         }
211 }
212
213 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
214 {
215         int a= 0;
216
217         while(a<track->markersnr) {
218                 if(track->markers[a].framenr==framenr) {
219                         if(track->markersnr>1) {
220                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
221                                 track->markersnr--;
222                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
223                         } else {
224                                 MEM_freeN(track->markers);
225                                 track->markers= NULL;
226                                 track->markersnr= 0;
227                         }
228
229                         break;
230                 }
231
232                 a++;
233         }
234 }
235
236 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
237 {
238         int a= track->markersnr-1;
239
240         if(!track->markersnr)
241                 return NULL;
242
243         /* approximate pre-first framenr marker with first marker */
244         if(framenr<track->markers[0].framenr)
245                 return &track->markers[0];
246
247         if(track->last_marker<track->markersnr)
248                 a= track->last_marker;
249
250         if(track->markers[a].framenr<=framenr) {
251                 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
252                         if(track->markers[a].framenr==framenr) {
253                                 track->last_marker= a;
254                                 return &track->markers[a];
255                         }
256                         a++;
257                 }
258
259                 /* if there's no marker for exact position, use nearest marker from left side */
260                 return &track->markers[a-1];
261         } else {
262                 while(a>=0 && track->markers[a].framenr>=framenr) {
263                         if(track->markers[a].framenr==framenr) {
264                                 track->last_marker= a;
265                                 return &track->markers[a];
266                         }
267
268                         a--;
269                 }
270
271                 /* if there's no marker for exact position, use nearest marker from left side */
272                 return &track->markers[a];
273         }
274
275         return NULL;
276 }
277
278 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
279 {
280         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
281
282         if(marker && marker->framenr!=framenr) {
283                 MovieTrackingMarker marker_new;
284
285                 marker_new= *marker;
286                 marker_new.framenr= framenr;
287
288                 BKE_tracking_insert_marker(track, &marker_new);
289                 marker= BKE_tracking_get_marker(track, framenr);
290         }
291
292         return marker;
293 }
294
295 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
296 {
297         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
298
299         if(marker && marker->framenr!=framenr)
300                 return NULL;
301
302         return marker;
303 }
304
305 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
306 {
307         return BKE_tracking_exact_marker(track, framenr) != 0;
308 }
309
310 void BKE_tracking_free_track(MovieTrackingTrack *track)
311 {
312         if(track->markers) MEM_freeN(track->markers);
313 }
314
315 MovieTrackingTrack *BKE_tracking_copy_track(MovieTrackingTrack *track)
316 {
317         MovieTrackingTrack *new_track= MEM_dupallocN(track);
318
319         new_track->next= new_track->prev= NULL;
320
321         if(new_track->markers)
322                 new_track->markers= MEM_dupallocN(new_track->markers);
323
324         return new_track;
325 }
326
327 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
328 {
329         int a;
330
331         if(action==TRACK_CLEAR_REMAINED) {
332                 a= 1;
333                 while(a<track->markersnr) {
334                         if(track->markers[a].framenr>ref_frame) {
335                                 track->markersnr= a;
336                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
337
338                                 break;
339                         }
340
341                         a++;
342                 }
343         } else if(action==TRACK_CLEAR_UPTO) {
344                 a= track->markersnr-1;
345                 while(a>=0) {
346                         if(track->markers[a].framenr<=ref_frame) {
347                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
348
349                                 track->markersnr= track->markersnr-a;
350                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
351
352                                 break;
353                         }
354
355                         a--;
356                 }
357         } else if(action==TRACK_CLEAR_ALL) {
358                 MovieTrackingMarker *marker, marker_new;
359
360                 marker= BKE_tracking_get_marker(track, ref_frame);
361                 if(marker)
362                         marker_new= *marker;
363
364                 MEM_freeN(track->markers);
365                 track->markers= NULL;
366                 track->markersnr= 0;
367
368                 if(marker)
369                         BKE_tracking_insert_marker(track, &marker_new);
370         }
371 }
372
373 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
374 {
375         int i, a= 0, b= 0, tot= dst_track->markersnr+src_track->markersnr;
376         int count= 0;
377
378         for(i= 0; i<tot; i++) {
379                 if(a>=src_track->markersnr) {
380                         b++;
381                         count++;
382                 }
383                 else if(b>=dst_track->markersnr) {
384                         a++;
385                         count++;
386                 }
387                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
388                         a++;
389                         count++;
390                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
391                         b++;
392                         count++;
393                 } else {
394                         if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
395                                 return 0;
396
397                         a++;
398                         b++;
399                         count++;
400                 }
401         }
402
403         return count;
404 }
405
406 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
407 {
408         int i, a= 0, b= 0, tot;
409         MovieTrackingMarker *markers;
410
411         tot= BKE_tracking_test_join_tracks(dst_track, src_track);
412
413         markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
414
415         for(i= 0; i<tot; i++) {
416                 if(b>=dst_track->markersnr) {
417                         markers[i]= src_track->markers[a++];
418                 }
419                 else if(a>=src_track->markersnr) {
420                         markers[i]= dst_track->markers[b++];
421                 }
422                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
423                         markers[i]= src_track->markers[a++];
424                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
425                         markers[i]= dst_track->markers[b++];
426                 } else {
427                         if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
428                         else markers[i]= src_track->markers[a++];
429
430                         a++;
431                         b++;
432                 }
433         }
434
435         MEM_freeN(dst_track->markers);
436
437         dst_track->markers= markers;
438         dst_track->markersnr= tot;
439 }
440
441 void BKE_tracking_free(MovieTracking *tracking)
442 {
443         MovieTrackingTrack *track;
444
445         for(track= tracking->tracks.first; track; track= track->next) {
446                 BKE_tracking_free_track(track);
447         }
448
449         BLI_freelistN(&tracking->tracks);
450
451         if(tracking->camera.reconstructed)
452                 MEM_freeN(tracking->camera.reconstructed);
453
454         if(tracking->stabilization.ibuf)
455                 IMB_freeImBuf(tracking->stabilization.ibuf);
456
457         if(tracking->stabilization.scaleibuf)
458                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
459 }
460
461 /*********************** tracking *************************/
462
463 typedef struct TrackContext {
464         MovieTrackingTrack *track;
465
466 #ifdef WITH_LIBMV
467         struct libmv_RegionTracker *region_tracker;
468 #endif
469 } TrackContext;
470
471 typedef struct MovieTrackingContext {
472         MovieClipUser user;
473         MovieClip *clip;
474
475         TrackContext *track_context;
476         int num_tracks;
477
478         GHash *hash;
479         MovieTrackingSettings settings;
480
481         int backwards;
482         int sync_frame;
483 } MovieTrackingContext;
484
485 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, int backwards)
486 {
487         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
488         MovieTracking *tracking= &clip->tracking;
489         MovieTrackingSettings *settings= &tracking->settings;
490         MovieTrackingTrack *track;
491         TrackContext *track_context;
492
493         context->settings= *settings;
494         context->backwards= backwards;
495         context->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "tracking trackHash");
496         context->sync_frame= user->framenr;
497
498         /* count */
499         track= tracking->tracks.first;
500         while(track) {
501                 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
502                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
503
504                         if((marker->flag&MARKER_DISABLED)==0)
505                                 context->num_tracks++;
506                 }
507
508                 track= track->next;
509         }
510
511         if(context->num_tracks) {
512                 int width, height;
513
514                 BKE_movieclip_acquire_size(clip, user, &width, &height);
515
516                 /* create tracking data */
517                 context->track_context= MEM_callocN(sizeof(TrackContext)*context->num_tracks, "tracking track_context");
518
519                 track_context= context->track_context;
520                 track= tracking->tracks.first;
521                 while(track) {
522                         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
523                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
524
525                                 if((marker->flag&MARKER_DISABLED)==0) {
526                                         MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
527
528                                         track_context->track= new_track;
529
530 #ifdef WITH_LIBMV
531                                         {
532                                                 float search_size_x= (track->search_max[0]-track->search_min[0])*width;
533                                                 float search_size_y= (track->search_max[1]-track->search_min[1])*height;
534                                                 float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
535                                                 float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
536
537                                                 int level= log(2.0f * MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y))/M_LN2;
538
539                                                 track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
540                                         }
541 #endif
542
543                                         BLI_ghash_insert(context->hash, new_track, track);
544
545                                         track_context++;
546                                 }
547                         }
548
549                         track= track->next;
550                 }
551         }
552
553         context->clip= clip;
554         context->user= *user;
555
556         return context;
557 }
558
559 void BKE_tracking_context_free(MovieTrackingContext *context)
560 {
561         int a;
562         TrackContext *track_context;
563
564         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
565                 BKE_tracking_free_track(context->track_context[a].track);
566
567 #if WITH_LIBMV
568                 libmv_regionTrackerDestroy(track_context->region_tracker);
569 #endif
570
571                 MEM_freeN(track_context->track);
572         }
573
574         if(context->track_context)
575                 MEM_freeN(context->track_context);
576
577         BLI_ghash_free(context->hash, NULL, NULL);
578
579         MEM_freeN(context);
580 }
581
582 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
583 {
584         int x, y;
585
586         if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
587                 return;
588
589         for(y= 0; y<ibuf->y; y++) {
590                 for (x= 0; x<ibuf->x; x++) {
591                         int pixel= ibuf->x*y + x;
592
593                         if(ibuf->rect_float) {
594                                 float *rrgbf= ibuf->rect_float + pixel*4;
595
596                                 if(track->flag&TRACK_DISABLE_RED)       rrgbf[0]= 0;
597                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgbf[1]= 0;
598                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgbf[2]= 0;
599                         } else {
600                                 char *rrgb= (char*)ibuf->rect + pixel*4;
601
602                                 if(track->flag&TRACK_DISABLE_RED)       rrgb[0]= 0;
603                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgb[1]= 0;
604                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgb[2]= 0;
605                         }
606                 }
607         }
608 }
609
610 static ImBuf *acquire_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
611                         float min[2], float max[2], int margin, float pos[2], int origin[2])
612 {
613         ImBuf *tmpibuf;
614         int x, y;
615         int x1, y1, x2, y2, w, h;
616
617         x= marker->pos[0]*ibuf->x;
618         y= marker->pos[1]*ibuf->y;
619         x1= x-(int)(-min[0]*ibuf->x);
620         y1= y-(int)(-min[1]*ibuf->y);
621         x2= x+(int)(max[0]*ibuf->x);
622         y2= y+(int)(max[1]*ibuf->y);
623
624         /* dimensions should be odd */
625         w= (x2-x1)|1;
626         h= (y2-y1)|1;
627
628         /* happens due to rounding issues */
629         if(x1+w<=x) x1++;
630         if(y1+h<=y) y1++;
631
632         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
633         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
634
635         if(pos != NULL) {
636                 pos[0]= x-x1+(marker->pos[0]*ibuf->x-x)+margin;
637                 pos[1]= y-y1+(marker->pos[1]*ibuf->y-y)+margin;
638         }
639
640         if(origin != NULL) {
641                 origin[0]= x1-margin;
642                 origin[1]= y1-margin;
643         }
644
645         disable_imbuf_channels(tmpibuf, track);
646
647         return tmpibuf;
648 }
649
650 ImBuf *BKE_tracking_acquire_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
651                         int margin, float pos[2], int origin[2])
652 {
653         return acquire_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, pos, origin);
654 }
655
656 ImBuf *BKE_tracking_acquire_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
657                         int margin, float pos[2], int origin[2])
658 {
659         return acquire_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, pos, origin);
660 }
661
662 #ifdef WITH_LIBMV
663 static float *acquire_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
664                         int *width_r, int *height_r, float pos[2], int origin[2])
665 {
666         ImBuf *tmpibuf;
667         float *pixels, *fp;
668         int x, y, width, height;
669
670         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
671         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
672
673         tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, pos, origin);
674         disable_imbuf_channels(tmpibuf, track);
675
676         *width_r= width;
677         *height_r= height;
678
679         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
680         for(y= 0; y<(int)height; y++) {
681                 for (x= 0; x<(int)width; x++) {
682                         int pixel= tmpibuf->x*y + x;
683
684                         if(tmpibuf->rect_float) {
685                                 float *rrgbf= ibuf->rect_float + pixel*4;
686
687                                 *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2])/255;
688                         } else {
689                                 char *rrgb= (char*)tmpibuf->rect + pixel*4;
690
691                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255;
692                         }
693
694                         fp++;
695                 }
696         }
697
698         IMB_freeImBuf(tmpibuf);
699
700         return pixels;
701 }
702 #endif
703
704 void BKE_tracking_sync(MovieTrackingContext *context)
705 {
706         TrackContext *track_context;
707         MovieTrackingTrack *track;
708         ListBase tracks= {NULL, NULL};
709         ListBase *old_tracks= &context->clip->tracking.tracks;
710         int a, sel_type, newframe;
711         void *sel;
712
713         BKE_movieclip_last_selection(context->clip, &sel_type, &sel);
714
715         /* duplicate currently tracking tracks to list of displaying tracks */
716         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
717                 int replace_sel= 0;
718                 MovieTrackingTrack *new_track, *old;
719
720                 track= track_context->track;
721
722                 /* find original of tracking track in list of previously displayed tracks */
723                 old= BLI_ghash_lookup(context->hash, track);
724                 if(old) {
725                         MovieTrackingTrack *cur= old_tracks->first;
726
727                         while(cur) {
728                                 if(cur==old)
729                                         break;
730
731                                 cur= cur->next;
732                         }
733
734                         /* original track was found, re-use flags and remove this track */
735                         if(cur) {
736                                 if(sel_type==MCLIP_SEL_TRACK && sel==cur)
737                                         replace_sel= 1;
738
739                                 track->flag= cur->flag;
740                                 track->pat_flag= cur->pat_flag;
741                                 track->search_flag= cur->search_flag;
742
743                                 BKE_tracking_free_track(cur);
744                                 BLI_freelinkN(old_tracks, cur);
745                         }
746                 }
747
748                 new_track= BKE_tracking_copy_track(track);
749
750                 BLI_ghash_remove(context->hash, track, NULL, NULL); /* XXX: are we actually need this */
751                 BLI_ghash_insert(context->hash, track, new_track);
752
753                 if(replace_sel)         /* update current selection in clip */
754                         BKE_movieclip_set_selection(context->clip, MCLIP_SEL_TRACK, new_track);
755
756                 BLI_addtail(&tracks, new_track);
757         }
758
759         /* move tracks, which could be added by user during tracking */
760         track= old_tracks->first;
761         while(track) {
762                 MovieTrackingTrack *next= track->next;
763
764                 track->next= track->prev= NULL;
765                 BLI_addtail(&tracks, track);
766
767                 track= next;
768         }
769
770         context->clip->tracking.tracks= tracks;
771
772         if(context->backwards) newframe= context->user.framenr+1;
773         else newframe= context->user.framenr-1;
774
775         context->sync_frame= newframe;
776 }
777
778 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
779 {
780         user->framenr= context->sync_frame;
781 }
782
783 int BKE_tracking_next(MovieTrackingContext *context)
784 {
785         ImBuf *ibuf, *ibuf_new;
786         int curfra= context->user.framenr;
787         int a, ok= 0;
788
789         /* nothing to track, avoid unneeded frames reading to save time and memory */
790         if(!context->num_tracks)
791                 return 0;
792
793         ibuf= BKE_movieclip_acquire_ibuf(context->clip, &context->user);
794         if(!ibuf) return 0;
795
796         if(context->backwards) context->user.framenr--;
797         else context->user.framenr++;
798
799         ibuf_new= BKE_movieclip_acquire_ibuf(context->clip, &context->user);
800         if(!ibuf_new) {
801                 IMB_freeImBuf(ibuf);
802                 return 0;
803         }
804
805         #pragma omp parallel for private(a) shared(ibuf, ibuf_new, ok)
806         for(a= 0; a<context->num_tracks; a++) {
807                 TrackContext *track_context= &context->track_context[a];
808                 MovieTrackingTrack *track= track_context->track;
809                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, curfra);
810
811                 if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
812 #ifdef WITH_LIBMV
813                         int width, height, origin[2];
814                         float pos[2];
815                         float *patch, *patch_new;
816                         double x1, y1, x2, y2;
817                         int wndx, wndy;
818                         MovieTrackingMarker marker_new;
819
820                         patch= acquire_search_floatbuf(ibuf, track, marker, &width, &height, pos, origin);
821                         patch_new= acquire_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
822
823                         x1= pos[0];
824                         y1= pos[1];
825
826                         x2= x1;
827                         y2= y1;
828
829                         wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf->x)/2;
830                         wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf->y)/2;
831
832                         if(libmv_regionTrackerTrack(track_context->region_tracker, patch, patch_new,
833                                                 width, height, MAX2(wndx, wndy),
834                                                 x1, y1, &x2, &y2)) {
835                                 memset(&marker_new, 0, sizeof(marker_new));
836                                 marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
837                                 marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
838                                 marker_new.flag|= MARKER_TRACKED;
839
840                                 if(context->backwards) marker_new.framenr= curfra-1;
841                                 else marker_new.framenr= curfra+1;
842
843                                 #pragma omp critical
844                                 {
845                                         BKE_tracking_insert_marker(track, &marker_new);
846                                 }
847
848                         } else {
849                                 marker_new= *marker;
850
851                                 if(context->backwards) marker_new.framenr--;
852                                 else marker_new.framenr++;
853
854                                 marker_new.flag|= MARKER_DISABLED;
855
856                                 #pragma omp critical
857                                 {
858                                         BKE_tracking_insert_marker(track, &marker_new);
859                                 }
860                         }
861
862                         MEM_freeN(patch);
863                         MEM_freeN(patch_new);
864
865                         ok= 1;
866 #endif
867                 }
868         }
869
870         IMB_freeImBuf(ibuf);
871         IMB_freeImBuf(ibuf_new);
872
873         return ok;
874 }
875
876 #if WITH_LIBMV
877 static struct libmv_Tracks *create_libmv_tracks(MovieClip *clip)
878 {
879         int width, height;
880         int tracknr= 0;
881         MovieTrackingTrack *track;
882         struct libmv_Tracks *tracks= libmv_tracksNew();;
883
884         /* XXX: could fail if footage uses images with different sizes */
885         BKE_movieclip_acquire_size(clip, NULL, &width, &height);
886
887         track= clip->tracking.tracks.first;
888         while(track) {
889                 int a= 0;
890
891                 for(a= 0; a<track->markersnr; a++) {
892                         MovieTrackingMarker *marker= &track->markers[a];
893
894                         if((marker->flag&MARKER_DISABLED)==0)
895                                 libmv_tracksInsert(tracks, marker->framenr, tracknr, marker->pos[0]*width, marker->pos[1]*height);
896                 }
897
898                 track= track->next;
899                 tracknr++;
900         }
901
902         return tracks;
903 }
904
905 static int retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstruction *reconstruction)
906 {
907         int tracknr= 0;
908         int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0;
909         MovieTracking *tracking= &clip->tracking;
910         MovieTrackingTrack *track;
911         MovieTrackingCamera *camera;
912         MovieReconstructedCamera *reconstructed;
913         float origin[3]= {0.0f, 0.f, 0.0f};
914         int ok= 1;
915
916         track= tracking->tracks.first;
917         while(track) {
918                 double pos[3];
919
920                 if(libmv_reporojectionPointForTrack(reconstruction, tracknr, pos)) {
921                         track->bundle_pos[0]= pos[0];
922                         track->bundle_pos[1]= pos[1];
923                         track->bundle_pos[2]= pos[2];
924
925                         track->flag|= TRACK_HAS_BUNDLE;
926                 } else {
927                         track->flag&= ~TRACK_HAS_BUNDLE;
928                         ok= 0;
929
930                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
931                 }
932
933                 if(track->markersnr) {
934                         if(track->markers[0].framenr<sfra) sfra= track->markers[0].framenr;
935                         if(track->markers[track->markersnr-1].framenr>efra) efra= track->markers[track->markersnr-1].framenr;
936                 }
937
938                 track= track->next;
939                 tracknr++;
940         }
941
942         camera= &tracking->camera;
943
944         if(camera->reconstructed)
945                 MEM_freeN(camera->reconstructed);
946
947         camera->reconnr= 0;
948         camera->reconstructed= NULL;
949         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
950
951         for(a= sfra; a<=efra; a++) {
952                 double matd[4][4];
953
954                 if(libmv_reporojectionCameraForImage(reconstruction, a, matd)) {
955                         int i, j;
956                         float mat[4][4];
957
958                         for(i=0; i<4; i++)
959                                 for(j= 0; j<4; j++)
960                                         mat[i][j]= matd[i][j];
961
962                         if(!origin_set) {
963                                 copy_v3_v3(origin, mat[3]);
964                                 origin_set= 1;
965                         }
966
967                         if(origin_set)
968                                 sub_v3_v3(mat[3], origin);
969
970                         copy_m4_m4(reconstructed[camera->reconnr].mat, mat);
971                         reconstructed[camera->reconnr].framenr= a;
972                         camera->reconnr++;
973                 } else {
974                         ok= 0;
975                         printf("No camera for frame %d\n", a);
976                 }
977         }
978
979         if(camera->reconnr) {
980                 camera->reconstructed= MEM_callocN(camera->reconnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
981                 memcpy(camera->reconstructed, reconstructed, camera->reconnr*sizeof(MovieReconstructedCamera));
982         }
983
984         if(origin_set) {
985                 track= tracking->tracks.first;
986                 while(track) {
987                         if(track->flag&TRACK_HAS_BUNDLE)
988                                 sub_v3_v3(track->bundle_pos, origin);
989
990                         track= track->next;
991                 }
992         }
993
994         MEM_freeN(reconstructed);
995
996         return ok;
997 }
998
999 #endif
1000
1001 float BKE_tracking_solve_reconstruction(MovieClip *clip)
1002 {
1003 #if WITH_LIBMV
1004         {
1005                 MovieTrackingCamera *camera= &clip->tracking.camera;
1006                 MovieTracking *tracking= &clip->tracking;
1007                 struct libmv_Tracks *tracks= create_libmv_tracks(clip);
1008                 struct libmv_Reconstruction *reconstruction = libmv_solveReconstruction(tracks,
1009                         tracking->settings.keyframe1, tracking->settings.keyframe2,
1010                         camera->focal, camera->principal[0], camera->principal[1],
1011                         camera->k1, camera->k2, camera->k3);
1012                 float error= libmv_reprojectionError(reconstruction);
1013
1014                 if(!retrive_libmv_reconstruct(clip, reconstruction))
1015                         error= -1.f;
1016
1017                 libmv_destroyReconstruction(reconstruction);
1018                 libmv_tracksDestroy(tracks);
1019
1020                 return error;
1021         }
1022 #endif
1023 }
1024
1025 void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
1026 {
1027         BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1028 }
1029
1030 MovieTrackingTrack *BKE_find_track_by_name(MovieTracking *tracking, const char *name)
1031 {
1032         MovieTrackingTrack *track= tracking->tracks.first;
1033
1034         while(track) {
1035                 if(!strcmp(track->name, name))
1036                         return track;
1037
1038                 track= track->next;
1039         }
1040
1041         return NULL;
1042 }
1043
1044 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
1045 {
1046         MovieTrackingCamera *camera= &tracking->camera;
1047         int a= 0, d= 1;
1048
1049         if(!camera->reconnr)
1050                 return NULL;
1051
1052         if(camera->last_camera<camera->reconnr)
1053                 a= camera->last_camera;
1054
1055         if(camera->reconstructed[a].framenr>=framenr)
1056                 d= -1;
1057
1058         while(a>=0 && a<camera->reconnr) {
1059                 if(camera->reconstructed[a].framenr==framenr) {
1060                         camera->last_camera= a;
1061                         return &camera->reconstructed[a];
1062
1063                         break;
1064                 }
1065
1066                 a+= d;
1067         }
1068
1069         return NULL;
1070 }
1071
1072 void BKE_get_tracking_mat(Scene *scene, float mat[4][4])
1073 {
1074         if(!scene->camera)
1075                 scene->camera= scene_find_camera(scene);
1076
1077         if(scene->camera)
1078                 where_is_object_mat(scene, scene->camera, mat);
1079         else
1080                 unit_m4(mat);
1081 }
1082
1083 void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
1084 {
1085         MovieReconstructedCamera *camera;
1086         float lens= tracking->camera.focal*32.0f/(float)winx;
1087         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
1088         float winmat[4][4];
1089
1090         clipsta= 0.1f;
1091         clipend= 1000.0f;
1092
1093         if(winx >= winy)
1094                 viewfac= (lens*winx)/32.0f;
1095         else
1096                 viewfac= (lens*winy)/32.0f;
1097
1098         pixsize= clipsta/viewfac;
1099
1100         left= -0.5f*(float)winx*pixsize;
1101         bottom= -0.5f*(float)winy*pixsize;
1102         right=  0.5f*(float)winx*pixsize;
1103         top=  0.5f*(float)winy*pixsize;
1104
1105         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
1106
1107         camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
1108         if(camera) {
1109                 float imat[4][4];
1110
1111                 invert_m4_m4(imat, camera->mat);
1112                 mul_m4_m4m4(mat, imat, winmat);
1113         } else copy_m4_m4(mat, winmat);
1114 }
1115
1116 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float width, float height, float nco[2])
1117 {
1118         MovieTrackingCamera *camera= &tracking->camera;
1119
1120 #ifdef WITH_LIBMV
1121         double x, y;
1122
1123         /* normalize coords */
1124         x= (co[0]-camera->principal[0]) / camera->focal;
1125         y= (co[1]-camera->principal[1]) / camera->focal;
1126
1127         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1],
1128                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1129
1130         /* result is in image coords already */
1131         nco[0]= x;
1132         nco[1]= y;
1133 #endif
1134 }
1135
1136 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float width, float height, float nco[2])
1137 {
1138         MovieTrackingCamera *camera= &tracking->camera;
1139
1140 #ifdef WITH_LIBMV
1141         double x= co[0], y= co[1];
1142
1143         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1],
1144                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1145
1146         nco[0]= x * camera->focal + camera->principal[0];
1147         nco[1]= y * camera->focal + camera->principal[1];
1148 #endif
1149 }
1150
1151 #ifdef WITH_LIBMV
1152 /* flips upside-down */
1153 static unsigned char *acquire_ucharbuf(ImBuf *ibuf)
1154 {
1155         int x, y;
1156         unsigned char *pixels, *fp;
1157
1158         fp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
1159         for(y= 0; y<ibuf->y; y++) {
1160                 for (x= 0; x<ibuf->x; x++) {
1161                         int pixel= ibuf->x*(ibuf->y-y-1) + x;
1162
1163                         if(ibuf->rect_float) {
1164                                 float *rrgbf= ibuf->rect_float + pixel*4;
1165
1166                                 //*fp= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
1167                                 *fp= (11*rrgbf[0]+16*rrgbf[1]+5*rrgbf[2])/32;
1168                         } else {
1169                                 char *rrgb= (char*)ibuf->rect + pixel*4;
1170
1171                                 //*fp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
1172                                 *fp= (11*rrgb[0]+16*rrgb[1]+5*rrgb[2])/32;
1173                         }
1174
1175                         fp++;
1176                 }
1177         }
1178
1179         return pixels;
1180 }
1181 #endif
1182
1183 void BKE_tracking_detect(MovieTracking *tracking, ImBuf *ibuf, int framenr)
1184 {
1185 #ifdef WITH_LIBMV
1186         struct libmv_Corners *corners;
1187         unsigned char *pixels= acquire_ucharbuf(ibuf);
1188         int a;
1189
1190         corners= libmv_detectCorners(pixels, ibuf->x, ibuf->y, ibuf->x);
1191         MEM_freeN(pixels);
1192
1193         a= libmv_countCorners(corners);
1194         while(a--) {
1195                 MovieTrackingTrack *track;
1196
1197                 float x, y, size, score;
1198
1199                 libmv_getCorner(corners, a, &x, &y, &score, &size);
1200
1201                 track= BKE_tracking_add_track(tracking, x/ibuf->x, 1.0f-(y/ibuf->y), framenr, ibuf->x, ibuf->y);
1202                 track->flag|= SELECT;
1203                 track->pat_flag|= SELECT;
1204                 track->search_flag|= SELECT;
1205         }
1206
1207         libmv_destroyCorners(corners);
1208 #endif
1209 }
1210
1211 MovieTrackingTrack *BKE_tracking_indexed_bundle(MovieTracking *tracking, int bundlenr)
1212 {
1213         MovieTrackingTrack *track= tracking->tracks.first;
1214         int cur= 1;
1215
1216         while(track) {
1217                 if(track->flag&TRACK_HAS_BUNDLE) {
1218                         if(cur==bundlenr)
1219                                 return track;
1220
1221                         cur++;
1222                 }
1223
1224                 track= track->next;
1225         }
1226
1227         return NULL;
1228 }
1229
1230 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
1231 {
1232         int ok= 0;
1233         float min[2], max[2];
1234         MovieTrackingTrack *track;
1235
1236         INIT_MINMAX2(min, max);
1237
1238         track= tracking->tracks.first;
1239         while(track) {
1240                 if(track->flag&TRACK_USE_2D_STAB) {
1241                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
1242
1243                         DO_MINMAX2(marker->pos, min, max);
1244
1245                         ok= 1;
1246                 }
1247
1248                 track= track->next;
1249         }
1250
1251         median[0]= (max[0]+min[0])/2.f;
1252         median[1]= (max[1]+min[1])/2.f;
1253
1254         return ok;
1255 }
1256
1257 static float stabilization_auto_scale_factor(MovieTracking *tracking)
1258 {
1259         float firstmedian[2];
1260         MovieTrackingStabilization *stab= &tracking->stabilization;
1261
1262         if(stab->ok)
1263                 return stab->scale;
1264
1265         if(stabilization_median_point(tracking, 1, firstmedian)) {
1266                 int sfra= INT_MAX, efra= INT_MIN, cfra;
1267                 float delta[2]= {0.f, 0.f}, scalex, scaley, near[2]={1.f, 1.f};
1268                 MovieTrackingTrack *track;
1269
1270                 track= tracking->tracks.first;
1271                 while(track) {
1272                         if(track->flag&TRACK_USE_2D_STAB) {
1273                                 if(track->markersnr) {
1274                                         sfra= MIN2(sfra, track->markers[0].framenr);
1275                                         efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
1276                                 }
1277                         }
1278
1279                         track= track->next;
1280                 }
1281
1282                 for(cfra=sfra; cfra<=efra; cfra++) {
1283                         float median[2], d[2];
1284
1285                         stabilization_median_point(tracking, cfra, median);
1286
1287                         sub_v2_v2v2(d, firstmedian, median);
1288                         d[0]= fabsf(d[0]);
1289                         d[1]= fabsf(d[1]);
1290
1291                         delta[0]= MAX2(delta[0], d[0]);
1292                         delta[1]= MAX2(delta[1], d[1]);
1293
1294                         near[0]= MIN3(near[0], median[0], 1.f-median[0]);
1295                         near[1]= MIN3(near[1], median[1], 1.f-median[1]);
1296                 }
1297
1298                 near[0]= MAX2(near[0], 0.05);
1299                 near[1]= MAX2(near[1], 0.05);
1300
1301                 scalex= 1.f+delta[0]/near[0];
1302                 scaley= 1.f+delta[1]/near[1];
1303
1304                 stab->scale= MAX2(scalex, scaley);
1305         } else {
1306                 stab->scale= 1.f;
1307         }
1308
1309         stab->ok= 1;
1310
1311         return stab->scale;
1312 }
1313
1314 static void calculate_stabmat(MovieTrackingStabilization *stab, float width, float height,
1315                         float firstmedian[2], float curmedian[2], float mat[4][4])
1316 {
1317         unit_m4(mat);
1318
1319         mat[0][0]= stab->scale;
1320         mat[1][1]= stab->scale;
1321         mat[2][2]= stab->scale;
1322         mat[3][0]= (firstmedian[0]-curmedian[0])*width*stab->scale;
1323         mat[3][1]= (firstmedian[1]-curmedian[1])*height*stab->scale;
1324
1325         mat[3][0]-= (firstmedian[0]*stab->scale-firstmedian[0])*width;
1326         mat[3][1]-= (firstmedian[1]*stab->scale-firstmedian[1])*height;
1327 }
1328
1329 static int stabilize_need_recalc(MovieTracking *tracking, float width, float height,
1330                         float firstmedian[2], float curmedian[2], float mat[4][4])
1331 {
1332         float stabmat[4][4];
1333         MovieTrackingStabilization *stab= &tracking->stabilization;
1334
1335         if(!mat)
1336                 return 1;
1337
1338         if(stab->flag&TRACKING_AUTOSCALE)
1339                 stabilization_auto_scale_factor(tracking);
1340
1341         calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
1342
1343         return memcmp(mat, stabmat, sizeof(float)*16);
1344 }
1345
1346 static ImBuf* stabilize_acquire_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
1347 {
1348         int flags;
1349
1350         if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
1351                 IMB_freeImBuf(cacheibuf);
1352                 cacheibuf= NULL;
1353         }
1354
1355         flags= IB_rect;
1356
1357         if(srcibuf->rect_float)
1358                 flags|= IB_rectfloat;
1359
1360         if(cacheibuf) {
1361                 if(fill) {
1362                         float col[4]= {0.f, 0.f, 0.f, 0.f};
1363                         IMB_rectfill(cacheibuf, col);
1364                 }
1365         }
1366         else {
1367                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
1368                 cacheibuf->profile= srcibuf->profile;
1369         }
1370
1371         return cacheibuf;
1372 }
1373
1374 void BKE_tracking_stabilization_matrix(MovieTracking *tracking, int framenr, int width, int height, float mat[4][4])
1375 {
1376         float firstmedian[2], curmedian[2], stabmat[4][4];
1377         MovieTrackingStabilization *stab= &tracking->stabilization;
1378
1379         copy_m4_m4(stabmat, mat);
1380
1381         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1382                 unit_m4(mat);
1383
1384                 return;
1385         }
1386
1387         if(stabilization_median_point(tracking, 1, firstmedian)) {
1388                 stabilization_median_point(tracking, framenr, curmedian);
1389
1390                 if((stab->flag&TRACKING_AUTOSCALE)==0)
1391                                 stab->scale= 1.f;
1392
1393                 if(!stab->ok && stab->ibufok && stab->ibuf)
1394                         stab->ibufok= stabilize_need_recalc(tracking, width, height, firstmedian, curmedian, mat) == 0;
1395
1396                 if(!stab->ibuf || !stab->ibufok) {
1397                         if(stab->flag&TRACKING_AUTOSCALE)
1398                                 stabilization_auto_scale_factor(tracking);
1399
1400                         calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
1401
1402                         stab->ok= 1;
1403                 } else {
1404                         calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
1405                 }
1406         } else {
1407                 unit_m4(stabmat);
1408         }
1409
1410         if(mat)
1411                 copy_m4_m4(mat, stabmat);
1412 }
1413
1414 ImBuf *BKE_tracking_stabilize_shot(MovieTracking *tracking, int framenr, ImBuf *ibuf, float mat[4][4])
1415 {
1416         float firstmedian[2], curmedian[2], stabmat[4][4];
1417         MovieTrackingStabilization *stab= &tracking->stabilization;
1418
1419         if(mat)
1420                 copy_m4_m4(stabmat, mat);
1421
1422         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1423                 if(mat)
1424                         unit_m4(mat);
1425
1426                 return ibuf;
1427         }
1428
1429         if(stabilization_median_point(tracking, 1, firstmedian)) {
1430                 ImBuf *tmpibuf;
1431                 float width= ibuf->x, height= ibuf->y;
1432
1433                 stabilization_median_point(tracking, framenr, curmedian);
1434
1435                 if((stab->flag&TRACKING_AUTOSCALE)==0)
1436                                 stab->scale= 1.f;
1437
1438                 if(!stab->ok && stab->ibufok && stab->ibuf)
1439                         stab->ibufok= stabilize_need_recalc(tracking, width, height, firstmedian, curmedian, mat) == 0;
1440
1441                 if(!stab->ibuf || !stab->ibufok) {
1442                         tmpibuf= stabilize_acquire_ibuf(stab->ibuf, ibuf, 1);
1443                         stab->ibuf= tmpibuf;
1444
1445                         if(stab->flag&TRACKING_AUTOSCALE) {
1446                                 ImBuf *scaleibuf;
1447
1448                                 stabilization_auto_scale_factor(tracking);
1449
1450                                 scaleibuf= stabilize_acquire_ibuf(stab->scaleibuf, ibuf, 0);
1451                                 stab->scaleibuf= scaleibuf;
1452
1453                                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
1454                                 IMB_scalefastImBuf(scaleibuf, ibuf->x*stab->scale, ibuf->y*stab->scale);
1455
1456                                 ibuf= scaleibuf;
1457                         }
1458
1459                         calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
1460
1461                         IMB_rectcpy(tmpibuf, ibuf, stabmat[3][0], stabmat[3][1], 0, 0, ibuf->x, ibuf->y);
1462
1463                         tmpibuf->userflags|= IB_MIPMAP_INVALID;
1464
1465                         if(tmpibuf->rect_float)
1466                                 tmpibuf->userflags|= IB_RECT_INVALID;
1467                 } else {
1468                         calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
1469                         tmpibuf= stab->ibuf;
1470                 }
1471
1472                 stab->ibuf= tmpibuf;
1473                 IMB_refImBuf(stab->ibuf);
1474
1475                 if(mat)
1476                         copy_m4_m4(mat, stabmat);
1477
1478                 stab->ibufok= 1;
1479                 stab->ok= 1;
1480
1481                 return stab->ibuf;
1482         } else {
1483                 unit_m4(stabmat);
1484         }
1485
1486         if(mat)
1487                 copy_m4_m4(mat, stabmat);
1488
1489         return ibuf;
1490 }