d65840720cd5db85583a80b17bf198e77f663502
[blender.git] / source / blender / blenkernel / intern / tracking.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenkernel/intern/tracking.c
28  *  \ingroup bke
29  */
30
31 #include <stddef.h>
32 #include <limits.h>
33 #include <math.h>
34 #include <memory.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_gpencil_types.h"
39 #include "DNA_camera_types.h"
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_math_base.h"
47 #include "BLI_listbase.h"
48 #include "BLI_ghash.h"
49 #include "BLI_path_util.h"
50
51 #include "BKE_global.h"
52 #include "BKE_tracking.h"
53 #include "BKE_movieclip.h"
54 #include "BKE_object.h"
55 #include "BKE_scene.h"
56
57 #include "IMB_imbuf_types.h"
58 #include "IMB_imbuf.h"
59
60 #ifdef WITH_LIBMV
61 #  include "libmv-capi.h"
62 #else
63 struct libmv_Features;
64 #endif
65
66 typedef struct MovieDistortion {
67         struct libmv_CameraIntrinsics *intrinsics;
68 } MovieDistortion;
69
70 /*********************** common functions *************************/
71
72 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
73 {
74         int a;
75         float pat_min[2];
76         float pat_max[2];
77         float max_pyramid_level_factor = 1.0;
78         if (track->tracker == TRACKER_KLT) {
79                 max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
80         }
81
82         /* sort */
83         for(a= 0; a<2; a++) {
84                 if(track->pat_min[a]>track->pat_max[a])
85                         SWAP(float, track->pat_min[a], track->pat_max[a]);
86
87                 if(track->search_min[a]>track->search_max[a])
88                         SWAP(float, track->search_min[a], track->search_max[a]);
89         }
90
91         /* compute the effective pattern size, which differs from the fine resolution
92          * pattern size for the pyramid KLT tracker */
93         for(a= 0; a<2; a++) {
94                 pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
95                 pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
96         }
97
98         if(event==CLAMP_PAT_DIM) {
99                 for(a= 0; a<2; a++) {
100                         /* search shouldn't be resized smaller than pattern */
101                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
102                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
103                 }
104         }
105         else if(event==CLAMP_PAT_POS) {
106                 float dim[2];
107                 sub_v2_v2v2(dim, track->pat_max, pat_min);
108
109                 for(a= 0; a<2; a++) {
110                         /* pattern shouldn't be moved outside of search */
111                         if(pat_min[a] < track->search_min[a]) {
112                                 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
113                                 track->pat_max[a]=  (pat_min[a] - track->pat_min[a])+dim[a];
114                         }
115                         if(track->pat_max[a] > track->search_max[a]) {
116                                 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
117                                 track->pat_min[a]= track->pat_max[a]-dim[a] - (pat_min[a] - track->pat_min[a]);
118                         }
119                 }
120         }
121         else if(event==CLAMP_SEARCH_DIM) {
122                 float max_pyramid_level_factor = 1.0;
123                 if (track->tracker == TRACKER_KLT) {
124                         max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
125                 }
126                 for(a= 0; a<2; a++) {
127                         /* search shouldn't be resized smaller than pattern */
128                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
129                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
130                 }
131         }
132         else if(event==CLAMP_SEARCH_POS) {
133                 float dim[2];
134                 sub_v2_v2v2(dim, track->search_max, track->search_min);
135
136                 for(a= 0; a<2; a++) {
137                         /* search shouldn't be moved inside pattern */
138                         if(track->search_min[a] > pat_min[a]) {
139                                 track->search_min[a]= pat_min[a];
140                                 track->search_max[a]= track->search_min[a]+dim[a];
141                         }
142                         if(track->search_max[a] < pat_max[a]) {
143                                 track->search_max[a]= pat_max[a];
144                                 track->search_min[a]= track->search_max[a]-dim[a];
145                         }
146                 }
147         }
148
149         else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT))  {
150                 float dim[2];
151                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
152                 {
153                         float search_ratio = 2.3f * max_pyramid_level_factor;
154
155                         /* resize the search area to something sensible based
156                          * on the number of pyramid levels */
157                         for(a= 0; a<2; a++) {
158                                 track->search_min[a]= search_ratio * track->pat_min[a];
159                                 track->search_max[a]= search_ratio * track->pat_max[a];
160                         }
161                 }
162         }
163
164         /* marker's center should be in center of pattern */
165         if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
166                 float dim[2];
167                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
168
169                 for(a= 0; a<2; a++) {
170                         track->pat_min[a]= -dim[a]/2.0f;
171                         track->pat_max[a]= dim[a]/2.0f;
172                 }
173         }
174 }
175
176 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
177 {
178         if(area==TRACK_AREA_NONE)
179                 return;
180
181         if(clear) {
182                 if(area&TRACK_AREA_POINT)       track->flag&= ~flag;
183                 if(area&TRACK_AREA_PAT)         track->pat_flag&= ~flag;
184                 if(area&TRACK_AREA_SEARCH)      track->search_flag&= ~flag;
185         } else {
186                 if(area&TRACK_AREA_POINT)       track->flag|= flag;
187                 if(area&TRACK_AREA_PAT)         track->pat_flag|= flag;
188                 if(area&TRACK_AREA_SEARCH)      track->search_flag|= flag;
189         }
190 }
191
192 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y,
193                         int framenr, int width, int height)
194 {
195         MovieTrackingTrack *track;
196         MovieTrackingMarker marker;
197
198         /* pick reasonable defaults */
199         float pat[2]= {5.5f, 5.5f}, search[2]= {25.5f, 25.5f}; /* TODO: move to default setting? */
200
201         pat[0] /= (float)width;
202         pat[1] /= (float)height;
203
204         search[0] /= (float)width;
205         search[1] /= (float)height;
206
207         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
208         strcpy(track->name, "Track");
209
210         /* default to KLT tracker */
211         track->tracker = TRACKER_KLT;
212         track->pyramid_levels = 2;
213
214         /* set SAD defaults even though it's not selected by default */
215         track->minimum_correlation= 0.75f;
216
217         memset(&marker, 0, sizeof(marker));
218         marker.pos[0]= x;
219         marker.pos[1]= y;
220         marker.framenr= framenr;
221
222         copy_v2_v2(track->pat_max, pat);
223         negate_v2_v2(track->pat_min, pat);
224
225         copy_v2_v2(track->search_max, search);
226         negate_v2_v2(track->search_min, search);
227
228         BKE_tracking_insert_marker(track, &marker);
229
230         BLI_addtail(&tracking->tracks, track);
231         BKE_track_unique_name(tracking, track);
232
233         return track;
234 }
235
236 void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
237 {
238         MovieTrackingMarker *old_marker= BKE_tracking_get_marker(track, marker->framenr);
239
240         if(old_marker && old_marker->framenr==marker->framenr) {
241                 *old_marker= *marker;
242         } else {
243                 int a= track->markersnr;
244
245                 while(a--) {
246                         if(track->markers[a].framenr<marker->framenr)
247                                 break;
248                 }
249
250                 track->markersnr++;
251
252                 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
253                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
254
255                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
256                 track->markers[a+1]= *marker;
257
258                 track->last_marker= a+1;
259         }
260 }
261
262 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
263 {
264         int a= 0;
265
266         while(a<track->markersnr) {
267                 if(track->markers[a].framenr==framenr) {
268                         if(track->markersnr>1) {
269                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
270                                 track->markersnr--;
271                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
272                         } else {
273                                 MEM_freeN(track->markers);
274                                 track->markers= NULL;
275                                 track->markersnr= 0;
276                         }
277
278                         break;
279                 }
280
281                 a++;
282         }
283 }
284
285 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
286 {
287         int a= track->markersnr-1;
288
289         if(!track->markersnr)
290                 return NULL;
291
292         /* approximate pre-first framenr marker with first marker */
293         if(framenr<track->markers[0].framenr)
294                 return &track->markers[0];
295
296         if(track->last_marker<track->markersnr)
297                 a= track->last_marker;
298
299         if(track->markers[a].framenr<=framenr) {
300                 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
301                         if(track->markers[a].framenr==framenr) {
302                                 track->last_marker= a;
303                                 return &track->markers[a];
304                         }
305                         a++;
306                 }
307
308                 /* if there's no marker for exact position, use nearest marker from left side */
309                 return &track->markers[a-1];
310         } else {
311                 while(a>=0 && track->markers[a].framenr>=framenr) {
312                         if(track->markers[a].framenr==framenr) {
313                                 track->last_marker= a;
314                                 return &track->markers[a];
315                         }
316
317                         a--;
318                 }
319
320                 /* if there's no marker for exact position, use nearest marker from left side */
321                 return &track->markers[a];
322         }
323
324         return NULL;
325 }
326
327 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
328 {
329         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
330
331         if(marker && marker->framenr!=framenr) {
332                 MovieTrackingMarker marker_new;
333
334                 marker_new= *marker;
335                 marker_new.framenr= framenr;
336
337                 BKE_tracking_insert_marker(track, &marker_new);
338                 marker= BKE_tracking_get_marker(track, framenr);
339         }
340
341         return marker;
342 }
343
344 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
345 {
346         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
347
348         if(marker && marker->framenr!=framenr)
349                 return NULL;
350
351         return marker;
352 }
353
354 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
355 {
356         return BKE_tracking_exact_marker(track, framenr) != 0;
357 }
358
359 void BKE_tracking_free_track(MovieTrackingTrack *track)
360 {
361         if(track->markers) MEM_freeN(track->markers);
362 }
363
364 MovieTrackingTrack *BKE_tracking_copy_track(MovieTrackingTrack *track)
365 {
366         MovieTrackingTrack *new_track= MEM_dupallocN(track);
367
368         new_track->next= new_track->prev= NULL;
369
370         if(new_track->markers)
371                 new_track->markers= MEM_dupallocN(new_track->markers);
372
373         return new_track;
374 }
375
376 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
377 {
378         MovieTrackingMarker marker_new;
379
380         marker_new= *ref_marker;
381         marker_new.flag&= ~MARKER_TRACKED;
382         marker_new.flag|= MARKER_DISABLED;
383
384         if(before) marker_new.framenr--;
385         else marker_new.framenr++;
386
387         if(!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
388                 BKE_tracking_insert_marker(track, &marker_new);
389 }
390
391 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
392 {
393         int a;
394
395         if(action==TRACK_CLEAR_REMAINED) {
396                 a= 1;
397                 while(a<track->markersnr) {
398                         if(track->markers[a].framenr>ref_frame) {
399                                 track->markersnr= a;
400                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
401
402                                 break;
403                         }
404
405                         a++;
406                 }
407
408                 if(track->markersnr)
409                         put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1);
410         } else if(action==TRACK_CLEAR_UPTO) {
411                 a= track->markersnr-1;
412                 while(a>=0) {
413                         if(track->markers[a].framenr<=ref_frame) {
414                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
415
416                                 track->markersnr= track->markersnr-a;
417                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
418
419                                 break;
420                         }
421
422                         a--;
423                 }
424
425                 if(track->markersnr)
426                         put_disabled_marker(track, &track->markers[0], 1, 1);
427         } else if(action==TRACK_CLEAR_ALL) {
428                 MovieTrackingMarker *marker, marker_new;
429
430                 marker= BKE_tracking_get_marker(track, ref_frame);
431                 marker_new= *marker;
432
433                 MEM_freeN(track->markers);
434                 track->markers= NULL;
435                 track->markersnr= 0;
436
437                 BKE_tracking_insert_marker(track, &marker_new);
438
439                 put_disabled_marker(track, &marker_new, 1, 1);
440                 put_disabled_marker(track, &marker_new, 0, 1);
441         }
442 }
443
444 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
445 {
446         int a= 0, b= 0;
447         /* int tot= dst_track->markersnr+src_track->markersnr; */ /* UNUSED */
448         int count= 0;
449
450         while(a<src_track->markersnr || b<dst_track->markersnr) {
451                 if(b>=dst_track->markersnr) {
452                         a++;
453                         count++;
454                 }
455                 else if(a>=src_track->markersnr) {
456                         b++;
457                         count++;
458                 }
459                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
460                         a++;
461                         count++;
462                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
463                         b++;
464                         count++;
465                 } else {
466                         if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
467                                 return 0;
468
469                         a++;
470                         b++;
471                         count++;
472                 }
473         }
474
475         return count;
476 }
477
478 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
479 {
480         int i, a= 0, b= 0, tot;
481         MovieTrackingMarker *markers;
482
483         tot= BKE_tracking_test_join_tracks(dst_track, src_track);
484
485         markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
486
487         for(i= 0; i<tot; i++) {
488                 if(b>=dst_track->markersnr) {
489                         markers[i]= src_track->markers[a++];
490                 }
491                 else if(a>=src_track->markersnr) {
492                         markers[i]= dst_track->markers[b++];
493                 }
494                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
495                         markers[i]= src_track->markers[a++];
496                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
497                         markers[i]= dst_track->markers[b++];
498                 } else {
499                         if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
500                         else markers[i]= src_track->markers[a++];
501
502                         a++;
503                         b++;
504                 }
505         }
506
507         MEM_freeN(dst_track->markers);
508
509         dst_track->markers= markers;
510         dst_track->markersnr= tot;
511 }
512
513 void BKE_tracking_free(MovieTracking *tracking)
514 {
515         MovieTrackingTrack *track;
516
517         for(track= tracking->tracks.first; track; track= track->next) {
518                 BKE_tracking_free_track(track);
519         }
520
521         BLI_freelistN(&tracking->tracks);
522
523         if(tracking->reconstruction.cameras)
524                 MEM_freeN(tracking->reconstruction.cameras);
525
526         if(tracking->stabilization.scaleibuf)
527                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
528
529         if(tracking->camera.intrinsics)
530                 BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
531 }
532
533 /*********************** tracking *************************/
534
535 typedef struct TrackContext {
536         MovieTrackingTrack *track;
537
538 #ifdef WITH_LIBMV
539         float keyframed_pos[2];
540
541         /* ** KLT tracker ** */
542         struct libmv_RegionTracker *region_tracker;
543         float *patch;                   /* keyframed patch */
544
545         /* ** SAD tracker ** */
546         int patsize;                    /* size of pattern (currently only 16x16 due to libmv side) */
547         unsigned char *pattern; /* keyframed pattern */
548         unsigned char *warped;  /* warped version of reference */
549 #endif
550 } TrackContext;
551
552 typedef struct MovieTrackingContext {
553         MovieClipUser user;
554         MovieClip *clip;
555
556         int first_time, frames;
557
558         TrackContext *track_context;
559         int num_tracks;
560
561         GHash *hash;
562         MovieTrackingSettings settings;
563
564         short backwards, disable_failed;
565         int sync_frame;
566 } MovieTrackingContext;
567
568 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short disable_failed)
569 {
570         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
571         MovieTracking *tracking= &clip->tracking;
572         MovieTrackingSettings *settings= &tracking->settings;
573         MovieTrackingTrack *track;
574         TrackContext *track_context;
575
576         context->settings= *settings;
577         context->backwards= backwards;
578         context->disable_failed= disable_failed;
579         context->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "tracking trackHash");
580         context->sync_frame= user->framenr;
581         context->first_time= 1;
582
583         /* count */
584         track= tracking->tracks.first;
585         while(track) {
586                 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
587                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
588
589                         if((marker->flag&MARKER_DISABLED)==0)
590                                 context->num_tracks++;
591                 }
592
593                 track= track->next;
594         }
595
596         if(context->num_tracks) {
597                 int width, height;
598
599                 BKE_movieclip_get_size(clip, user, &width, &height);
600
601                 /* create tracking data */
602                 context->track_context= MEM_callocN(sizeof(TrackContext)*context->num_tracks, "tracking track_context");
603
604                 track_context= context->track_context;
605                 track= tracking->tracks.first;
606                 while(track) {
607                         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
608                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
609
610                                 if((marker->flag&MARKER_DISABLED)==0) {
611                                         MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
612
613                                         track_context->track= new_track;
614 #ifdef WITH_LIBMV
615                                         {
616                                                 if(track_context->track->tracker==TRACKER_KLT) {
617                                                         float search_size_x= (track->search_max[0]-track->search_min[0])*width;
618                                                         float search_size_y= (track->search_max[1]-track->search_min[1])*height;
619                                                         float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
620                                                         float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
621
622                                                         /* compute the maximum pyramid size */
623                                                         double search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
624                                                                 / MAX2(pattern_size_x, pattern_size_y);
625                                                         double log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
626                                                         int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
627
628                                                         /* try to accomodate the user's choice of pyramid level in a way
629                                                          * that doesn't cause the coarsest pyramid pattern to be larger
630                                                          * than the search size */
631                                                         int level= MIN2(track_context->track->pyramid_levels, max_pyramid_levels);
632                                                         track_context->region_tracker= libmv_regionTrackerNew(100, level);
633                                                 }
634                                                 else if(track_context->track->tracker==TRACKER_SAD) {
635                                                         /* nothing to initialize */
636                                                 }
637                                         }
638 #endif
639
640                                         BLI_ghash_insert(context->hash, new_track, track);
641
642                                         track_context++;
643                                 }
644                         }
645
646                         track= track->next;
647                 }
648         }
649
650         context->clip= clip;
651         context->user= *user;
652
653         return context;
654 }
655
656 void BKE_tracking_context_free(MovieTrackingContext *context)
657 {
658         int a;
659         TrackContext *track_context;
660
661         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
662                 BKE_tracking_free_track(context->track_context[a].track);
663
664 #if WITH_LIBMV
665                 if(track_context->region_tracker)
666                         libmv_regionTrackerDestroy(track_context->region_tracker);
667
668                 if(track_context->patch)
669                         MEM_freeN(track_context->patch);
670
671                 if(track_context->pattern)
672                         MEM_freeN(track_context->pattern);
673
674                 if(track_context->warped)
675                         MEM_freeN(track_context->warped);
676 #endif
677
678                 MEM_freeN(track_context->track);
679         }
680
681         if(context->track_context)
682                 MEM_freeN(context->track_context);
683
684         BLI_ghash_free(context->hash, NULL, NULL);
685
686         MEM_freeN(context);
687 }
688
689 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
690 {
691         int x, y;
692
693         if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
694                 return;
695
696         for(y= 0; y<ibuf->y; y++) {
697                 for (x= 0; x<ibuf->x; x++) {
698                         int pixel= ibuf->x*y + x;
699
700                         if(ibuf->rect_float) {
701                                 float *rrgbf= ibuf->rect_float + pixel*4;
702
703                                 if(track->flag&TRACK_DISABLE_RED)       rrgbf[0]= 0;
704                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgbf[1]= 0;
705                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgbf[2]= 0;
706                         } else {
707                                 char *rrgb= (char*)ibuf->rect + pixel*4;
708
709                                 if(track->flag&TRACK_DISABLE_RED)       rrgb[0]= 0;
710                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgb[1]= 0;
711                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgb[2]= 0;
712                         }
713                 }
714         }
715 }
716
717 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
718                         float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
719 {
720         ImBuf *tmpibuf;
721         int x, y;
722         int x1, y1, x2, y2, w, h;
723         float mpos[2];
724
725         copy_v2_v2(mpos, marker->pos);
726         if(anchored)
727                 add_v2_v2(mpos, track->offset);
728
729         x= mpos[0]*ibuf->x;
730         y= mpos[1]*ibuf->y;
731         x1= x-(int)(-min[0]*ibuf->x);
732         y1= y-(int)(-min[1]*ibuf->y);
733         x2= x+(int)(max[0]*ibuf->x);
734         y2= y+(int)(max[1]*ibuf->y);
735
736         /* dimensions should be odd */
737         w= (x2-x1)|1;
738         h= (y2-y1)|1;
739
740         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
741         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
742
743         if(pos != NULL) {
744                 pos[0]= mpos[0]*ibuf->x-x1+margin;
745                 pos[1]= mpos[1]*ibuf->y-y1+margin;
746         }
747
748         if(origin != NULL) {
749                 origin[0]= x1-margin;
750                 origin[1]= y1-margin;
751         }
752
753         disable_imbuf_channels(tmpibuf, track);
754
755         return tmpibuf;
756 }
757
758 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
759                         int margin, int anchored, float pos[2], int origin[2])
760 {
761         return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
762 }
763
764 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
765                         int margin, int anchored, float pos[2], int origin[2])
766 {
767         return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
768 }
769
770 #ifdef WITH_LIBMV
771 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
772                         int *width_r, int *height_r, float pos[2], int origin[2])
773 {
774         ImBuf *tmpibuf;
775         float *pixels, *fp;
776         int x, y, width, height;
777
778         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
779         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
780
781         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
782         disable_imbuf_channels(tmpibuf, track);
783
784         *width_r= width;
785         *height_r= height;
786
787         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
788         for(y= 0; y<(int)height; y++) {
789                 for (x= 0; x<(int)width; x++) {
790                         int pixel= tmpibuf->x*y + x;
791
792                         if(tmpibuf->rect_float) {
793                                 float *rrgbf= tmpibuf->rect_float + pixel*4;
794
795                                 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
796                         } else {
797                                 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
798
799                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
800                         }
801
802                         fp++;
803                 }
804         }
805
806         IMB_freeImBuf(tmpibuf);
807
808         return pixels;
809 }
810
811 static unsigned char *get_ucharbuf(ImBuf *ibuf)
812 {
813         int x, y;
814         unsigned char *pixels, *cp;
815
816         cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
817         for(y= 0; y<ibuf->y; y++) {
818                 for (x= 0; x<ibuf->x; x++) {
819                         int pixel= ibuf->x*y + x;
820
821                         if(ibuf->rect_float) {
822                                 float *rrgbf= ibuf->rect_float + pixel*4;
823
824                                 *cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]);
825                         } else {
826                                 unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
827
828                                 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
829                         }
830
831                         cp++;
832                 }
833         }
834
835         return pixels;
836 }
837
838 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
839                         int *width_r, int *height_r, float pos[2], int origin[2])
840 {
841         ImBuf *tmpibuf;
842         unsigned char *pixels;
843
844         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
845         disable_imbuf_channels(tmpibuf, track);
846
847         *width_r= tmpibuf->x;
848         *height_r= tmpibuf->y;
849
850         pixels= get_ucharbuf(tmpibuf);
851
852         IMB_freeImBuf(tmpibuf);
853
854         return pixels;
855 }
856
857 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
858 {
859         ImBuf *ibuf;
860         int framenr_old= context->user.framenr;
861
862         context->user.framenr= framenr;
863
864         ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, 0);
865
866         context->user.framenr= framenr_old;
867
868         return ibuf;
869 }
870
871 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
872                         MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
873 {
874         int framenr= marker->framenr;
875         int a= marker-track->markers;
876
877         *marker_keyed= marker;
878
879         while(a>=0 && a<track->markersnr) {
880                 int next= (context->backwards) ? a+1 : a-1;
881                 int is_keyframed= 0;
882                 MovieTrackingMarker *marker= &track->markers[a];
883                 MovieTrackingMarker *next_marker= NULL;
884
885                 if(next>=0 && next<track->markersnr)
886                         next_marker= &track->markers[next];
887
888                 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
889                 if(next_marker && next_marker->flag&MARKER_DISABLED)
890                         is_keyframed= 1;
891
892                 is_keyframed|= (marker->flag&MARKER_TRACKED)==0;
893
894                 if(is_keyframed) {
895                         framenr= marker->framenr;
896                         *marker_keyed= marker;
897                         break;
898                 }
899
900                 a= next;
901         }
902
903         return get_frame_ibuf(context, framenr);
904 }
905
906 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
907                         int curfra, MovieTrackingMarker **marker_keyed)
908 {
909         ImBuf *ibuf= NULL;
910
911         if(context->settings.adjframes == 0) {
912                 ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed);
913         } else {
914                 ibuf= get_frame_ibuf(context, curfra);
915
916                 /* use current marker as keyframed position */
917                 *marker_keyed= marker;
918         }
919
920         return ibuf;
921 }
922
923 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
924 {
925         int i, j;
926
927         for(i=0; i<track_context->patsize; i++) {
928                 for(j=0; j<track_context->patsize; j++) {
929                         track_context->warped[i*track_context->patsize+j]=
930                                         image[(y+i-track_context->patsize/2)*width+x+j-track_context->patsize/2];
931                 }
932         }
933 }
934
935 #endif
936
937 void BKE_tracking_sync(MovieTrackingContext *context)
938 {
939         TrackContext *track_context;
940         MovieTracking *tracking= &context->clip->tracking;
941         MovieTrackingTrack *track;
942         ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
943         ListBase *old_tracks= &context->clip->tracking.tracks;
944         int a, newframe;
945
946         /* duplicate currently tracking tracks to temporary list.
947            this is needed to keep names in unique state and it's faster to change names
948            of currently tracking tracks (if needed) */
949         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
950                 int replace_sel= 0;
951                 MovieTrackingTrack *new_track, *old;
952
953                 track= track_context->track;
954
955                 /* find original of tracking track in list of previously displayed tracks */
956                 old= BLI_ghash_lookup(context->hash, track);
957                 if(old) {
958                         MovieTrackingTrack *cur= old_tracks->first;
959
960                         while(cur) {
961                                 if(cur==old)
962                                         break;
963
964                                 cur= cur->next;
965                         }
966
967                         /* original track was found, re-use flags and remove this track */
968                         if(cur) {
969                                 if(cur==tracking->act_track)
970                                         replace_sel= 1;
971
972                                 track->flag= cur->flag;
973                                 track->pat_flag= cur->pat_flag;
974                                 track->search_flag= cur->search_flag;
975
976                                 BKE_tracking_free_track(cur);
977                                 BLI_freelinkN(old_tracks, cur);
978                         }
979                 }
980
981                 new_track= BKE_tracking_copy_track(track);
982
983                 BLI_ghash_remove(context->hash, track, NULL, NULL); /* XXX: are we actually need this */
984                 BLI_ghash_insert(context->hash, track, new_track);
985
986                 if(replace_sel)         /* update current selection in clip */
987                         tracking->act_track= new_track;
988
989                 BLI_addtail(&tracks, new_track);
990         }
991
992         /* move all tracks, which aren't tracking */
993         track= old_tracks->first;
994         while(track) {
995                 MovieTrackingTrack *next= track->next;
996
997                 track->next= track->prev= NULL;
998                 BLI_addtail(&new_tracks, track);
999
1000                 track= next;
1001         }
1002
1003         /* now move all tracks which are currently tracking and keep their names unique */
1004         track= tracks.first;
1005         while(track) {
1006                 MovieTrackingTrack *next= track->next;
1007
1008                 BLI_remlink(&tracks, track);
1009
1010                 track->next= track->prev= NULL;
1011                 BLI_addtail(&new_tracks, track);
1012
1013                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1014
1015                 track= next;
1016         }
1017
1018         context->clip->tracking.tracks= new_tracks;
1019
1020         if(context->backwards) newframe= context->user.framenr+1;
1021         else newframe= context->user.framenr-1;
1022
1023         context->sync_frame= newframe;
1024 }
1025
1026 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
1027 {
1028         user->framenr= context->sync_frame;
1029 }
1030
1031 int BKE_tracking_next(MovieTrackingContext *context)
1032 {
1033         ImBuf *ibuf_new;
1034         int curfra= context->user.framenr;
1035         int a, ok= 0;
1036
1037         /* nothing to track, avoid unneeded frames reading to save time and memory */
1038         if(!context->num_tracks)
1039                 return 0;
1040
1041         if(context->backwards) context->user.framenr--;
1042         else context->user.framenr++;
1043
1044         ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, 0);
1045         if(!ibuf_new)
1046                 return 0;
1047
1048         #pragma omp parallel for private(a) shared(ibuf_new, ok) if(context->num_tracks>1)
1049         for(a= 0; a<context->num_tracks; a++) {
1050                 TrackContext *track_context= &context->track_context[a];
1051                 MovieTrackingTrack *track= track_context->track;
1052                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, curfra);
1053
1054                 if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
1055 #ifdef WITH_LIBMV
1056                         int width, height, origin[2], tracked= 0, need_readjust= 0;
1057                         float pos[2], margin[2];
1058                         double x1, y1, x2, y2;
1059                         ImBuf *ibuf= NULL;
1060                         MovieTrackingMarker marker_new, *marker_keyed;
1061                         int onbound= 0, coords_correct= 0;
1062                         int nextfra;
1063
1064                         if(!context->settings.adjframes) need_readjust= context->first_time;
1065                         else need_readjust= context->frames%context->settings.adjframes == 0;
1066
1067                         if(context->backwards) nextfra= curfra-1;
1068                         else nextfra= curfra+1;
1069
1070                         /* margin from frame boundaries */
1071                         sub_v2_v2v2(margin, track->pat_max, track->pat_min);
1072
1073                         margin[0]= MAX2(margin[0], (float)context->settings.margin / ibuf_new->x);
1074                         margin[1]= MAX2(margin[1], (float)context->settings.margin / ibuf_new->y);
1075
1076                         /* do not track markers which are too close to boundary */
1077                         if(marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] ||
1078                            marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
1079                                 onbound= 1;
1080                         }
1081                         else if(track_context->track->tracker==TRACKER_KLT) {
1082                                 int wndx, wndy;
1083                                 float *patch_new;
1084
1085                                 if(need_readjust) {
1086                                         /* calculate patch for keyframed position */
1087                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1088
1089                                         if(track_context->patch)
1090                                                 MEM_freeN(track_context->patch);
1091
1092                                         track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin);
1093
1094                                         IMB_freeImBuf(ibuf);
1095                                 }
1096
1097                                 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1098
1099                                 x1= track_context->keyframed_pos[0];
1100                                 y1= track_context->keyframed_pos[1];
1101
1102                                 x2= pos[0];
1103                                 y2= pos[1];
1104
1105                                 wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf_new->x)/2;
1106                                 wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf_new->y)/2;
1107
1108                                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1109                                                         width, height, MAX2(wndx, wndy), x1, y1, &x2, &y2);
1110
1111                                 MEM_freeN(patch_new);
1112                         }
1113                         else if(track_context->track->tracker==TRACKER_SAD) {
1114                                 unsigned char *image_new;
1115                                 float correlation;
1116                                 float warp[3][2]={{0}};
1117
1118                                 if(need_readjust) {
1119                                         unsigned char *image;
1120
1121                                         /* calculate pattern for keyframed position */
1122                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1123
1124                                         image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1125
1126                                         memset(warp, 0, sizeof(warp));
1127                                         warp[0][0]= 1;
1128                                         warp[1][1]= 1;
1129                                         warp[2][0]= pos[0];
1130                                         warp[2][1]= pos[1];
1131
1132                                         /* pattern size is hardcoded to 16x16px in libmv */
1133                                         track_context->patsize= 16;
1134
1135                                         if(!track_context->pattern)
1136                                                 track_context->pattern= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking pattern");
1137
1138                                         libmv_SADSamplePattern(image, width, warp, track_context->pattern);
1139
1140                                         MEM_freeN(image);
1141                                         IMB_freeImBuf(ibuf);
1142                                 }
1143
1144                                 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1145
1146                                 if(track_context->warped==NULL) {
1147                                         unsigned char *image_old;
1148
1149                                         ibuf= get_frame_ibuf(context, curfra);
1150
1151                                         if(track_context->warped==NULL)
1152                                                 track_context->warped= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking warped");
1153
1154                                         image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1155                                         get_warped(track_context, pos[0], pos[1], width, image_old);
1156                                         IMB_freeImBuf(ibuf);
1157                                         MEM_freeN(image_old);
1158                                 }
1159
1160                                 memset(warp, 0, sizeof(warp));
1161                                 warp[0][0]= 1;
1162                                 warp[1][1]= 1;
1163                                 warp[2][0]= pos[0];
1164                                 warp[2][1]= pos[1];
1165
1166                                 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
1167
1168                                 x2= warp[2][0];
1169                                 y2= warp[2][1];
1170
1171                                 tracked= track_context->track->minimum_correlation < correlation;
1172
1173                                 if(tracked)
1174                                         get_warped(track_context, x2, y2, width, image_new);
1175
1176                                 MEM_freeN(image_new);
1177                         }
1178
1179                         coords_correct= !isnan(x2) && !isnan(y2) && finite(x2) && finite(y2);
1180                         if(coords_correct && (tracked || !context->disable_failed)) {
1181                                 if(context->first_time) {
1182                                         #pragma omp critical
1183                                         {
1184                                                 /* check if there's no keyframe/tracked markers before tracking marker.
1185                                                     if so -- create disabled marker before currently tracking "segment" */
1186                                                 put_disabled_marker(track, marker, 1, 0);
1187                                         }
1188                                 }
1189
1190                                 memset(&marker_new, 0, sizeof(marker_new));
1191
1192                                 if(!onbound) {
1193                                         marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1194                                         marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1195                                 } else {
1196                                         copy_v2_v2(marker_new.pos, marker->pos);
1197                                 }
1198
1199                                 marker_new.flag|= MARKER_TRACKED;
1200                                 marker_new.framenr= nextfra;
1201
1202                                 #pragma omp critical
1203                                 {
1204                                         BKE_tracking_insert_marker(track, &marker_new);
1205                                 }
1206
1207                                 /* make currently tracked segment be finished with disabled marker */
1208                                 #pragma omp critical
1209                                 {
1210                                         put_disabled_marker(track, &marker_new, 0, 0);
1211                                 }
1212                         } else {
1213                                 marker_new= *marker;
1214
1215                                 marker_new.framenr= nextfra;
1216                                 marker_new.flag|= MARKER_DISABLED;
1217
1218                                 #pragma omp critical
1219                                 {
1220                                         BKE_tracking_insert_marker(track, &marker_new);
1221                                 }
1222                         }
1223
1224                         ok= 1;
1225 #endif
1226                 }
1227         }
1228
1229         IMB_freeImBuf(ibuf_new);
1230
1231         context->first_time= 0;
1232         context->frames++;
1233
1234         return ok;
1235 }
1236
1237 #if WITH_LIBMV
1238 static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height)
1239 {
1240         int tracknr= 0;
1241         MovieTrackingTrack *track;
1242         struct libmv_Tracks *tracks= libmv_tracksNew();
1243
1244         track= tracking->tracks.first;
1245         while(track) {
1246                 int a= 0;
1247
1248                 for(a= 0; a<track->markersnr; a++) {
1249                         MovieTrackingMarker *marker= &track->markers[a];
1250
1251                         if((marker->flag&MARKER_DISABLED)==0)
1252                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1253                                                         marker->pos[0]*width, marker->pos[1]*height);
1254                 }
1255
1256                 track= track->next;
1257                 tracknr++;
1258         }
1259
1260         return tracks;
1261 }
1262
1263 static int retrieve_libmv_reconstruct(MovieTracking *tracking, struct libmv_Reconstruction *libmv_reconstruction)
1264 {
1265         int tracknr= 0;
1266         int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0;
1267         MovieTrackingTrack *track;
1268         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1269         MovieReconstructedCamera *reconstructed;
1270         float origin[3]= {0.0f, 0.0f, 0.0f};
1271         int ok= 1;
1272
1273         track= tracking->tracks.first;
1274         while(track) {
1275                 double pos[3];
1276
1277                 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1278                         track->bundle_pos[0]= pos[0];
1279                         track->bundle_pos[1]= pos[1];
1280                         track->bundle_pos[2]= pos[2];
1281
1282                         track->flag|= TRACK_HAS_BUNDLE;
1283                         track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1284                 } else {
1285                         track->flag&= ~TRACK_HAS_BUNDLE;
1286                         ok= 0;
1287
1288                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1289                 }
1290
1291                 if(track->markersnr) {
1292                         int first= 0, last= track->markersnr;
1293                         MovieTrackingMarker *first_marker= &track->markers[0];
1294                         MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1];
1295
1296                         /* find first not-disabled marker */
1297                         while(first<track->markersnr-1 && first_marker->flag&MARKER_DISABLED) {
1298                                 first++;
1299                                 first_marker++;
1300                         }
1301
1302                         /* find last not-disabled marker */
1303                         while(last>=0 && last_marker->flag&MARKER_DISABLED) {
1304                                 last--;
1305                                 last_marker--;
1306                         }
1307
1308                         if(first<track->markersnr-1)
1309                                 sfra= MIN2(sfra, first_marker->framenr);
1310
1311                         if(last>=0)
1312                                 efra= MAX2(efra, last_marker->framenr);
1313                 }
1314
1315                 track= track->next;
1316                 tracknr++;
1317         }
1318
1319         if(reconstruction->cameras)
1320                 MEM_freeN(reconstruction->cameras);
1321
1322         reconstruction->camnr= 0;
1323         reconstruction->cameras= NULL;
1324         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1325
1326         for(a= sfra; a<=efra; a++) {
1327                 double matd[4][4];
1328
1329                 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1330                         int i, j;
1331                         float mat[4][4];
1332                         float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a);
1333
1334                         for(i=0; i<4; i++)
1335                                 for(j= 0; j<4; j++)
1336                                         mat[i][j]= matd[i][j];
1337
1338                         if(!origin_set) {
1339                                 copy_v3_v3(origin, mat[3]);
1340                                 origin_set= 1;
1341                         }
1342
1343                         if(origin_set)
1344                                 sub_v3_v3(mat[3], origin);
1345
1346                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1347                         reconstructed[reconstruction->camnr].framenr= a;
1348                         reconstructed[reconstruction->camnr].error= error;
1349                         reconstruction->camnr++;
1350                 } else {
1351                         ok= 0;
1352                         printf("No camera for frame %d\n", a);
1353                 }
1354         }
1355
1356         if(reconstruction->camnr) {
1357                 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1358                 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1359         }
1360
1361         if(origin_set) {
1362                 track= tracking->tracks.first;
1363                 while(track) {
1364                         if(track->flag&TRACK_HAS_BUNDLE)
1365                                 sub_v3_v3(track->bundle_pos, origin);
1366
1367                         track= track->next;
1368                 }
1369         }
1370
1371         MEM_freeN(reconstructed);
1372
1373         return ok;
1374 }
1375
1376 #endif
1377
1378 float BKE_tracking_solve_reconstruction(MovieTracking *tracking, int width, int height)
1379 {
1380 #if WITH_LIBMV
1381         {
1382                 MovieTrackingCamera *camera= &tracking->camera;
1383                 float aspy= 1.0f/tracking->camera.pixel_aspect;
1384                 struct libmv_Tracks *tracks= create_libmv_tracks(tracking, width, height*aspy);
1385                 struct libmv_Reconstruction *reconstruction = libmv_solveReconstruction(tracks,
1386                         tracking->settings.keyframe1, tracking->settings.keyframe2,
1387                         camera->focal,
1388                         camera->principal[0], camera->principal[1]*aspy,
1389                         camera->k1, camera->k2, camera->k3);
1390                 float error= libmv_reprojectionError(reconstruction);
1391
1392                 tracking->reconstruction.error= error;
1393
1394                 if(!retrieve_libmv_reconstruct(tracking, reconstruction))
1395                         error= -1.0f;
1396
1397                 libmv_destroyReconstruction(reconstruction);
1398                 libmv_tracksDestroy(tracks);
1399
1400                 tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
1401
1402                 return error;
1403         }
1404 #else
1405         (void)tracking;
1406         (void)width;
1407         (void)height;
1408
1409         return -1.0f;
1410 #endif
1411 }
1412
1413 void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
1414 {
1415         BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1416 }
1417
1418 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char *name)
1419 {
1420         MovieTrackingTrack *track= tracking->tracks.first;
1421
1422         while(track) {
1423                 if(!strcmp(track->name, name))
1424                         return track;
1425
1426                 track= track->next;
1427         }
1428
1429         return NULL;
1430 }
1431
1432 static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest)
1433 {
1434         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1435         MovieReconstructedCamera *cameras= reconstruction->cameras;
1436         int a= 0, d= 1;
1437
1438         if(!reconstruction->camnr)
1439                 return -1;
1440
1441         if(framenr<cameras[0].framenr) {
1442                 if(nearest) return 0;
1443                 else return -1;
1444         }
1445
1446         if(framenr>cameras[reconstruction->camnr-1].framenr) {
1447                 if(nearest) return reconstruction->camnr-1;
1448                 else return -1;
1449         }
1450
1451         if(reconstruction->last_camera<reconstruction->camnr)
1452                 a= reconstruction->last_camera;
1453
1454         if(cameras[a].framenr>=framenr)
1455                 d= -1;
1456
1457         while(a>=0 && a<reconstruction->camnr) {
1458                 int cfra= cameras[a].framenr;
1459
1460                 /* check if needed framenr was "skipped" -- no data for requested frame */
1461
1462                 if(d>0 && cfra>framenr) {
1463                         /* interpolate with previous position */
1464                         if(nearest) return a-1;
1465                         else break;
1466                 }
1467
1468                 if(d<0 && cfra<framenr) {
1469                         /* interpolate with next position */
1470                         if(nearest) return a;
1471                         else break;
1472                 }
1473
1474                 if(cfra==framenr) {
1475                         reconstruction->last_camera= a;
1476
1477                         return a;
1478                 }
1479
1480                 a+= d;
1481         }
1482
1483         return -1;
1484 }
1485
1486 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
1487 {
1488         int a= reconstruction_camera_index(tracking, framenr, 0);
1489
1490         if(a==-1)
1491                 return NULL;
1492
1493         return &tracking->reconstruction.cameras[a];
1494 }
1495
1496 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4])
1497 {
1498         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1499         MovieReconstructedCamera *cameras= reconstruction->cameras;
1500         int a= reconstruction_camera_index(tracking, framenr, 1);
1501
1502         if(a==-1) {
1503                 unit_m4(mat);
1504                 return;
1505         }
1506
1507         if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
1508                 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
1509
1510                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
1511         } else {
1512                 copy_m4_m4(mat, cameras[a].mat);
1513         }
1514 }
1515
1516 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
1517 {
1518         if(!ob) {
1519                 if(scene->camera) ob= scene->camera;
1520                 else ob= scene_find_camera(scene);
1521         }
1522
1523         if(ob)
1524                 where_is_object_mat(scene, ob, mat);
1525         else
1526                 unit_m4(mat);
1527 }
1528
1529 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
1530 {
1531         *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx;
1532         *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx;
1533 }
1534
1535 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
1536 {
1537         float focal= tracking->camera.focal;
1538
1539         camera->sensor_x= tracking->camera.sensor_width;
1540         camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO;
1541         camera->lens= focal*camera->sensor_x/width;
1542
1543         scene->r.xsch= width*tracking->camera.pixel_aspect;
1544         scene->r.ysch= height;
1545
1546         scene->r.xasp= 1.0f;
1547         scene->r.yasp= 1.0f;
1548
1549         BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
1550 }
1551
1552 void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
1553 {
1554         MovieReconstructedCamera *camera;
1555         float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
1556         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
1557         float winmat[4][4];
1558         float ycor= 1.0f/tracking->camera.pixel_aspect;
1559         float shiftx, shifty, winside= MAX2(winx, winy);
1560
1561         BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
1562
1563         clipsta= 0.1f;
1564         clipend= 1000.0f;
1565
1566         if(winx >= winy)
1567                 viewfac= (lens*winx)/tracking->camera.sensor_width;
1568         else
1569                 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
1570
1571         pixsize= clipsta/viewfac;
1572
1573         left= -0.5f*(float)winx + shiftx*winside;
1574         bottom= -0.5f*(ycor)*(float)winy + shifty*winside;
1575         right=  0.5f*(float)winx + shiftx*winside;
1576         top=  0.5f*(ycor)*(float)winy + shifty*winside;
1577
1578         left *= pixsize;
1579         right *= pixsize;
1580         bottom *= pixsize;
1581         top *= pixsize;
1582
1583         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
1584
1585         camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
1586         if(camera) {
1587                 float imat[4][4];
1588
1589                 invert_m4_m4(imat, camera->mat);
1590                 mul_m4_m4m4(mat, imat, winmat);
1591         } else copy_m4_m4(mat, winmat);
1592 }
1593
1594 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1595 {
1596         MovieTrackingCamera *camera= &tracking->camera;
1597
1598 #ifdef WITH_LIBMV
1599         double x, y;
1600         float aspy= 1.0f/tracking->camera.pixel_aspect;
1601
1602         /* normalize coords */
1603         x= (co[0]-camera->principal[0]) / camera->focal;
1604         y= (co[1]-camera->principal[1] * aspy) / camera->focal;
1605
1606         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1607                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1608
1609         /* result is in image coords already */
1610         nco[0]= x;
1611         nco[1]= y;
1612 #else
1613         (void)camera;
1614         (void)co;
1615         (void)nco;
1616 #endif
1617 }
1618
1619 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1620 {
1621         MovieTrackingCamera *camera= &tracking->camera;
1622
1623 #ifdef WITH_LIBMV
1624         double x= co[0], y= co[1];
1625         float aspy= 1.0f/tracking->camera.pixel_aspect;
1626
1627         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1628                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1629
1630         nco[0]= x * camera->focal + camera->principal[0];
1631         nco[1]= y * camera->focal + camera->principal[1] * aspy;
1632 #else
1633         (void)camera;
1634         (void)co;
1635         (void)nco;
1636 #endif
1637 }
1638
1639 #ifdef WITH_LIBMV
1640 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
1641 {
1642         int i, prev;
1643         int count= 0;
1644         bGPDspoint *points= stroke->points;
1645
1646         prev= stroke->totpoints-1;
1647
1648         for(i= 0; i<stroke->totpoints; i++) {
1649                 if((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) {
1650                         float fac= (y-points[i].y)/(points[prev].y-points[i].y);
1651
1652                         if (points[i].x+fac*(points[prev].x-points[i].x)<x)
1653                                 count++;
1654                 }
1655
1656                 prev= i;
1657         }
1658
1659         return count%2;
1660 }
1661
1662 static int point_in_layer(bGPDlayer *layer, float x, float y)
1663 {
1664         bGPDframe *frame= layer->frames.first;
1665
1666         while(frame) {
1667                 bGPDstroke *stroke= frame->strokes.first;
1668                 while(stroke) {
1669                         if(point_in_stroke(stroke, x, y))
1670                                 return 1;
1671
1672                         stroke= stroke->next;
1673                 }
1674                 frame= frame->next;
1675         }
1676
1677         return 0;
1678 }
1679
1680 static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Features *features,
1681                         int framenr, int width, int height, bGPDlayer *layer, int place_outside_layer)
1682 {
1683         int a;
1684
1685         a= libmv_countFeatures(features);
1686         while(a--) {
1687                 MovieTrackingTrack *track;
1688                 double x, y, size, score;
1689                 int ok= 1;
1690                 float xu, yu;
1691
1692                 libmv_getFeature(features, a, &x, &y, &score, &size);
1693
1694                 xu= x/width;
1695                 yu= y/height;
1696
1697                 if(layer)
1698                         ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
1699
1700                 if(ok) {
1701                         track= BKE_tracking_add_track(tracking, xu, yu, framenr, width, height);
1702                         track->flag|= SELECT;
1703                         track->pat_flag|= SELECT;
1704                         track->search_flag|= SELECT;
1705                 }
1706         }
1707 }
1708 #endif
1709
1710 void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
1711                         int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
1712                         int place_outside_layer)
1713 {
1714 #ifdef WITH_LIBMV
1715         struct libmv_Features *features;
1716         unsigned char *pixels= get_ucharbuf(ibuf);
1717
1718         features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance);
1719
1720         MEM_freeN(pixels);
1721
1722         retrieve_libmv_features(tracking, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer);
1723
1724         libmv_destroyFeatures(features);
1725 #else
1726         (void)tracking;
1727         (void)ibuf;
1728         (void)framenr;
1729         (void)margin;
1730         (void)min_trackness;
1731         (void)min_distance;
1732         (void)layer;
1733         (void)place_outside_layer;
1734 #endif
1735 }
1736
1737 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr)
1738 {
1739         MovieTrackingTrack *track= tracking->tracks.first;
1740         int cur= 1;
1741
1742         while(track) {
1743                 if(track->flag&TRACK_HAS_BUNDLE) {
1744                         if(cur==tracknr)
1745                                 return track;
1746
1747                         cur++;
1748                 }
1749
1750                 track= track->next;
1751         }
1752
1753         return NULL;
1754 }
1755
1756 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
1757 {
1758         int ok= 0;
1759         float min[2], max[2];
1760         MovieTrackingTrack *track;
1761
1762         INIT_MINMAX2(min, max);
1763
1764         track= tracking->tracks.first;
1765         while(track) {
1766                 if(track->flag&TRACK_USE_2D_STAB) {
1767                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
1768
1769                         DO_MINMAX2(marker->pos, min, max);
1770
1771                         ok= 1;
1772                 }
1773
1774                 track= track->next;
1775         }
1776
1777         median[0]= (max[0]+min[0])/2.0f;
1778         median[1]= (max[1]+min[1])/2.0f;
1779
1780         return ok;
1781 }
1782
1783 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
1784                         float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
1785 {
1786         MovieTrackingStabilization *stab= &tracking->stabilization;
1787
1788         *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f;
1789         *angle= 0.0f;
1790
1791         loc[0]= (firstmedian[0]-median[0])*width*(*scale);
1792         loc[1]= (firstmedian[1]-median[1])*height*(*scale);
1793
1794         mul_v2_fl(loc, stab->locinf);
1795
1796         if(stab->rot_track && stab->rotinf) {
1797                 MovieTrackingMarker *marker;
1798                 float a[2], b[2];
1799                 float x0= (float)width/2.0f, y0= (float)height/2.0f;
1800                 float x= median[0]*width, y= median[1]*height;
1801
1802                 marker= BKE_tracking_get_marker(stab->rot_track, 1);
1803                 sub_v2_v2v2(a, marker->pos, firstmedian);
1804                 a[0]*= width;
1805                 a[1]*= height;
1806
1807                 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
1808                 sub_v2_v2v2(b, marker->pos, median);
1809                 b[0]*= width;
1810                 b[1]*= height;
1811
1812                 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
1813                 *angle*= stab->rotinf;
1814
1815                 /* convert to rotation around image center */
1816                 loc[0]-= (x0 + (x-x0)*cosf(*angle)-(y-y0)*sinf(*angle) - x)*(*scale);
1817                 loc[1]-= (y0 + (x-x0)*sinf(*angle)+(y-y0)*cosf(*angle) - y)*(*scale);
1818         }
1819 }
1820
1821 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
1822 {
1823         float firstmedian[2];
1824         MovieTrackingStabilization *stab= &tracking->stabilization;
1825
1826         if(stab->ok)
1827                 return stab->scale;
1828
1829         if(stabilization_median_point(tracking, 1, firstmedian)) {
1830                 int sfra= INT_MAX, efra= INT_MIN, cfra;
1831                 float delta[2]= {0.0f, 0.0f}, scalex= 1.0f, scaley= 1.0f;
1832                 MovieTrackingTrack *track;
1833
1834                 stab->scale= 1.0f;
1835
1836                 track= tracking->tracks.first;
1837                 while(track) {
1838                         if(track->flag&TRACK_USE_2D_STAB || track==stab->rot_track) {
1839                                 if(track->markersnr) {
1840                                         sfra= MIN2(sfra, track->markers[0].framenr);
1841                                         efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
1842                                 }
1843                         }
1844
1845                         track= track->next;
1846                 }
1847
1848                 for(cfra=sfra; cfra<=efra; cfra++) {
1849                         float median[2], near[2];
1850                         float loc[2], scale, angle;
1851
1852                         stabilization_median_point(tracking, cfra, median);
1853
1854                         calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
1855                                                 loc, &scale, &angle);
1856
1857                         if(angle==0.0f) {
1858                                 loc[0]= fabsf(loc[0]);
1859                                 loc[1]= fabsf(loc[1]);
1860
1861                                 delta[0]= MAX2(delta[0], loc[0]);
1862                                 delta[1]= MAX2(delta[1], loc[1]);
1863
1864                                 near[0]= MIN2(median[0], 1.0f-median[0]);
1865                                 near[1]= MIN2(median[1], 1.0f-median[1]);
1866                                 near[0]= MAX2(near[0], 0.05f);
1867                                 near[1]= MAX2(near[1], 0.05f);
1868
1869                                 scalex= 1.0f+delta[0]/(near[0]*width);
1870                                 scaley= 1.0f+delta[1]/(near[1]*height);
1871                         } else {
1872                                 int i;
1873                                 float mat[4][4];
1874                                 float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
1875
1876                                 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
1877
1878                                 for(i= 0; i<4; i++) {
1879                                         int j;
1880                                         float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f};
1881
1882                                         copy_v3_v3(a, points[i]);
1883                                         copy_v3_v3(b, points[(i+1)%4]);
1884
1885                                         mul_m4_v3(mat, a);
1886                                         mul_m4_v3(mat, b);
1887
1888                                         for(j= 0; j<4; j++) {
1889                                                 float point[3]= {points[j][0], points[j][1], 0.0f};
1890                                                 float v1[3], v2[3];
1891
1892                                                 sub_v3_v3v3(v1, b, a);
1893                                                 sub_v3_v3v3(v2, point, a);
1894
1895                                                 if(cross_v2v2(v1, v2) >= 0.0f) {
1896                                                         float dist= dist_to_line_v2(point, a, b);
1897                                                         if(i%2==0) {
1898                                                                 scalex= MAX2(scalex, (width+2*dist)/width);
1899                                                         } else {
1900                                                                 scaley= MAX2(scaley, (height+2*dist)/height);
1901                                                         }
1902                                                 }
1903                                         }
1904                                 }
1905                         }
1906                 }
1907
1908                 stab->scale= MAX2(scalex, scaley);
1909
1910                 if(stab->maxscale>0.0f)
1911                         stab->scale= MIN2(stab->scale, stab->maxscale);
1912         } else {
1913                 stab->scale= 1.0f;
1914         }
1915
1916         stab->ok= 1;
1917
1918         return stab->scale;
1919 }
1920
1921 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
1922 {
1923         int flags;
1924
1925         if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
1926                 IMB_freeImBuf(cacheibuf);
1927                 cacheibuf= NULL;
1928         }
1929
1930         flags= IB_rect;
1931
1932         if(srcibuf->rect_float)
1933                 flags|= IB_rectfloat;
1934
1935         if(cacheibuf) {
1936                 if(fill) {
1937                         float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
1938                         IMB_rectfill(cacheibuf, col);
1939                 }
1940         }
1941         else {
1942                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
1943                 cacheibuf->profile= srcibuf->profile;
1944         }
1945
1946         return cacheibuf;
1947 }
1948
1949 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
1950 {
1951         float firstmedian[2], median[2];
1952         MovieTrackingStabilization *stab= &tracking->stabilization;
1953
1954         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1955                 zero_v2(loc);
1956                 *scale= 1.0f;
1957                 *angle= 0.0f;
1958
1959                 return;
1960         }
1961
1962         if(stabilization_median_point(tracking, 1, firstmedian)) {
1963                 stabilization_median_point(tracking, framenr, median);
1964
1965                 if((stab->flag&TRACKING_AUTOSCALE)==0)
1966                         stab->scale= 1.0f;
1967
1968                 if(!stab->ok) {
1969                         if(stab->flag&TRACKING_AUTOSCALE)
1970                                 stabilization_auto_scale_factor(tracking, width, height);
1971
1972                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1973
1974                         stab->ok= 1;
1975                 } else {
1976                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1977                 }
1978         } else {
1979                 zero_v2(loc);
1980                 *scale= 1.0f;
1981                 *angle= 0.0f;
1982         }
1983 }
1984
1985 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
1986 {
1987         float tloc[2], tscale, tangle;
1988         MovieTrackingStabilization *stab= &tracking->stabilization;
1989         ImBuf *tmpibuf;
1990         float width= ibuf->x, height= ibuf->y;
1991
1992         if(loc)         copy_v2_v2(tloc, loc);
1993         if(scale)       tscale= *scale;
1994
1995         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1996                 if(loc)         zero_v2(loc);
1997                 if(scale)       *scale= 1.0f;
1998
1999                 return ibuf;
2000         }
2001
2002         BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
2003
2004         tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
2005
2006         /* scale would be handled by matrix transformation when angle is non-zero */
2007         if(tscale!=1.0f && tangle==0.0f) {
2008                 ImBuf *scaleibuf;
2009
2010                 stabilization_auto_scale_factor(tracking, width, height);
2011
2012                 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
2013                 stab->scaleibuf= scaleibuf;
2014
2015                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
2016                 IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale);
2017
2018                 ibuf= scaleibuf;
2019         }
2020
2021         if(tangle==0.0f) {
2022                 /* if angle is zero, then it's much faster to use rect copy
2023                    but could be issues with subpixel precisions */
2024                 IMB_rectcpy(tmpibuf, ibuf, tloc[0]-(tscale-1.0f)*width/2.0f, tloc[1]-(tscale-1.0f)*height/2.0f, 0, 0, ibuf->x, ibuf->y);
2025         } else {
2026                 float mat[4][4];
2027                 int i, j;
2028
2029                 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
2030                 invert_m4(mat);
2031
2032                 for(j=0; j<tmpibuf->y; j++) {
2033                         for(i=0; i<tmpibuf->x;i++) {
2034                                 float vec[3]= {i, j, 0};
2035
2036                                 mul_v3_m4v3(vec, mat, vec);
2037
2038                                 /* TODO: add selector for interpolation method */
2039                                 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
2040                         }
2041                 }
2042         }
2043
2044         tmpibuf->userflags|= IB_MIPMAP_INVALID;
2045
2046         if(tmpibuf->rect_float)
2047                 tmpibuf->userflags|= IB_RECT_INVALID;
2048
2049         if(loc)         copy_v2_v2(loc, tloc);
2050         if(scale)       *scale= tscale;
2051         if(angle)       *angle= tangle;
2052
2053         return tmpibuf;
2054 }
2055
2056 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
2057 {
2058         float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
2059         float svec[3]= {scale, scale, scale};
2060
2061         unit_m4(rmat);
2062         unit_m4(lmat);
2063         unit_m4(smat);
2064         unit_m4(cmat);
2065
2066         /* image center as rotation center */
2067         cmat[3][0]= (float)width/2.0f;
2068         cmat[3][1]= (float)height/2.0f;
2069         invert_m4_m4(icmat, cmat);
2070
2071         size_to_mat4(smat, svec);               /* scale matrix */
2072         add_v2_v2(lmat[3], loc);                /* tranlation matrix */
2073         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
2074
2075         /* compose transformation matrix */
2076         mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
2077 }
2078
2079 MovieDistortion *BKE_tracking_distortion_create(void)
2080 {
2081         MovieDistortion *distortion;
2082
2083         distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2084
2085         return distortion;
2086 }
2087
2088 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
2089 {
2090         MovieDistortion *new_distortion;
2091
2092         new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2093
2094 #ifdef WITH_LIBMV
2095         new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics);
2096 #else
2097         (void)distortion;
2098 #endif
2099
2100         return new_distortion;
2101 }
2102
2103 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
2104 {
2105         MovieTrackingCamera *camera= &tracking->camera;
2106         float aspy= 1.0f/tracking->camera.pixel_aspect;
2107
2108 #ifdef WITH_LIBMV
2109         if(!distortion->intrinsics) {
2110                 distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal,
2111                                 camera->principal[0], camera->principal[1] * aspy,
2112                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2113         } else {
2114                 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
2115                                 camera->principal[0], camera->principal[1] * aspy,
2116                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2117         }
2118 #else
2119         (void)distortion;
2120         (void)width;
2121         (void)height;
2122         (void)camera;
2123         (void)aspy;
2124 #endif
2125 }
2126
2127 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
2128                         ImBuf *ibuf, int width, int height, float overscan, int undistort)
2129 {
2130         ImBuf *resibuf;
2131
2132         BKE_tracking_distortion_update(distortion, tracking, width, height);
2133
2134         resibuf= IMB_dupImBuf(ibuf);
2135
2136         if(ibuf->rect_float) {
2137 #ifdef WITH_LIBMV
2138                 if(undistort) {
2139                         libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
2140                                                 ibuf->rect_float, resibuf->rect_float,
2141                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2142                 } else {
2143                         libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
2144                                                 ibuf->rect_float, resibuf->rect_float,
2145                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2146                 }
2147 #endif
2148
2149                 ibuf->userflags|= IB_RECT_INVALID;
2150         } else {
2151 #ifdef WITH_LIBMV
2152                 if(undistort) {
2153                                 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
2154                                                         (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2155                                                         ibuf->x, ibuf->y, overscan, ibuf->channels);
2156                 } else {
2157                         libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
2158                                                 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2159                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2160                 }
2161 #endif
2162         }
2163
2164 #ifndef WITH_LIBMV
2165         (void)overscan;
2166         (void)undistort;
2167 #endif
2168
2169         return resibuf;
2170 }
2171
2172 void BKE_tracking_distortion_destroy(MovieDistortion *distortion)
2173 {
2174 #ifdef WITH_LIBMV
2175         libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
2176 #endif
2177
2178         MEM_freeN(distortion);
2179 }
2180
2181 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2182 {
2183         MovieTrackingCamera *camera= &tracking->camera;
2184
2185         if(camera->intrinsics == NULL)
2186                 camera->intrinsics= BKE_tracking_distortion_create();
2187
2188         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1);
2189 }
2190
2191 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2192 {
2193         MovieTrackingCamera *camera= &tracking->camera;
2194
2195         if(camera->intrinsics == NULL)
2196                 camera->intrinsics= BKE_tracking_distortion_create();
2197
2198         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0);
2199 }
2200
2201 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
2202 void BKE_tracking_select_track(MovieTracking *tracking, MovieTrackingTrack *track, int area, int extend)
2203 {
2204         if(extend) {
2205                 BKE_tracking_track_flag(track, area, SELECT, 0);
2206         } else {
2207                 MovieTrackingTrack *cur= tracking->tracks.first;
2208
2209                 while(cur) {
2210                         if(cur==track) {
2211                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2212                                 BKE_tracking_track_flag(cur, area, SELECT, 0);
2213                         }
2214                         else {
2215                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2216                         }
2217
2218                         cur= cur->next;
2219                 }
2220         }
2221 }
2222
2223 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
2224 {
2225         BKE_tracking_track_flag(track, area, SELECT, 1);
2226 }