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         /* XXX: not very nice to have such check here, but it will prevent
160                 complaints about bad default settings for new markers */
161         if(tracking->settings.tracker==TRACKER_SAD) {
162                 pat[0]= 8.f;
163                 pat[1]= 8.f;
164
165                 search[0]= 32.f;
166                 search[1]= 32.f;
167         }
168
169         pat[0] /= (float)width;
170         pat[1] /= (float)height;
171
172         search[0] /= (float)width;
173         search[1] /= (float)height;
174
175         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
176         strcpy(track->name, "Track");
177
178         memset(&marker, 0, sizeof(marker));
179         marker.pos[0]= x;
180         marker.pos[1]= y;
181         marker.framenr= framenr;
182
183         copy_v2_v2(track->pat_max, pat);
184         negate_v2_v2(track->pat_min, pat);
185
186         copy_v2_v2(track->search_max, search);
187         negate_v2_v2(track->search_min, search);
188
189         BKE_tracking_insert_marker(track, &marker);
190
191         BLI_addtail(&tracking->tracks, track);
192         BKE_track_unique_name(tracking, track);
193
194         return track;
195 }
196
197 void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
198 {
199         MovieTrackingMarker *old_marker= BKE_tracking_get_marker(track, marker->framenr);
200
201         if(old_marker && old_marker->framenr==marker->framenr) {
202                 *old_marker= *marker;
203         } else {
204                 int a= track->markersnr;
205
206                 while(a--) {
207                         if(track->markers[a].framenr<marker->framenr)
208                                 break;
209                 }
210
211                 track->markersnr++;
212
213                 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
214                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
215
216                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
217                 track->markers[a+1]= *marker;
218
219                 track->last_marker= a+1;
220         }
221 }
222
223 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
224 {
225         int a= 0;
226
227         while(a<track->markersnr) {
228                 if(track->markers[a].framenr==framenr) {
229                         if(track->markersnr>1) {
230                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
231                                 track->markersnr--;
232                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
233                         } else {
234                                 MEM_freeN(track->markers);
235                                 track->markers= NULL;
236                                 track->markersnr= 0;
237                         }
238
239                         break;
240                 }
241
242                 a++;
243         }
244 }
245
246 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
247 {
248         int a= track->markersnr-1;
249
250         if(!track->markersnr)
251                 return NULL;
252
253         /* approximate pre-first framenr marker with first marker */
254         if(framenr<track->markers[0].framenr)
255                 return &track->markers[0];
256
257         if(track->last_marker<track->markersnr)
258                 a= track->last_marker;
259
260         if(track->markers[a].framenr<=framenr) {
261                 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
262                         if(track->markers[a].framenr==framenr) {
263                                 track->last_marker= a;
264                                 return &track->markers[a];
265                         }
266                         a++;
267                 }
268
269                 /* if there's no marker for exact position, use nearest marker from left side */
270                 return &track->markers[a-1];
271         } else {
272                 while(a>=0 && track->markers[a].framenr>=framenr) {
273                         if(track->markers[a].framenr==framenr) {
274                                 track->last_marker= a;
275                                 return &track->markers[a];
276                         }
277
278                         a--;
279                 }
280
281                 /* if there's no marker for exact position, use nearest marker from left side */
282                 return &track->markers[a];
283         }
284
285         return NULL;
286 }
287
288 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
289 {
290         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
291
292         if(marker && marker->framenr!=framenr) {
293                 MovieTrackingMarker marker_new;
294
295                 marker_new= *marker;
296                 marker_new.framenr= framenr;
297
298                 BKE_tracking_insert_marker(track, &marker_new);
299                 marker= BKE_tracking_get_marker(track, framenr);
300         }
301
302         return marker;
303 }
304
305 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
306 {
307         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
308
309         if(marker && marker->framenr!=framenr)
310                 return NULL;
311
312         return marker;
313 }
314
315 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
316 {
317         return BKE_tracking_exact_marker(track, framenr) != 0;
318 }
319
320 void BKE_tracking_free_track(MovieTrackingTrack *track)
321 {
322         if(track->markers) MEM_freeN(track->markers);
323 }
324
325 MovieTrackingTrack *BKE_tracking_copy_track(MovieTrackingTrack *track)
326 {
327         MovieTrackingTrack *new_track= MEM_dupallocN(track);
328
329         new_track->next= new_track->prev= NULL;
330
331         if(new_track->markers)
332                 new_track->markers= MEM_dupallocN(new_track->markers);
333
334         return new_track;
335 }
336
337 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
338 {
339         int a;
340
341         if(action==TRACK_CLEAR_REMAINED) {
342                 a= 1;
343                 while(a<track->markersnr) {
344                         if(track->markers[a].framenr>ref_frame) {
345                                 track->markersnr= a;
346                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
347
348                                 break;
349                         }
350
351                         a++;
352                 }
353         } else if(action==TRACK_CLEAR_UPTO) {
354                 a= track->markersnr-1;
355                 while(a>=0) {
356                         if(track->markers[a].framenr<=ref_frame) {
357                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
358
359                                 track->markersnr= track->markersnr-a;
360                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
361
362                                 break;
363                         }
364
365                         a--;
366                 }
367         } else if(action==TRACK_CLEAR_ALL) {
368                 MovieTrackingMarker *marker, marker_new;
369
370                 marker= BKE_tracking_get_marker(track, ref_frame);
371                 if(marker)
372                         marker_new= *marker;
373
374                 MEM_freeN(track->markers);
375                 track->markers= NULL;
376                 track->markersnr= 0;
377
378                 if(marker)
379                         BKE_tracking_insert_marker(track, &marker_new);
380         }
381 }
382
383 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
384 {
385         int i, a= 0, b= 0, tot= dst_track->markersnr+src_track->markersnr;
386         int count= 0;
387
388         for(i= 0; i<tot; i++) {
389                 if(a>=src_track->markersnr) {
390                         b++;
391                         count++;
392                 }
393                 else if(b>=dst_track->markersnr) {
394                         a++;
395                         count++;
396                 }
397                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
398                         a++;
399                         count++;
400                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
401                         b++;
402                         count++;
403                 } else {
404                         if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
405                                 return 0;
406
407                         a++;
408                         b++;
409                         count++;
410                 }
411         }
412
413         return count;
414 }
415
416 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
417 {
418         int i, a= 0, b= 0, tot;
419         MovieTrackingMarker *markers;
420
421         tot= BKE_tracking_test_join_tracks(dst_track, src_track);
422
423         markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
424
425         for(i= 0; i<tot; i++) {
426                 if(b>=dst_track->markersnr) {
427                         markers[i]= src_track->markers[a++];
428                 }
429                 else if(a>=src_track->markersnr) {
430                         markers[i]= dst_track->markers[b++];
431                 }
432                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
433                         markers[i]= src_track->markers[a++];
434                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
435                         markers[i]= dst_track->markers[b++];
436                 } else {
437                         if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
438                         else markers[i]= src_track->markers[a++];
439
440                         a++;
441                         b++;
442                 }
443         }
444
445         MEM_freeN(dst_track->markers);
446
447         dst_track->markers= markers;
448         dst_track->markersnr= tot;
449 }
450
451 void BKE_tracking_free(MovieTracking *tracking)
452 {
453         MovieTrackingTrack *track;
454
455         for(track= tracking->tracks.first; track; track= track->next) {
456                 BKE_tracking_free_track(track);
457         }
458
459         BLI_freelistN(&tracking->tracks);
460
461         if(tracking->reconstruction.cameras)
462                 MEM_freeN(tracking->reconstruction.cameras);
463
464         if(tracking->stabilization.scaleibuf)
465                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
466 }
467
468 /*********************** tracking *************************/
469
470 typedef struct TrackContext {
471         MovieTrackingTrack *track;
472
473 #ifdef WITH_LIBMV
474         /* ** KLT tracker ** */
475         struct libmv_RegionTracker *region_tracker;
476         float *patch;                   /* keyframed patch */
477
478         /* ** SAD tracker ** */
479         int patsize;                    /* size of pattern (currently only 16x16 due to libmv side) */
480         unsigned char *pattern; /* keyframed pattern */
481         unsigned char *warped;  /* warped version of reference */
482 #endif
483 } TrackContext;
484
485 typedef struct MovieTrackingContext {
486         MovieClipUser user;
487         MovieClip *clip;
488
489         int first_time, frames;
490
491         TrackContext *track_context;
492         int num_tracks;
493
494         GHash *hash;
495         MovieTrackingSettings settings;
496
497         short backwards, disable_failed;
498         int sync_frame;
499 } MovieTrackingContext;
500
501 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short disable_failed)
502 {
503         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
504         MovieTracking *tracking= &clip->tracking;
505         MovieTrackingSettings *settings= &tracking->settings;
506         MovieTrackingTrack *track;
507         TrackContext *track_context;
508
509         context->settings= *settings;
510         context->backwards= backwards;
511         context->disable_failed= disable_failed;
512         context->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "tracking trackHash");
513         context->sync_frame= user->framenr;
514         context->first_time= 1;
515
516         /* count */
517         track= tracking->tracks.first;
518         while(track) {
519                 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
520                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
521
522                         if((marker->flag&MARKER_DISABLED)==0)
523                                 context->num_tracks++;
524                 }
525
526                 track= track->next;
527         }
528
529         if(context->num_tracks) {
530                 int width, height;
531
532                 BKE_movieclip_acquire_size(clip, user, &width, &height);
533
534                 /* create tracking data */
535                 context->track_context= MEM_callocN(sizeof(TrackContext)*context->num_tracks, "tracking track_context");
536
537                 track_context= context->track_context;
538                 track= tracking->tracks.first;
539                 while(track) {
540                         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
541                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
542
543                                 if((marker->flag&MARKER_DISABLED)==0) {
544                                         MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
545
546                                         track_context->track= new_track;
547
548 #ifdef WITH_LIBMV
549                                         {
550                                                 if(context->settings.tracker==TRACKER_KLT) {
551                                                         float search_size_x= (track->search_max[0]-track->search_min[0])*width;
552                                                         float search_size_y= (track->search_max[1]-track->search_min[1])*height;
553                                                         float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
554                                                         float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
555
556                                                         int level= log(2.0f * MIN2(search_size_x, search_size_y) / MAX2(pattern_size_x, pattern_size_y))/M_LN2;
557
558                                                         track_context->region_tracker= libmv_regionTrackerNew(100, level, 0.2);
559                                                 }
560                                                 else if(context->settings.tracker==TRACKER_SAD) {
561                                                         /* notfing to initialize */
562                                                 }
563                                         }
564 #endif
565
566                                         BLI_ghash_insert(context->hash, new_track, track);
567
568                                         track_context++;
569                                 }
570                         }
571
572                         track= track->next;
573                 }
574         }
575
576         context->clip= clip;
577         context->user= *user;
578
579         return context;
580 }
581
582 void BKE_tracking_context_free(MovieTrackingContext *context)
583 {
584         int a;
585         TrackContext *track_context;
586
587         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
588                 BKE_tracking_free_track(context->track_context[a].track);
589
590 #if WITH_LIBMV
591                 if(track_context->region_tracker)
592                         libmv_regionTrackerDestroy(track_context->region_tracker);
593
594                 if(track_context->patch)
595                         MEM_freeN(track_context->patch);
596
597                 if(track_context->pattern)
598                         MEM_freeN(track_context->pattern);
599
600                 if(track_context->warped)
601                         MEM_freeN(track_context->warped);
602 #endif
603
604                 MEM_freeN(track_context->track);
605         }
606
607         if(context->track_context)
608                 MEM_freeN(context->track_context);
609
610         BLI_ghash_free(context->hash, NULL, NULL);
611
612         MEM_freeN(context);
613 }
614
615 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
616 {
617         int x, y;
618
619         if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
620                 return;
621
622         for(y= 0; y<ibuf->y; y++) {
623                 for (x= 0; x<ibuf->x; x++) {
624                         int pixel= ibuf->x*y + x;
625
626                         if(ibuf->rect_float) {
627                                 float *rrgbf= ibuf->rect_float + pixel*4;
628
629                                 if(track->flag&TRACK_DISABLE_RED)       rrgbf[0]= 0;
630                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgbf[1]= 0;
631                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgbf[2]= 0;
632                         } else {
633                                 char *rrgb= (char*)ibuf->rect + pixel*4;
634
635                                 if(track->flag&TRACK_DISABLE_RED)       rrgb[0]= 0;
636                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgb[1]= 0;
637                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgb[2]= 0;
638                         }
639                 }
640         }
641 }
642
643 static ImBuf *acquire_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
644                         float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
645 {
646         ImBuf *tmpibuf;
647         int x, y;
648         int x1, y1, x2, y2, w, h;
649         float mpos[2];
650
651         copy_v2_v2(mpos, marker->pos);
652         if(anchored)
653                 add_v2_v2(mpos, track->offset);
654
655         x= mpos[0]*ibuf->x;
656         y= mpos[1]*ibuf->y;
657         x1= x-(int)(-min[0]*ibuf->x);
658         y1= y-(int)(-min[1]*ibuf->y);
659         x2= x+(int)(max[0]*ibuf->x);
660         y2= y+(int)(max[1]*ibuf->y);
661
662         /* dimensions should be odd */
663         w= (x2-x1)|1;
664         h= (y2-y1)|1;
665
666         /* happens due to rounding issues */
667         if(x1+w<=x) x1++;
668         if(y1+h<=y) y1++;
669
670         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
671         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
672
673         if(pos != NULL) {
674                 pos[0]= x-x1+(mpos[0]*ibuf->x-x)+margin;
675                 pos[1]= y-y1+(mpos[1]*ibuf->y-y)+margin;
676         }
677
678         if(origin != NULL) {
679                 origin[0]= x1-margin;
680                 origin[1]= y1-margin;
681         }
682
683         disable_imbuf_channels(tmpibuf, track);
684
685         return tmpibuf;
686 }
687
688 ImBuf *BKE_tracking_acquire_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
689                         int margin, int anchored, float pos[2], int origin[2])
690 {
691         return acquire_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
692 }
693
694 ImBuf *BKE_tracking_acquire_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
695                         int margin, int anchored, float pos[2], int origin[2])
696 {
697         return acquire_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
698 }
699
700 #ifdef WITH_LIBMV
701 static float *acquire_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
702                         int *width_r, int *height_r, float pos[2], int origin[2])
703 {
704         ImBuf *tmpibuf;
705         float *pixels, *fp;
706         int x, y, width, height;
707
708         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
709         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
710
711         tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
712         disable_imbuf_channels(tmpibuf, track);
713
714         *width_r= width;
715         *height_r= height;
716
717         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
718         for(y= 0; y<(int)height; y++) {
719                 for (x= 0; x<(int)width; x++) {
720                         int pixel= tmpibuf->x*y + x;
721
722                         if(tmpibuf->rect_float) {
723                                 float *rrgbf= ibuf->rect_float + pixel*4;
724
725                                 *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2])/255;
726                         } else {
727                                 char *rrgb= (char*)tmpibuf->rect + pixel*4;
728
729                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255;
730                         }
731
732                         fp++;
733                 }
734         }
735
736         IMB_freeImBuf(tmpibuf);
737
738         return pixels;
739 }
740
741 static unsigned char *acquire_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
742                         int *width_r, int *height_r, float pos[2], int origin[2])
743 {
744         ImBuf *tmpibuf;
745         unsigned char *pixels, *fp;
746         int x, y, width, height;
747
748         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
749         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
750
751         tmpibuf= BKE_tracking_acquire_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
752         disable_imbuf_channels(tmpibuf, track);
753
754         *width_r= width;
755         *height_r= height;
756
757         fp= pixels= MEM_callocN(width*height*sizeof(unsigned char), "tracking byteBuf");
758         for(y= 0; y<(int)height; y++) {
759                 for (x= 0; x<(int)width; x++) {
760                         int pixel= tmpibuf->x*y + x;
761
762                         if(tmpibuf->rect_float) {
763                                 float *rrgbf= ibuf->rect_float + pixel*4;
764
765                                 *fp= (0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2]);
766                         } else {
767                                 char *rrgb= (char*)tmpibuf->rect + pixel*4;
768
769                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2]);
770                         }
771
772                         fp++;
773                 }
774         }
775
776         IMB_freeImBuf(tmpibuf);
777
778         return pixels;
779 }
780
781 static ImBuf *acquire_frame_ibuf(MovieTrackingContext *context, int framenr)
782 {
783         ImBuf *ibuf;
784         int framenr_old= context->user.framenr;
785
786         context->user.framenr= framenr;
787
788         ibuf= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
789
790         context->user.framenr= framenr_old;
791
792         return ibuf;
793 }
794
795 static ImBuf *acquire_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
796                         MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
797 {
798         int framenr= marker->framenr;
799         int a= marker-track->markers;
800
801         *marker_keyed= marker;
802
803         while(a>=0 && a<track->markersnr) {
804                 if((track->markers[a].flag&MARKER_TRACKED)==0) {
805                         framenr= track->markers[a].framenr;
806                         *marker_keyed= &track->markers[a];
807                         break;
808                 }
809
810                 if(context->backwards) a++;
811                 else a--;
812         }
813
814         return acquire_frame_ibuf(context, framenr);
815 }
816
817 static ImBuf *acquire_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
818                         int curfra, MovieTrackingMarker **marker_keyed)
819 {
820         ImBuf *ibuf= NULL;
821
822         if(context->settings.adjframes == 0) {
823                 ibuf= acquire_keyframed_ibuf(context, track, marker, marker_keyed);
824         } else {
825                 ibuf= acquire_frame_ibuf(context, curfra);
826
827                 /* use current marker as keyframed position */
828                 *marker_keyed= marker;
829         }
830
831         return ibuf;
832 }
833
834 static void acquire_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
835 {
836         int i, j;
837
838         for(i=0; i<track_context->patsize; i++) {
839                 for(j=0; j<track_context->patsize; j++) {
840                         track_context->warped[i*track_context->patsize+j]=
841                                         image[(y+i-track_context->patsize/2)*width+x+j-track_context->patsize/2];
842                 }
843         }
844 }
845
846 #endif
847
848 void BKE_tracking_sync(MovieTrackingContext *context)
849 {
850         TrackContext *track_context;
851         MovieTracking *tracking= &context->clip->tracking;
852         MovieTrackingTrack *track;
853         ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
854         ListBase *old_tracks= &context->clip->tracking.tracks;
855         int a, newframe;
856
857         /* duplicate currently tracking tracks to temporary list.
858            this is needed to keep names in unique state and it's faster to change names
859            of currently tracking tracks (if needed) */
860         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
861                 int replace_sel= 0;
862                 MovieTrackingTrack *new_track, *old;
863
864                 track= track_context->track;
865
866                 /* find original of tracking track in list of previously displayed tracks */
867                 old= BLI_ghash_lookup(context->hash, track);
868                 if(old) {
869                         MovieTrackingTrack *cur= old_tracks->first;
870
871                         while(cur) {
872                                 if(cur==old)
873                                         break;
874
875                                 cur= cur->next;
876                         }
877
878                         /* original track was found, re-use flags and remove this track */
879                         if(cur) {
880                                 if(cur==tracking->act_track)
881                                         replace_sel= 1;
882
883                                 track->flag= cur->flag;
884                                 track->pat_flag= cur->pat_flag;
885                                 track->search_flag= cur->search_flag;
886
887                                 BKE_tracking_free_track(cur);
888                                 BLI_freelinkN(old_tracks, cur);
889                         }
890                 }
891
892                 new_track= BKE_tracking_copy_track(track);
893
894                 BLI_ghash_remove(context->hash, track, NULL, NULL); /* XXX: are we actually need this */
895                 BLI_ghash_insert(context->hash, track, new_track);
896
897                 if(replace_sel)         /* update current selection in clip */
898                         tracking->act_track= new_track;
899
900                 BLI_addtail(&tracks, new_track);
901         }
902
903         /* move all tracks, which aren't tracking */
904         track= old_tracks->first;
905         while(track) {
906                 MovieTrackingTrack *next= track->next;
907
908                 track->next= track->prev= NULL;
909                 BLI_addtail(&new_tracks, track);
910
911                 track= next;
912         }
913
914         /* now move all tracks which are currently tracking and keep their names unique */
915         track= tracks.first;
916         while(track) {
917                 MovieTrackingTrack *next= track->next;
918
919                 BLI_remlink(&tracks, track);
920
921                 track->next= track->prev= NULL;
922                 BLI_addtail(&new_tracks, track);
923
924                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
925
926                 track= next;
927         }
928
929         context->clip->tracking.tracks= new_tracks;
930
931         if(context->backwards) newframe= context->user.framenr+1;
932         else newframe= context->user.framenr-1;
933
934         context->sync_frame= newframe;
935 }
936
937 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
938 {
939         user->framenr= context->sync_frame;
940 }
941
942 int BKE_tracking_next(MovieTrackingContext *context)
943 {
944         ImBuf *ibuf_new;
945         int curfra= context->user.framenr;
946         int a, ok= 0;
947
948         /* nothing to track, avoid unneeded frames reading to save time and memory */
949         if(!context->num_tracks)
950                 return 0;
951
952         if(context->backwards) context->user.framenr--;
953         else context->user.framenr++;
954
955         ibuf_new= BKE_movieclip_acquire_ibuf_flag(context->clip, &context->user, 0);
956         if(!ibuf_new)
957                 return 0;
958
959         #pragma omp parallel for private(a) shared(ibuf_new, ok) if(context->num_tracks>1)
960         for(a= 0; a<context->num_tracks; a++) {
961                 TrackContext *track_context= &context->track_context[a];
962                 MovieTrackingTrack *track= track_context->track;
963                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, curfra);
964
965                 if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
966 #ifdef WITH_LIBMV
967                         int width, height, origin[2], tracked= 0, need_readjust= 0;
968                         float pos[2], margin[2];
969                         double x1, y1, x2, y2;
970                         ImBuf *ibuf= NULL;
971                         MovieTrackingMarker marker_new, *marker_keyed;
972                         int onbound= 0;
973
974                         if(!context->settings.adjframes) need_readjust= context->first_time;
975                         else need_readjust= context->frames%context->settings.adjframes == 0;
976
977                         /* margin from frame boundaries */
978                         sub_v2_v2v2(margin, track->pat_max, track->pat_min);
979
980                         margin[0]= MAX2(margin[0], (float)context->settings.margin / ibuf_new->x);
981                         margin[1]= MAX2(margin[1], (float)context->settings.margin / ibuf_new->y);
982
983                         /* do not track markers which are too close to boundary */
984                         if(marker->pos[0]<margin[0] || marker->pos[0]>1.f-margin[0] ||
985                            marker->pos[1]<margin[1] || marker->pos[1]>1.f-margin[1]) {
986                                 onbound= 1;
987                         }
988                         else if(context->settings.tracker==TRACKER_KLT) {
989                                 int wndx, wndy;
990                                 float *patch_new;
991
992                                 if(need_readjust) {
993                                         /* calculate patch for keyframed position */
994                                         ibuf= acquire_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
995
996                                         if(track_context->patch)
997                                                 MEM_freeN(track_context->patch);
998
999                                         track_context->patch= acquire_search_floatbuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1000
1001                                         IMB_freeImBuf(ibuf);
1002                                 }
1003
1004                                 patch_new= acquire_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1005
1006                                 x1= pos[0];
1007                                 y1= pos[1];
1008
1009                                 x2= x1;
1010                                 y2= y1;
1011
1012                                 wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf_new->x)/2;
1013                                 wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf_new->y)/2;
1014
1015                                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1016                                                         width, height, MAX2(wndx, wndy), x1, y1, &x2, &y2);
1017
1018                                 MEM_freeN(patch_new);
1019                         }
1020                         else if(context->settings.tracker==TRACKER_SAD) {
1021                                 unsigned char *image_new;
1022                                 float corr;
1023                                 float warp[3][2]={{0}};
1024
1025                                 if(need_readjust) {
1026                                         unsigned char *image;
1027
1028                                         /* calculate pattern for keyframed position */
1029                                         ibuf= acquire_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1030
1031                                         image= acquire_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1032
1033                                         memset(warp, 0, sizeof(warp));
1034                                         warp[0][0]= 1;
1035                                         warp[1][1]= 1;
1036                                         warp[2][0]= pos[0];
1037                                         warp[2][1]= pos[1];
1038
1039                                         /* pattern size is hardcoded to 16x16px in libmv */
1040                                         track_context->patsize= 16;
1041
1042                                         if(!track_context->pattern)
1043                                                 track_context->pattern= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking pattern");
1044
1045                                         libmv_SADSamplePattern(image, width, warp, track_context->pattern);
1046
1047                                         MEM_freeN(image);
1048                                         IMB_freeImBuf(ibuf);
1049                                 }
1050
1051                                 image_new= acquire_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1052
1053                                 if(track_context->warped==NULL) {
1054                                         unsigned char *image_old;
1055
1056                                         ibuf= acquire_frame_ibuf(context, curfra);
1057
1058                                         if(track_context->warped==NULL)
1059                                                 track_context->warped= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking warped");
1060
1061                                         image_old= acquire_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1062                                         acquire_warped(track_context, pos[0], pos[1], width, image_old);
1063                                         IMB_freeImBuf(ibuf);
1064                                         MEM_freeN(image_old);
1065                                 }
1066
1067                                 memset(warp, 0, sizeof(warp));
1068                                 warp[0][0]= 1;
1069                                 warp[1][1]= 1;
1070                                 warp[2][0]= pos[0];
1071                                 warp[2][1]= pos[1];
1072
1073                                 corr= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
1074
1075                                 x2= warp[2][0];
1076                                 y2= warp[2][1];
1077
1078                                 tracked= corr>=context->settings.corr;
1079
1080                                 if(tracked)
1081                                         acquire_warped(track_context, x2, y2, width, image_new);
1082
1083                                 MEM_freeN(image_new);
1084                         }
1085
1086                         if(tracked || !context->disable_failed) {
1087                                 if(context->first_time) {
1088                                         int prevframe;
1089
1090                                         if(context->backwards) prevframe= curfra+1;
1091                                         else prevframe= curfra-1;
1092
1093                                         /* check if there's no keyframe/tracked markers before tracking marker.
1094                                             if so -- create disabled marker before currently tracking "segment" */
1095                                         if(!BKE_tracking_has_marker(track, prevframe)) {
1096                                                 marker_new= *marker;
1097                                                 marker_new.framenr= prevframe;
1098
1099                                                 marker_new.flag|= MARKER_DISABLED;
1100
1101                                                 #pragma omp critical
1102                                                 {
1103                                                         BKE_tracking_insert_marker(track, &marker_new);
1104                                                 }
1105                                         }
1106                                 }
1107
1108                                 memset(&marker_new, 0, sizeof(marker_new));
1109
1110                                 if(!onbound) {
1111                                         marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1112                                         marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1113                                 } else {
1114                                         copy_v2_v2(marker_new.pos, marker->pos);
1115                                 }
1116
1117                                 marker_new.flag|= MARKER_TRACKED;
1118
1119                                 if(context->backwards) marker_new.framenr= curfra-1;
1120                                 else marker_new.framenr= curfra+1;
1121
1122                                 #pragma omp critical
1123                                 {
1124                                         BKE_tracking_insert_marker(track, &marker_new);
1125                                 }
1126
1127                         } else {
1128                                 marker_new= *marker;
1129
1130                                 if(context->backwards) marker_new.framenr--;
1131                                 else marker_new.framenr++;
1132
1133                                 marker_new.flag|= MARKER_DISABLED;
1134
1135                                 #pragma omp critical
1136                                 {
1137                                         BKE_tracking_insert_marker(track, &marker_new);
1138                                 }
1139                         }
1140
1141                         ok= 1;
1142 #endif
1143                 }
1144         }
1145
1146         IMB_freeImBuf(ibuf_new);
1147
1148         context->first_time= 0;
1149         context->frames++;
1150
1151         return ok;
1152 }
1153
1154 #if WITH_LIBMV
1155 static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height)
1156 {
1157         int tracknr= 0;
1158         MovieTrackingTrack *track;
1159         struct libmv_Tracks *tracks= libmv_tracksNew();
1160
1161         track= tracking->tracks.first;
1162         while(track) {
1163                 int a= 0;
1164
1165                 for(a= 0; a<track->markersnr; a++) {
1166                         MovieTrackingMarker *marker= &track->markers[a];
1167
1168                         if((marker->flag&MARKER_DISABLED)==0)
1169                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1170                                                         marker->pos[0]*width, marker->pos[1]*height);
1171                 }
1172
1173                 track= track->next;
1174                 tracknr++;
1175         }
1176
1177         return tracks;
1178 }
1179
1180 static int retrive_libmv_reconstruct(MovieTracking *tracking, struct libmv_Reconstruction *libmv_reconstruction)
1181 {
1182         int tracknr= 0;
1183         int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0;
1184         MovieTrackingTrack *track;
1185         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1186         MovieReconstructedCamera *reconstructed;
1187         float origin[3]= {0.0f, 0.f, 0.0f};
1188         int ok= 1;
1189
1190         track= tracking->tracks.first;
1191         while(track) {
1192                 double pos[3];
1193
1194                 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1195                         track->bundle_pos[0]= pos[0];
1196                         track->bundle_pos[1]= pos[1];
1197                         track->bundle_pos[2]= pos[2];
1198
1199                         track->flag|= TRACK_HAS_BUNDLE;
1200                         track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1201                 } else {
1202                         track->flag&= ~TRACK_HAS_BUNDLE;
1203                         ok= 0;
1204
1205                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1206                 }
1207
1208                 if(track->markersnr) {
1209                         if(track->markers[0].framenr<sfra) sfra= track->markers[0].framenr;
1210                         if(track->markers[track->markersnr-1].framenr>efra) efra= track->markers[track->markersnr-1].framenr;
1211                 }
1212
1213                 track= track->next;
1214                 tracknr++;
1215         }
1216
1217         if(reconstruction->cameras)
1218                 MEM_freeN(reconstruction->cameras);
1219
1220         reconstruction->camnr= 0;
1221         reconstruction->cameras= NULL;
1222         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1223
1224         for(a= sfra; a<=efra; a++) {
1225                 double matd[4][4];
1226
1227                 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1228                         int i, j;
1229                         float mat[4][4];
1230
1231                         for(i=0; i<4; i++)
1232                                 for(j= 0; j<4; j++)
1233                                         mat[i][j]= matd[i][j];
1234
1235                         if(!origin_set) {
1236                                 copy_v3_v3(origin, mat[3]);
1237                                 origin_set= 1;
1238                         }
1239
1240                         if(origin_set)
1241                                 sub_v3_v3(mat[3], origin);
1242
1243                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1244                         reconstructed[reconstruction->camnr].framenr= a;
1245                         reconstruction->camnr++;
1246                 } else {
1247                         ok= 0;
1248                         printf("No camera for frame %d\n", a);
1249                 }
1250         }
1251
1252         if(reconstruction->camnr) {
1253                 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1254                 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1255         }
1256
1257         if(origin_set) {
1258                 track= tracking->tracks.first;
1259                 while(track) {
1260                         if(track->flag&TRACK_HAS_BUNDLE)
1261                                 sub_v3_v3(track->bundle_pos, origin);
1262
1263                         track= track->next;
1264                 }
1265         }
1266
1267         MEM_freeN(reconstructed);
1268
1269         return ok;
1270 }
1271
1272 #endif
1273
1274 float BKE_tracking_solve_reconstruction(MovieTracking *tracking, int width, int height)
1275 {
1276 #if WITH_LIBMV
1277         {
1278                 MovieTrackingCamera *camera= &tracking->camera;
1279                 float aspy= 1.f/tracking->camera.pixel_aspect;
1280                 struct libmv_Tracks *tracks= create_libmv_tracks(tracking, width, height*aspy);
1281                 struct libmv_Reconstruction *reconstruction = libmv_solveReconstruction(tracks,
1282                         tracking->settings.keyframe1, tracking->settings.keyframe2,
1283                         camera->focal,
1284                         camera->principal[0], camera->principal[1]*aspy,
1285                         camera->k1, camera->k2, camera->k3);
1286                 float error= libmv_reprojectionError(reconstruction);
1287
1288                 tracking->reconstruction.error= error;
1289
1290                 if(!retrive_libmv_reconstruct(tracking, reconstruction))
1291                         error= -1.f;
1292
1293                 libmv_destroyReconstruction(reconstruction);
1294                 libmv_tracksDestroy(tracks);
1295
1296                 tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
1297
1298                 return error;
1299         }
1300 #endif
1301 }
1302
1303 void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
1304 {
1305         BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1306 }
1307
1308 MovieTrackingTrack *BKE_find_track_by_name(MovieTracking *tracking, const char *name)
1309 {
1310         MovieTrackingTrack *track= tracking->tracks.first;
1311
1312         while(track) {
1313                 if(!strcmp(track->name, name))
1314                         return track;
1315
1316                 track= track->next;
1317         }
1318
1319         return NULL;
1320 }
1321
1322 static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest)
1323 {
1324         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1325         MovieReconstructedCamera *cameras= reconstruction->cameras;
1326         int a= 0, d= 1;
1327
1328         if(!reconstruction->camnr)
1329                 return -1;
1330
1331         if(framenr<cameras[0].framenr) {
1332                 if(nearest) return 0;
1333                 else return -1;
1334         }
1335
1336         if(framenr>cameras[reconstruction->camnr-1].framenr) {
1337                 if(nearest) return reconstruction->camnr-1;
1338                 else return -1;
1339         }
1340
1341         if(reconstruction->last_camera<reconstruction->camnr)
1342                 a= reconstruction->last_camera;
1343
1344         if(cameras[a].framenr>=framenr)
1345                 d= -1;
1346
1347         while(a>=0 && a<reconstruction->camnr) {
1348                 int cfra= cameras[a].framenr;
1349
1350                 /* check if needed framenr was "skipped" -- no data for requested frame */
1351
1352                 if(d>0 && cfra>framenr) {
1353                         /* interpolate with previous position */
1354                         if(nearest) return a-1;
1355                         else break;
1356                 }
1357
1358                 if(d<0 && cfra<framenr) {
1359                         /* interpolate with next position */
1360                         if(nearest) return a;
1361                         else break;
1362                 }
1363
1364                 if(cfra==framenr) {
1365                         reconstruction->last_camera= a;
1366
1367                         return a;
1368                 }
1369
1370                 a+= d;
1371         }
1372
1373         return -1;
1374 }
1375
1376 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
1377 {
1378         int a= reconstruction_camera_index(tracking, framenr, 0);
1379
1380         if(a==-1)
1381                 return NULL;
1382
1383         return &tracking->reconstruction.cameras[a];
1384 }
1385
1386 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4])
1387 {
1388         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1389         MovieReconstructedCamera *cameras= reconstruction->cameras;
1390         int a= reconstruction_camera_index(tracking, framenr, 1);
1391
1392         if(a==-1) {
1393                 unit_m4(mat);
1394                 return;
1395         }
1396
1397         if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
1398                 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
1399
1400                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
1401         } else {
1402                 copy_m4_m4(mat, cameras[a].mat);
1403         }
1404 }
1405
1406 void BKE_get_tracking_mat(Scene *scene, float mat[4][4])
1407 {
1408         if(!scene->camera)
1409                 scene->camera= scene_find_camera(scene);
1410
1411         if(scene->camera)
1412                 where_is_object_mat(scene, scene->camera, mat);
1413         else
1414                 unit_m4(mat);
1415 }
1416
1417 void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
1418 {
1419         MovieReconstructedCamera *camera;
1420         float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
1421         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
1422         float winmat[4][4];
1423         float ycor= 1.f/tracking->camera.pixel_aspect;
1424
1425         clipsta= 0.1f;
1426         clipend= 1000.0f;
1427
1428         if(winx >= winy)
1429                 viewfac= (lens*winx)/tracking->camera.sensor_width;
1430         else
1431                 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
1432
1433         pixsize= clipsta/viewfac;
1434
1435         left= -0.5f*(float)winx*pixsize;
1436         bottom= -0.5f*ycor*(float)winy*pixsize;
1437         right=  0.5f*(float)winx*pixsize;
1438         top=  0.5f*ycor*(float)winy*pixsize;
1439
1440         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
1441
1442         camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
1443         if(camera) {
1444                 float imat[4][4];
1445
1446                 invert_m4_m4(imat, camera->mat);
1447                 mul_m4_m4m4(mat, imat, winmat);
1448         } else copy_m4_m4(mat, winmat);
1449 }
1450
1451 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1452 {
1453         MovieTrackingCamera *camera= &tracking->camera;
1454
1455 #ifdef WITH_LIBMV
1456         double x, y;
1457         float aspy= 1.f/tracking->camera.pixel_aspect;
1458
1459         /* normalize coords */
1460         x= (co[0]-camera->principal[0]) / camera->focal;
1461         y= (co[1]-camera->principal[1] * aspy) / camera->focal;
1462
1463         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1464                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1465
1466         /* result is in image coords already */
1467         nco[0]= x;
1468         nco[1]= y;
1469 #endif
1470 }
1471
1472 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1473 {
1474         MovieTrackingCamera *camera= &tracking->camera;
1475
1476 #ifdef WITH_LIBMV
1477         double x= co[0], y= co[1];
1478         float aspy= 1.f/tracking->camera.pixel_aspect;
1479
1480         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1481                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1482
1483         nco[0]= x * camera->focal + camera->principal[0];
1484         nco[1]= y * camera->focal + camera->principal[1] * aspy;
1485 #endif
1486 }
1487
1488 #ifdef WITH_LIBMV
1489 /* flips upside-down */
1490 static unsigned char *acquire_ucharbuf(ImBuf *ibuf)
1491 {
1492         int x, y;
1493         unsigned char *pixels, *fp;
1494
1495         fp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
1496         for(y= 0; y<ibuf->y; y++) {
1497                 for (x= 0; x<ibuf->x; x++) {
1498                         int pixel= ibuf->x*(ibuf->y-y-1) + x;
1499
1500                         if(ibuf->rect_float) {
1501                                 float *rrgbf= ibuf->rect_float + pixel*4;
1502
1503                                 //*fp= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
1504                                 *fp= (11*rrgbf[0]+16*rrgbf[1]+5*rrgbf[2])/32;
1505                         } else {
1506                                 char *rrgb= (char*)ibuf->rect + pixel*4;
1507
1508                                 //*fp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
1509                                 *fp= (11*rrgb[0]+16*rrgb[1]+5*rrgb[2])/32;
1510                         }
1511
1512                         fp++;
1513                 }
1514         }
1515
1516         return pixels;
1517 }
1518 #endif
1519
1520 void BKE_tracking_detect(MovieTracking *tracking, ImBuf *ibuf, int framenr, int margin, int count, int min_distance)
1521 {
1522 #ifdef WITH_LIBMV
1523         struct libmv_Features *features;
1524         unsigned char *pixels= acquire_ucharbuf(ibuf);
1525         int a;
1526
1527         features= libmv_detectFeatures(pixels, ibuf->x, ibuf->y, ibuf->x, margin, count, min_distance);
1528         MEM_freeN(pixels);
1529
1530         a= libmv_countFeatures(features);
1531         while(a--) {
1532                 MovieTrackingTrack *track;
1533                 double x, y, size, score;
1534
1535                 libmv_getFeature(features, a, &x, &y, &score, &size);
1536
1537                 track= BKE_tracking_add_track(tracking, x/ibuf->x, 1.0f-(y/ibuf->y), framenr, ibuf->x, ibuf->y);
1538                 track->flag|= SELECT;
1539                 track->pat_flag|= SELECT;
1540                 track->search_flag|= SELECT;
1541         }
1542
1543         libmv_destroyFeatures(features);
1544 #endif
1545 }
1546
1547 MovieTrackingTrack *BKE_tracking_indexed_bundle(MovieTracking *tracking, int bundlenr)
1548 {
1549         MovieTrackingTrack *track= tracking->tracks.first;
1550         int cur= 1;
1551
1552         while(track) {
1553                 if(track->flag&TRACK_HAS_BUNDLE) {
1554                         if(cur==bundlenr)
1555                                 return track;
1556
1557                         cur++;
1558                 }
1559
1560                 track= track->next;
1561         }
1562
1563         return NULL;
1564 }
1565
1566 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
1567 {
1568         int ok= 0;
1569         float min[2], max[2];
1570         MovieTrackingTrack *track;
1571
1572         INIT_MINMAX2(min, max);
1573
1574         track= tracking->tracks.first;
1575         while(track) {
1576                 if(track->flag&TRACK_USE_2D_STAB) {
1577                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
1578
1579                         DO_MINMAX2(marker->pos, min, max);
1580
1581                         ok= 1;
1582                 }
1583
1584                 track= track->next;
1585         }
1586
1587         median[0]= (max[0]+min[0])/2.f;
1588         median[1]= (max[1]+min[1])/2.f;
1589
1590         return ok;
1591 }
1592
1593 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
1594                         float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
1595 {
1596         MovieTrackingStabilization *stab= &tracking->stabilization;
1597
1598         *scale= (stab->scale-1.f)*stab->scaleinf+1.f;
1599         *angle= 0.f;
1600
1601         loc[0]= (firstmedian[0]-median[0])*width*(*scale);
1602         loc[1]= (firstmedian[1]-median[1])*height*(*scale);
1603
1604         loc[0]-= (firstmedian[0]*(*scale)-firstmedian[0])*width;
1605         loc[1]-= (firstmedian[1]*(*scale)-firstmedian[1])*height;
1606
1607         mul_v2_fl(loc, stab->locinf);
1608
1609         if(stab->rot_track && stab->rotinf) {
1610                 MovieTrackingMarker *marker;
1611                 float a[2], b[2];
1612                 float x0= (float)width/2.f, y0= (float)height/2.f;
1613                 float x= median[0]*width, y= median[1]*height;
1614
1615                 marker= BKE_tracking_get_marker(stab->rot_track, 1);
1616                 sub_v2_v2v2(a, marker->pos, firstmedian);
1617                 a[0]*= width;
1618                 a[1]*= height;
1619
1620                 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
1621                 sub_v2_v2v2(b, marker->pos, median);
1622                 b[0]*= width;
1623                 b[1]*= height;
1624
1625                 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
1626                 *angle*= stab->rotinf;
1627
1628                 /* convert to rotation around image center */
1629                 loc[0]-= (x0 + (x-x0)*cos(*angle)-(y-y0)*sin(*angle) - x);
1630                 loc[1]-= (y0 + (x-x0)*sin(*angle)+(y-y0)*cos(*angle) - y);
1631         }
1632 }
1633
1634 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
1635 {
1636         float firstmedian[2];
1637         MovieTrackingStabilization *stab= &tracking->stabilization;
1638
1639         if(stab->ok)
1640                 return stab->scale;
1641
1642         if(stabilization_median_point(tracking, 1, firstmedian)) {
1643                 int sfra= INT_MAX, efra= INT_MIN, cfra;
1644                 float delta[2]= {0.f, 0.f}, scalex= 1.f, scaley= 1.f;
1645                 MovieTrackingTrack *track;
1646
1647                 stab->scale= 1.f;
1648
1649                 track= tracking->tracks.first;
1650                 while(track) {
1651                         if(track->flag&TRACK_USE_2D_STAB || track==stab->rot_track) {
1652                                 if(track->markersnr) {
1653                                         sfra= MIN2(sfra, track->markers[0].framenr);
1654                                         efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
1655                                 }
1656                         }
1657
1658                         track= track->next;
1659                 }
1660
1661                 for(cfra=sfra; cfra<=efra; cfra++) {
1662                         float median[2], near[2];
1663                         float loc[2], scale, angle;
1664
1665                         stabilization_median_point(tracking, cfra, median);
1666
1667                         calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
1668                                                 loc, &scale, &angle);
1669
1670                         if(angle==0.f) {
1671                                 loc[0]= fabsf(loc[0]);
1672                                 loc[1]= fabsf(loc[1]);
1673
1674                                 delta[0]= MAX2(delta[0], loc[0]);
1675                                 delta[1]= MAX2(delta[1], loc[1]);
1676
1677                                 near[0]= MIN2(median[0], 1.f-median[0]);
1678                                 near[1]= MIN2(median[1], 1.f-median[1]);
1679                                 near[0]= MAX2(near[0], 0.05);
1680                                 near[1]= MAX2(near[1], 0.05);
1681
1682                                 scalex= 1.f+delta[0]/(near[0]*width);
1683                                 scaley= 1.f+delta[1]/(near[1]*height);
1684                         } else {
1685                                 int i;
1686                                 float mat[4][4];
1687                                 float points[4][2]={{0.f, 0.f}, {0.f, height}, {width, height}, {width, 0.f}};
1688
1689                                 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
1690
1691                                 for(i= 0; i<4; i++) {
1692                                         int j;
1693                                         float a[3]= {0.f}, b[3]= {0.f};
1694
1695                                         copy_v3_v3(a, points[i]);
1696                                         copy_v3_v3(b, points[(i+1)%4]);
1697
1698                                         mul_m4_v3(mat, a);
1699                                         mul_m4_v3(mat, b);
1700
1701                                         for(j= 0; j<4; j++) {
1702                                                 float point[3]= {points[j][0], points[j][1], 0.f};
1703                                                 float v1[3], v2[3];
1704
1705                                                 sub_v3_v3v3(v1, b, a);
1706                                                 sub_v3_v3v3(v2, point, a);
1707
1708                                                 if(cross_v2v2(v1, v2) >= 0.f) {
1709                                                         float dist= dist_to_line_v2(point, a, b);
1710                                                         if(i%2==0) {
1711                                                                 scalex= MAX2(scalex, (width+2*dist)/width);
1712                                                         } else {
1713                                                                 scaley= MAX2(scaley, (height+2*dist)/height);
1714                                                         }
1715                                                 }
1716                                         }
1717                                 }
1718                         }
1719                 }
1720
1721                 stab->scale= MAX2(scalex, scaley);
1722
1723                 if(stab->maxscale>0.f)
1724                         stab->scale= MIN2(stab->scale, stab->maxscale);
1725         } else {
1726                 stab->scale= 1.f;
1727         }
1728
1729         stab->ok= 1;
1730
1731         return stab->scale;
1732 }
1733
1734 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
1735 {
1736         int flags;
1737
1738         if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
1739                 IMB_freeImBuf(cacheibuf);
1740                 cacheibuf= NULL;
1741         }
1742
1743         flags= IB_rect;
1744
1745         if(srcibuf->rect_float)
1746                 flags|= IB_rectfloat;
1747
1748         if(cacheibuf) {
1749                 if(fill) {
1750                         float col[4]= {0.f, 0.f, 0.f, 0.f};
1751                         IMB_rectfill(cacheibuf, col);
1752                 }
1753         }
1754         else {
1755                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
1756                 cacheibuf->profile= srcibuf->profile;
1757         }
1758
1759         return cacheibuf;
1760 }
1761
1762 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
1763 {
1764         float firstmedian[2], median[2];
1765         MovieTrackingStabilization *stab= &tracking->stabilization;
1766
1767         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1768                 zero_v2(loc);
1769                 *scale= 1.f;
1770                 *angle= 0.f;
1771
1772                 return;
1773         }
1774
1775         if(stabilization_median_point(tracking, 1, firstmedian)) {
1776                 stabilization_median_point(tracking, framenr, median);
1777
1778                 if((stab->flag&TRACKING_AUTOSCALE)==0)
1779                         stab->scale= 1.f;
1780
1781                 if(!stab->ok) {
1782                         if(stab->flag&TRACKING_AUTOSCALE)
1783                                 stabilization_auto_scale_factor(tracking, width, height);
1784
1785                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1786
1787                         stab->ok= 1;
1788                 } else {
1789                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1790                 }
1791         } else {
1792                 zero_v2(loc);
1793                 *scale= 1.f;
1794                 *angle= 0.f;
1795         }
1796 }
1797
1798 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
1799 {
1800         float tloc[2], tscale, tangle;
1801         MovieTrackingStabilization *stab= &tracking->stabilization;
1802         ImBuf *tmpibuf;
1803         float width= ibuf->x, height= ibuf->y;
1804
1805         if(loc)         copy_v2_v2(tloc, loc);
1806         if(scale)       tscale= *scale;
1807
1808         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1809                 if(loc)         zero_v2(loc);
1810                 if(scale)       *scale= 1.f;
1811
1812                 return ibuf;
1813         }
1814
1815         BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
1816
1817         tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
1818
1819         /* scale would be handled by matrix transformation when angle is non-zero */
1820         if(tscale!=1.f && tangle==0.f) {
1821                 ImBuf *scaleibuf;
1822                 float scale= (stab->scale-1.f)*stab->scaleinf+1.f;
1823
1824                 stabilization_auto_scale_factor(tracking, width, height);
1825
1826                 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
1827                 stab->scaleibuf= scaleibuf;
1828
1829                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
1830                 IMB_scalefastImBuf(scaleibuf, ibuf->x*scale, ibuf->y*scale);
1831
1832                 ibuf= scaleibuf;
1833         }
1834
1835         if(tangle==0.f) {
1836                 /* if angle is zero, then it's much faster to use rect copy
1837                    but could be issues with subpixel precisions */
1838                 IMB_rectcpy(tmpibuf, ibuf, tloc[0], tloc[1], 0, 0, ibuf->x, ibuf->y);
1839         } else {
1840                 float mat[4][4];
1841                 int i, j;
1842
1843                 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
1844                 invert_m4(mat);
1845
1846                 for(j=0; j<tmpibuf->y; j++) {
1847                         for(i=0; i<tmpibuf->x;i++) {
1848                                 float vec[3]= {i, j, 0};
1849
1850                                 mul_v3_m4v3(vec, mat, vec);
1851
1852                                 /* TODO: add selector for interpolation method */
1853                                 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
1854                         }
1855                 }
1856         }
1857
1858         tmpibuf->userflags|= IB_MIPMAP_INVALID;
1859
1860         if(tmpibuf->rect_float)
1861                 tmpibuf->userflags|= IB_RECT_INVALID;
1862
1863         if(loc)         copy_v2_v2(loc, tloc);
1864         if(scale)       *scale= tscale;
1865         if(angle)       *angle= tangle;
1866
1867         return tmpibuf;
1868 }
1869
1870 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
1871 {
1872         float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
1873         float svec[3]= {scale, scale, scale};
1874
1875         unit_m4(rmat);
1876         unit_m4(lmat);
1877         unit_m4(smat);
1878         unit_m4(cmat);
1879
1880         /* image center as rotation center */
1881         cmat[3][0]= (float)width/2.f;
1882         cmat[3][1]= (float)height/2.f;
1883         invert_m4_m4(icmat, cmat);
1884
1885         size_to_mat4(smat, svec);               /* scale matrix */
1886         add_v2_v2(lmat[3], loc);                /* tranlation matrix */
1887         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
1888
1889         /* compose transformation matrix */
1890         mul_serie_m4(mat, lmat, smat, cmat, rmat, icmat, NULL, NULL, NULL);
1891 }
1892
1893 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf)
1894 {
1895         ImBuf *resibuf;
1896         MovieTrackingCamera *camera= &tracking->camera;
1897         float aspy= 1.f/tracking->camera.pixel_aspect;
1898
1899         resibuf= IMB_dupImBuf(ibuf);
1900
1901         if(ibuf->rect_float) {
1902                 libmv_undistortFloat(camera->focal,
1903                                      camera->principal[0], camera->principal[1] * aspy,
1904                                      camera->k1, camera->k2, camera->k3,
1905                                      ibuf->rect_float, resibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels);
1906
1907                 ibuf->userflags|= IB_RECT_INVALID;
1908         } else {
1909                 libmv_undistortByte(camera->focal,
1910                                     camera->principal[0], camera->principal[1] * aspy,
1911                                     camera->k1, camera->k2, camera->k3,
1912                                     (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, ibuf->x, ibuf->y, ibuf->channels);
1913         }
1914
1915         return resibuf;
1916 }
1917
1918 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf)
1919 {
1920         ImBuf *resibuf;
1921         MovieTrackingCamera *camera= &tracking->camera;
1922         float aspy= 1.f/tracking->camera.pixel_aspect;
1923
1924         resibuf= IMB_dupImBuf(ibuf);
1925
1926         if(ibuf->rect_float) {
1927                 libmv_distortFloat(camera->focal,
1928                                    camera->principal[0], camera->principal[1] * aspy,
1929                                    camera->k1, camera->k2, camera->k3,
1930                                    ibuf->rect_float, resibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels);
1931
1932                 ibuf->userflags|= IB_RECT_INVALID;
1933         } else {
1934                 libmv_distortByte(camera->focal,
1935                                   camera->principal[0], camera->principal[1] * aspy,
1936                                   camera->k1, camera->k2, camera->k3,
1937                                   (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, ibuf->x, ibuf->y, ibuf->channels);
1938         }
1939
1940         return resibuf;
1941 }