style cleanup: follow style guide for/with/if spacing
[blender-staging.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 #include "BLI_string.h"
51 #include "BLI_threads.h"
52
53 #include "BKE_global.h"
54 #include "BKE_tracking.h"
55 #include "BKE_movieclip.h"
56 #include "BKE_object.h"
57 #include "BKE_scene.h"
58 #include "BKE_main.h"   // XXX: ...
59
60 #include "IMB_imbuf_types.h"
61 #include "IMB_imbuf.h"
62
63 #ifdef WITH_LIBMV
64 #  include "libmv-capi.h"
65 #else
66 struct libmv_Features;
67 #endif
68
69 typedef struct MovieDistortion {
70         struct libmv_CameraIntrinsics *intrinsics;
71 } MovieDistortion;
72
73 static struct {
74         ListBase tracks;
75 } tracking_clipboard;
76
77 /*********************** common functions *************************/
78
79 void BKE_tracking_init_settings(MovieTracking *tracking)
80 {
81         tracking->camera.sensor_width= 35.0f;
82         tracking->camera.pixel_aspect= 1.0f;
83         tracking->camera.units= CAMERA_UNITS_MM;
84
85         tracking->settings.default_tracker= TRACKER_HYBRID;
86         tracking->settings.default_minimum_correlation= 0.75;
87         tracking->settings.default_pattern_size= 11;
88         tracking->settings.default_search_size= 51;
89         tracking->settings.default_pyramid_levels= 2;
90         tracking->settings.keyframe1= 1;
91         tracking->settings.keyframe2= 30;
92         tracking->settings.dist= 1;
93         tracking->settings.object_distance= 1;
94
95         tracking->stabilization.scaleinf= 1.0f;
96         tracking->stabilization.locinf= 1.0f;
97         tracking->stabilization.rotinf= 1.0f;
98         tracking->stabilization.maxscale= 2.0f;
99
100         BKE_tracking_new_object(tracking, "Camera");
101 }
102
103 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
104 {
105         int a;
106         float pat_min[2];
107         float pat_max[2];
108         float max_pyramid_level_factor = 1.0;
109
110         if (track->tracker == TRACKER_KLT) {
111                 max_pyramid_level_factor= 1 << (track->pyramid_levels - 1);
112         }
113
114         /* sort */
115         for (a= 0; a<2; a++) {
116                 if (track->pat_min[a]>track->pat_max[a])
117                         SWAP(float, track->pat_min[a], track->pat_max[a]);
118
119                 if (track->search_min[a]>track->search_max[a])
120                         SWAP(float, track->search_min[a], track->search_max[a]);
121         }
122
123         /* compute the effective pattern size, which differs from the fine resolution
124          * pattern size for the pyramid KLT tracker */
125         for (a= 0; a<2; a++) {
126                 pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
127                 pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
128         }
129
130         if (event==CLAMP_PAT_DIM) {
131                 for (a= 0; a<2; a++) {
132                         /* search shouldn't be resized smaller than pattern */
133                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
134                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
135                 }
136         }
137         else if (event==CLAMP_PAT_POS) {
138                 float dim[2];
139                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
140
141                 for (a= 0; a<2; a++) {
142                         /* pattern shouldn't be moved outside of search */
143                         if (pat_min[a] < track->search_min[a]) {
144                                 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
145                                 track->pat_max[a]= track->pat_min[a] + dim[a];
146                         }
147                         if (track->pat_max[a] > track->search_max[a]) {
148                                 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
149                                 track->pat_min[a]= track->pat_max[a] - dim[a];
150                         }
151                 }
152         }
153         else if (event==CLAMP_SEARCH_DIM) {
154                 for (a= 0; a<2; a++) {
155                         /* search shouldn't be resized smaller than pattern */
156                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
157                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
158                 }
159         }
160         else if (event==CLAMP_SEARCH_POS) {
161                 float dim[2];
162                 sub_v2_v2v2(dim, track->search_max, track->search_min);
163
164                 for (a= 0; a<2; a++) {
165                         /* search shouldn't be moved inside pattern */
166                         if (track->search_min[a] > pat_min[a]) {
167                                 track->search_min[a]= pat_min[a];
168                                 track->search_max[a]= track->search_min[a]+dim[a];
169                         }
170                         if (track->search_max[a] < pat_max[a]) {
171                                 track->search_max[a]= pat_max[a];
172                                 track->search_min[a]= track->search_max[a]-dim[a];
173                         }
174                 }
175         }
176         else if (event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT)) {
177                 float dim[2];
178                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
179                 {
180                         float search_ratio= 2.3f * max_pyramid_level_factor;
181
182                         /* resize the search area to something sensible based
183                          * on the number of pyramid levels */
184                         for (a= 0; a<2; a++) {
185                                 track->search_min[a]= search_ratio * track->pat_min[a];
186                                 track->search_max[a]= search_ratio * track->pat_max[a];
187                         }
188                 }
189         }
190
191         /* marker's center should be in center of pattern */
192         if (event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
193                 float dim[2];
194                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
195
196                 for (a= 0; a<2; a++) {
197                         track->pat_min[a]= -dim[a]/2.0f;
198                         track->pat_max[a]= dim[a]/2.0f;
199                 }
200         }
201 }
202
203 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
204 {
205         if (area==TRACK_AREA_NONE)
206                 return;
207
208         if (clear) {
209                 if (area&TRACK_AREA_POINT)      track->flag&= ~flag;
210                 if (area&TRACK_AREA_PAT)                track->pat_flag&= ~flag;
211                 if (area&TRACK_AREA_SEARCH)     track->search_flag&= ~flag;
212         }
213         else {
214                 if (area&TRACK_AREA_POINT)      track->flag|= flag;
215                 if (area&TRACK_AREA_PAT)                track->pat_flag|= flag;
216                 if (area&TRACK_AREA_SEARCH)     track->search_flag|= flag;
217         }
218 }
219
220 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
221                         int framenr, int width, int height)
222 {
223         MovieTrackingTrack *track;
224         MovieTrackingMarker marker;
225         MovieTrackingSettings *settings= &tracking->settings;
226
227         float half_pattern= (float)settings->default_pattern_size/2.0f;
228         float half_search= (float)settings->default_search_size/2.0f;
229         float pat[2], search[2];
230
231         pat[0]= half_pattern/(float)width;
232         pat[1]= half_pattern/(float)height;
233
234         search[0]= half_search/(float)width;
235         search[1]= half_search/(float)height;
236
237         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
238         strcpy(track->name, "Track");
239
240         track->tracker= settings->default_tracker;
241         track->pyramid_levels= settings->default_pyramid_levels;
242         track->minimum_correlation= settings->default_minimum_correlation;
243         track->margin= settings->default_margin;
244         track->pattern_match= settings->default_pattern_match;
245         track->frames_limit= settings->default_frames_limit;
246         track->flag= settings->default_flag;
247
248         memset(&marker, 0, sizeof(marker));
249         marker.pos[0]= x;
250         marker.pos[1]= y;
251         marker.framenr= framenr;
252
253         copy_v2_v2(track->pat_max, pat);
254         negate_v2_v2(track->pat_min, pat);
255
256         copy_v2_v2(track->search_max, search);
257         negate_v2_v2(track->search_min, search);
258
259         BKE_tracking_insert_marker(track, &marker);
260
261         if (track->tracker == TRACKER_KLT)
262                 BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
263
264         BLI_addtail(tracksbase, track);
265         BKE_track_unique_name(tracksbase, track);
266
267         return track;
268 }
269
270 MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
271 {
272         MovieTrackingMarker *old_marker= NULL;
273
274         if (track->markersnr)
275                 old_marker= BKE_tracking_exact_marker(track, marker->framenr);
276
277         if (old_marker) {
278                 *old_marker= *marker;
279
280                 return old_marker;
281         }
282         else {
283                 int a= track->markersnr;
284
285                 while (a--) {
286                         if (track->markers[a].framenr<marker->framenr)
287                                 break;
288                 }
289
290                 track->markersnr++;
291
292                 if (track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
293                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
294
295                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
296                 track->markers[a+1]= *marker;
297
298                 track->last_marker= a+1;
299
300                 return &track->markers[a+1];
301         }
302 }
303
304 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
305 {
306         int a= 0;
307
308         while (a<track->markersnr) {
309                 if (track->markers[a].framenr==framenr) {
310                         if (track->markersnr>1) {
311                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
312                                 track->markersnr--;
313                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
314                         }
315                         else {
316                                 MEM_freeN(track->markers);
317                                 track->markers= NULL;
318                                 track->markersnr= 0;
319                         }
320
321                         break;
322                 }
323
324                 a++;
325         }
326 }
327
328 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
329 {
330         int a= track->markersnr-1;
331
332         if (!track->markersnr)
333                 return NULL;
334
335         /* approximate pre-first framenr marker with first marker */
336         if (framenr<track->markers[0].framenr)
337                 return &track->markers[0];
338
339         if (track->last_marker<track->markersnr)
340                 a= track->last_marker;
341
342         if (track->markers[a].framenr<=framenr) {
343                 while (a<track->markersnr && track->markers[a].framenr<=framenr) {
344                         if (track->markers[a].framenr==framenr) {
345                                 track->last_marker= a;
346                                 return &track->markers[a];
347                         }
348                         a++;
349                 }
350
351                 /* if there's no marker for exact position, use nearest marker from left side */
352                 return &track->markers[a-1];
353         }
354         else {
355                 while (a>=0 && track->markers[a].framenr>=framenr) {
356                         if (track->markers[a].framenr==framenr) {
357                                 track->last_marker= a;
358                                 return &track->markers[a];
359                         }
360
361                         a--;
362                 }
363
364                 /* if there's no marker for exact position, use nearest marker from left side */
365                 return &track->markers[a];
366         }
367
368         return NULL;
369 }
370
371 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
372 {
373         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
374
375         if (marker->framenr!=framenr) {
376                 MovieTrackingMarker marker_new;
377
378                 marker_new= *marker;
379                 marker_new.framenr= framenr;
380
381                 BKE_tracking_insert_marker(track, &marker_new);
382                 marker= BKE_tracking_get_marker(track, framenr);
383         }
384
385         return marker;
386 }
387
388 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
389 {
390         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
391
392         if (marker->framenr!=framenr)
393                 return NULL;
394
395         return marker;
396 }
397
398 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
399 {
400         return BKE_tracking_exact_marker(track, framenr) != 0;
401 }
402
403 int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr)
404 {
405         MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr);
406
407         return marker && (marker->flag & MARKER_DISABLED) == 0;
408 }
409
410 void BKE_tracking_free_track(MovieTrackingTrack *track)
411 {
412         if (track->markers) MEM_freeN(track->markers);
413 }
414
415 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
416 {
417         MovieTrackingMarker marker_new;
418
419         marker_new= *ref_marker;
420         marker_new.flag&= ~MARKER_TRACKED;
421         marker_new.flag|= MARKER_DISABLED;
422
423         if (before) marker_new.framenr--;
424         else marker_new.framenr++;
425
426         if (!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
427                 BKE_tracking_insert_marker(track, &marker_new);
428 }
429
430 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
431 {
432         int a;
433
434         if (action==TRACK_CLEAR_REMAINED) {
435                 a= 1;
436                 while (a<track->markersnr) {
437                         if (track->markers[a].framenr>ref_frame) {
438                                 track->markersnr= a;
439                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
440
441                                 break;
442                         }
443
444                         a++;
445                 }
446
447                 if (track->markersnr)
448                         put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1);
449         }
450         else if (action==TRACK_CLEAR_UPTO) {
451                 a= track->markersnr-1;
452                 while (a>=0) {
453                         if (track->markers[a].framenr<=ref_frame) {
454                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
455
456                                 track->markersnr= track->markersnr-a;
457                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
458
459                                 break;
460                         }
461
462                         a--;
463                 }
464
465                 if (track->markersnr)
466                         put_disabled_marker(track, &track->markers[0], 1, 1);
467         }
468         else if (action==TRACK_CLEAR_ALL) {
469                 MovieTrackingMarker *marker, marker_new;
470
471                 marker= BKE_tracking_get_marker(track, ref_frame);
472                 marker_new= *marker;
473
474                 MEM_freeN(track->markers);
475                 track->markers= NULL;
476                 track->markersnr= 0;
477
478                 BKE_tracking_insert_marker(track, &marker_new);
479
480                 put_disabled_marker(track, &marker_new, 1, 1);
481                 put_disabled_marker(track, &marker_new, 0, 1);
482         }
483 }
484
485 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
486 {
487         int i= 0, a= 0, b= 0;
488         MovieTrackingMarker *markers;
489
490         markers= MEM_callocN((dst_track->markersnr+src_track->markersnr)*sizeof(MovieTrackingMarker), "tmp tracking joined tracks");
491
492         while (a < src_track->markersnr || b < dst_track->markersnr) {
493                 if (b>=dst_track->markersnr) {
494                         markers[i]= src_track->markers[a++];
495                 }
496                 else if (a>=src_track->markersnr) {
497                         markers[i]= dst_track->markers[b++];
498                 }
499                 else if (src_track->markers[a].framenr<dst_track->markers[b].framenr) {
500                         markers[i]= src_track->markers[a++];
501                 }
502                 else if (src_track->markers[a].framenr>dst_track->markers[b].framenr) {
503                         markers[i]= dst_track->markers[b++];
504                 }
505                 else {
506                         if ((src_track->markers[a].flag&MARKER_DISABLED)==0) {
507                                 if ((dst_track->markers[b].flag&MARKER_DISABLED)==0) {
508                                         /* both tracks are enabled on this frame, so find the whole segment
509                                          * on which tracks are intersecting and blend tracks using linear
510                                          * interpolation to prevent jumps */
511
512                                         MovieTrackingMarker *marker_a, *marker_b;
513                                         int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
514                                         int j, inverse = 0;
515
516                                         inverse = (b == 0) ||
517                                                   (dst_track->markers[b-1].flag & MARKER_DISABLED) ||
518                                                   (dst_track->markers[b-1].framenr != frame - 1);
519
520                                         while (a < src_track->markersnr && b < dst_track->markersnr) {
521                                                 marker_a = &src_track->markers[a];
522                                                 marker_b = &dst_track->markers[b];
523
524                                                 if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED)
525                                                         break;
526
527                                                 if (marker_a->framenr != frame || marker_b->framenr != frame)
528                                                         break;
529
530                                                 frame++;
531                                                 len++;
532                                                 a++;
533                                                 b++;
534                                         }
535
536                                         a = start_a;
537                                         b = start_b;
538
539                                         for (j = 0; j < len; j++) {
540                                                 float fac = 0.5f;
541
542                                                 if (len > 1)
543                                                         fac = 1.0f / (len - 1) * j;
544
545                                                 if (inverse)
546                                                         fac = 1.0f - fac;
547
548                                                 marker_a = &src_track->markers[a];
549                                                 marker_b = &dst_track->markers[b];
550
551                                                 markers[i]= dst_track->markers[b];
552                                                 interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac);
553                                                 a++;
554                                                 b++;
555                                                 i++;
556                                         }
557
558                                         /* this values will be incremented at the end of the loop cycle */
559                                         a--; b--; i--;
560                                 }
561                                 else markers[i]= src_track->markers[a];
562                         }
563                         else markers[i]= dst_track->markers[b];
564
565                         a++;
566                         b++;
567                 }
568
569                 i++;
570         }
571
572         MEM_freeN(dst_track->markers);
573
574         dst_track->markers= MEM_callocN(i*sizeof(MovieTrackingMarker), "tracking joined tracks");
575         memcpy(dst_track->markers, markers, i*sizeof(MovieTrackingMarker));
576
577         dst_track->markersnr= i;
578
579         MEM_freeN(markers);
580 }
581
582 static void tracking_tracks_free(ListBase *tracks)
583 {
584         MovieTrackingTrack *track;
585
586         for (track= tracks->first; track; track= track->next) {
587                 BKE_tracking_free_track(track);
588         }
589
590         BLI_freelistN(tracks);
591 }
592
593 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
594 {
595         if (reconstruction->cameras)
596                 MEM_freeN(reconstruction->cameras);
597 }
598
599 static void tracking_object_free(MovieTrackingObject *object)
600 {
601         tracking_tracks_free(&object->tracks);
602         tracking_reconstruction_free(&object->reconstruction);
603 }
604
605 static void tracking_objects_free(ListBase *objects)
606 {
607         MovieTrackingObject *object;
608
609         for (object= objects->first; object; object= object->next)
610                 tracking_object_free(object);
611
612         BLI_freelistN(objects);
613 }
614
615 void BKE_tracking_free(MovieTracking *tracking)
616 {
617         tracking_tracks_free(&tracking->tracks);
618         tracking_reconstruction_free(&tracking->reconstruction);
619         tracking_objects_free(&tracking->objects);
620
621         if (tracking->stabilization.scaleibuf)
622                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
623
624         if (tracking->camera.intrinsics)
625                 BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
626 }
627
628 static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track)
629 {
630         MovieTrackingTrack *new_track;
631
632         new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track");
633
634         *new_track= *track;
635         new_track->next = new_track->prev = NULL;
636
637         new_track->markers = MEM_dupallocN(new_track->markers);
638
639         return new_track;
640 }
641
642 /*********************** clipboard *************************/
643
644 void BKE_tracking_free_clipboard(void)
645 {
646         MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
647
648         while (track) {
649                 next_track = track->next;
650
651                 BKE_tracking_free_track(track);
652                 MEM_freeN(track);
653
654                 track = next_track;
655         }
656 }
657
658 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
659 {
660         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
661         MovieTrackingTrack *track = tracksbase->first;
662
663         while (track) {
664                 if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) {
665                         MovieTrackingTrack *new_track = duplicate_track(track);
666
667                         BLI_addtail(&tracking_clipboard.tracks, new_track);
668                 }
669
670                 track = track->next;
671         }
672 }
673
674 int BKE_tracking_clipboard_has_tracks(void)
675 {
676         return tracking_clipboard.tracks.first != NULL;
677 }
678
679 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
680 {
681         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
682         MovieTrackingTrack *track = tracking_clipboard.tracks.first;
683
684         while (track) {
685                 MovieTrackingTrack *new_track = duplicate_track(track);
686
687                 BLI_addtail(tracksbase, new_track);
688                 BKE_track_unique_name(tracksbase, new_track);
689
690                 track = track->next;
691         }
692 }
693
694 /*********************** tracks map *************************/
695
696 typedef struct TracksMap {
697         char object_name[MAX_NAME];
698         int is_camera;
699
700         int num_tracks;
701         int customdata_size;
702
703         char *customdata;
704         MovieTrackingTrack *tracks;
705
706         GHash *hash;
707
708         int ptr;
709 } TracksMap;
710
711 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
712 {
713         TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap");
714
715         BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
716         map->is_camera= is_camera;
717
718         map->num_tracks= num_tracks;
719         map->customdata_size= customdata_size;
720
721         map->tracks= MEM_callocN(sizeof(MovieTrackingTrack)*num_tracks, "TrackingsMap tracks");
722
723         if (customdata_size)
724                 map->customdata= MEM_callocN(customdata_size*num_tracks, "TracksMap customdata");
725
726         map->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "TracksMap hash");
727
728         return map;
729 }
730
731 static int tracks_map_size(TracksMap *map)
732 {
733         return map->num_tracks;
734 }
735
736 static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
737 {
738         *track= &map->tracks[index];
739
740         if (map->customdata)
741                 *customdata= &map->customdata[index*map->customdata_size];
742 }
743
744 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
745 {
746         MovieTrackingTrack new_track= *track;
747
748         new_track.markers= MEM_dupallocN(new_track.markers);
749
750         map->tracks[map->ptr]= new_track;
751
752         if (customdata)
753                 memcpy(&map->customdata[map->ptr*map->customdata_size], customdata, map->customdata_size);
754
755         BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
756
757         map->ptr++;
758 }
759
760 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
761 {
762         MovieTrackingTrack *track;
763         MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
764         MovieTrackingTrack *rot_track= tracking->stabilization.rot_track;
765         ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
766         ListBase *old_tracks;
767         int a;
768
769         if (map->is_camera) {
770                 old_tracks= &tracking->tracks;
771         }
772         else {
773                 MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name);
774
775                 if (!object) {
776                         /* object was deleted by user, create new one */
777                         object= BKE_tracking_new_object(tracking, map->object_name);
778                 }
779
780                 old_tracks= &object->tracks;
781         }
782
783         /* duplicate currently operating tracks to temporary list.
784          * this is needed to keep names in unique state and it's faster to change names
785          * of currently operating tracks (if needed) */
786         for (a= 0; a<map->num_tracks; a++) {
787                 int replace_sel= 0, replace_rot= 0;
788                 MovieTrackingTrack *new_track, *old;
789
790                 track= &map->tracks[a];
791
792                 /* find original of operating track in list of previously displayed tracks */
793                 old= BLI_ghash_lookup(map->hash, track);
794                 if (old) {
795                         MovieTrackingTrack *cur= old_tracks->first;
796
797                         while (cur) {
798                                 if (cur==old)
799                                         break;
800
801                                 cur= cur->next;
802                         }
803
804                         /* original track was found, re-use flags and remove this track */
805                         if (cur) {
806                                 if (cur==act_track)
807                                         replace_sel= 1;
808                                 if (cur==rot_track)
809                                         replace_rot= 1;
810
811                                 track->flag= cur->flag;
812                                 track->pat_flag= cur->pat_flag;
813                                 track->search_flag= cur->search_flag;
814
815                                 BKE_tracking_free_track(cur);
816                                 BLI_freelinkN(old_tracks, cur);
817                         }
818                 }
819
820                 new_track= duplicate_track(track);
821
822                 BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
823                 BLI_ghash_insert(map->hash, track, new_track);
824
825                 if (replace_sel)                /* update current selection in clip */
826                         tracking->act_track= new_track;
827
828                 if (replace_rot)                /* update track used for rotation stabilization */
829                         tracking->stabilization.rot_track= new_track;
830
831                 BLI_addtail(&tracks, new_track);
832         }
833
834         /* move all tracks, which aren't operating */
835         track= old_tracks->first;
836         while (track) {
837                 MovieTrackingTrack *next= track->next;
838
839                 track->next= track->prev= NULL;
840                 BLI_addtail(&new_tracks, track);
841
842                 track= next;
843         }
844
845         /* now move all tracks which are currently operating and keep their names unique */
846         track= tracks.first;
847         while (track) {
848                 MovieTrackingTrack *next= track->next;
849
850                 BLI_remlink(&tracks, track);
851
852                 track->next= track->prev= NULL;
853                 BLI_addtail(&new_tracks, track);
854
855                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
856
857                 track= next;
858         }
859
860         *old_tracks= new_tracks;
861 }
862
863 static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata))
864 {
865         int i= 0;
866
867         BLI_ghash_free(map->hash, NULL, NULL);
868
869         for (i= 0; i<map->num_tracks; i++) {
870                 if (map->customdata && customdata_free)
871                         customdata_free(&map->customdata[i*map->customdata_size]);
872
873                 BKE_tracking_free_track(&map->tracks[i]);
874         }
875
876         if (map->customdata)
877                 MEM_freeN(map->customdata);
878
879         MEM_freeN(map->tracks);
880         MEM_freeN(map);
881 }
882
883 /*********************** tracking *************************/
884
885 typedef struct TrackContext {
886 #ifdef WITH_LIBMV
887         float keyframed_pos[2];
888
889         /* ** KLT tracker ** */
890         struct libmv_RegionTracker *region_tracker;
891         float *patch;                   /* keyframed patch */
892
893         /* ** SAD tracker ** */
894         int pattern_size;               /* size of pattern */
895         unsigned char *pattern; /* keyframed pattern */
896         unsigned char *warped;  /* warped version of reference */
897 #else
898         int pad;
899 #endif
900 } TrackContext;
901
902 typedef struct MovieTrackingContext {
903         MovieClipUser user;
904         MovieClip *clip;
905         int clip_flag;
906
907         int first_time, frames;
908
909         MovieTrackingSettings settings;
910         TracksMap *tracks_map;
911
912         short backwards, sequence;
913         int sync_frame;
914 } MovieTrackingContext;
915
916 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
917 {
918         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
919         MovieTracking *tracking= &clip->tracking;
920         MovieTrackingSettings *settings= &tracking->settings;
921         ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
922         MovieTrackingTrack *track;
923         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
924         int num_tracks= 0;
925
926         context->settings= *settings;
927         context->backwards= backwards;
928         context->sync_frame= user->framenr;
929         context->first_time= 1;
930         context->sequence= sequence;
931
932         /* count */
933         track= tracksbase->first;
934         while (track) {
935                 if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN))==0) {
936                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
937
938                         if ((marker->flag&MARKER_DISABLED)==0)
939                                 num_tracks++;
940                 }
941
942                 track= track->next;
943         }
944
945         if (num_tracks) {
946                 int width, height;
947
948                 context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
949                                         num_tracks, sizeof(TrackContext));
950
951                 BKE_movieclip_get_size(clip, user, &width, &height);
952
953                 /* create tracking data */
954                 track= tracksbase->first;
955                 while (track) {
956                         if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED))==0) {
957                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
958
959                                 if ((marker->flag&MARKER_DISABLED)==0) {
960                                         TrackContext track_context;
961
962                                         memset(&track_context, 0, sizeof(TrackContext));
963
964 #ifdef WITH_LIBMV
965                                         {
966                                                 float patx, paty;
967                                                 patx= (int)((track->pat_max[0]-track->pat_min[0])*width);
968                                                 paty= (int)((track->pat_max[1]-track->pat_min[1])*height);
969
970                                                 if (ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
971                                                         float search_size_x= (track->search_max[0]-track->search_min[0])*width;
972                                                         float search_size_y= (track->search_max[1]-track->search_min[1])*height;
973                                                         float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
974                                                         float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
975                                                         int wndx= (int)patx/2, wndy= (int)paty/2;
976
977                                                         /* compute the maximum pyramid size */
978                                                         float search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
979                                                                 / MAX2(pattern_size_x, pattern_size_y);
980                                                         float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
981                                                         int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
982
983                                                         /* try to accommodate the user's choice of pyramid level in a way
984                                                          * that doesn't cause the coarsest pyramid pattern to be larger
985                                                          * than the search size */
986                                                         int level= MIN2(track->pyramid_levels, max_pyramid_levels);
987
988                                                         if (track->tracker==TRACKER_KLT)
989                                                                 track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation);
990                                                         else
991                                                                 track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation);
992                                                 }
993                                                 else if (track->tracker==TRACKER_SAD) {
994                                                         track_context.pattern_size= MAX2(patx, paty);
995                                                 }
996                                         }
997 #endif
998
999                                         tracks_map_insert(context->tracks_map, track, &track_context);
1000                                 }
1001                         }
1002
1003                         track= track->next;
1004                 }
1005         }
1006
1007         context->clip= clip;
1008
1009         /* store needed clip flags passing to get_buffer functions
1010          * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
1011          *   only in case Proxy/Timecode flag is set, so store this flag to use
1012          *   timecodes properly but reset render size to SIZE_FULL so correct resolution
1013          *   would be used for images
1014          * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
1015          *   be stored in a different location
1016          * ignore all the rest possible flags for now */
1017         context->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS;
1018
1019         context->user= *user;
1020         context->user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL;
1021         context->user.render_flag= 0;
1022
1023         if (!sequence)
1024                 BLI_begin_threaded_malloc();
1025
1026         return context;
1027 }
1028
1029 static void track_context_free(void *customdata)
1030 {
1031         TrackContext *track_context= (TrackContext *)customdata;
1032
1033 #if WITH_LIBMV
1034         if (track_context->region_tracker)
1035                 libmv_regionTrackerDestroy(track_context->region_tracker);
1036
1037         if (track_context->patch)
1038                 MEM_freeN(track_context->patch);
1039
1040         if (track_context->pattern)
1041                 MEM_freeN(track_context->pattern);
1042
1043         if (track_context->warped)
1044                 MEM_freeN(track_context->warped);
1045 #else
1046                 (void) track_context;
1047 #endif
1048 }
1049
1050 void BKE_tracking_context_free(MovieTrackingContext *context)
1051 {
1052         if (!context->sequence)
1053                 BLI_end_threaded_malloc();
1054
1055         tracks_map_free(context->tracks_map, track_context_free);
1056
1057         MEM_freeN(context);
1058 }
1059
1060 /* zap channels from the imbuf that are disabled by the user. this can lead to
1061  * better tracks sometimes. however, instead of simply zeroing the channels
1062  * out, do a partial grayscale conversion so the display is better. */
1063 void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale)
1064 {
1065         int x, y;
1066         float scale;
1067
1068         if (!disable_red && !disable_green && !disable_blue && !grayscale)
1069                 return;
1070
1071         /* If only some components are selected, it's important to rescale the result
1072          * appropriately so that e.g. if only blue is selected, it's not zeroed out. */
1073         scale = (disable_red   ? 0.0f : 0.2126f) +
1074                 (disable_green ? 0.0f : 0.7152f) +
1075                 (disable_blue  ? 0.0f : 0.0722f);
1076
1077         for (y= 0; y<ibuf->y; y++) {
1078                 for (x= 0; x<ibuf->x; x++) {
1079                         int pixel= ibuf->x*y + x;
1080
1081                         if (ibuf->rect_float) {
1082                                 float *rrgbf= ibuf->rect_float + pixel*4;
1083                                 float r = disable_red   ? 0.0f : rrgbf[0];
1084                                 float g = disable_green ? 0.0f : rrgbf[1];
1085                                 float b = disable_blue  ? 0.0f : rrgbf[2];
1086                                 if (grayscale) {
1087                                         float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
1088                                         rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
1089                                 }
1090                                 else {
1091                                         rrgbf[0] = r;
1092                                         rrgbf[1] = g;
1093                                         rrgbf[2] = b;
1094                                 }
1095                         }
1096                         else {
1097                                 char *rrgb= (char*)ibuf->rect + pixel*4;
1098                                 char r = disable_red   ? 0 : rrgb[0];
1099                                 char g = disable_green ? 0 : rrgb[1];
1100                                 char b = disable_blue  ? 0 : rrgb[2];
1101                                 if (grayscale) {
1102                                         float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
1103                                         rrgb[0] = rrgb[1] = rrgb[2] = gray;
1104                                 }
1105                                 else {
1106                                         rrgb[0] = r;
1107                                         rrgb[1] = g;
1108                                         rrgb[2] = b;
1109                                 }
1110                         }
1111                 }
1112         }
1113 }
1114
1115 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
1116 {
1117         BKE_tracking_disable_imbuf_channels(ibuf, track->flag&TRACK_DISABLE_RED,
1118                         track->flag&TRACK_DISABLE_GREEN, track->flag&TRACK_DISABLE_BLUE, grayscale);
1119 }
1120
1121 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1122                         float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
1123 {
1124         ImBuf *tmpibuf;
1125         int x, y;
1126         int x1, y1, w, h;
1127         float mpos[2];
1128
1129         copy_v2_v2(mpos, marker->pos);
1130         if (anchored)
1131                 add_v2_v2(mpos, track->offset);
1132
1133         if (pos)
1134                 zero_v2(pos);
1135
1136         x= mpos[0]*ibuf->x;
1137         y= mpos[1]*ibuf->y;
1138
1139         w= (max[0]-min[0])*ibuf->x;
1140         h= (max[1]-min[1])*ibuf->y;
1141
1142         /* dimensions should be odd */
1143         w= w|1;
1144         h= h|1;
1145
1146         x1= x-(int)(w * (-min[0] / (max[0] - min[0])));
1147         y1= y-(int)(h * (-min[1] / (max[1] - min[1])));
1148
1149         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
1150         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
1151
1152         if (pos != NULL) {
1153                 pos[0]= mpos[0]*ibuf->x-x1+margin;
1154                 pos[1]= mpos[1]*ibuf->y-y1+margin;
1155         }
1156
1157         if (origin != NULL) {
1158                 origin[0]= x1-margin;
1159                 origin[1]= y1-margin;
1160         }
1161
1162         if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
1163            (track->flag & TRACK_DISABLE_RED)       ||
1164            (track->flag & TRACK_DISABLE_GREEN)     ||
1165            (track->flag & TRACK_DISABLE_BLUE))
1166         {
1167                 disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */);
1168         }
1169
1170         return tmpibuf;
1171 }
1172
1173 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1174                         int margin, int anchored, float pos[2], int origin[2])
1175 {
1176         return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
1177 }
1178
1179 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1180                         int margin, int anchored, float pos[2], int origin[2])
1181 {
1182         return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
1183 }
1184
1185 #ifdef WITH_LIBMV
1186 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1187                         int *width_r, int *height_r, float pos[2], int origin[2])
1188 {
1189         ImBuf *tmpibuf;
1190         float *pixels, *fp;
1191         int x, y, width, height;
1192
1193         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
1194         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
1195
1196         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
1197         disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
1198
1199         *width_r= width;
1200         *height_r= height;
1201
1202         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
1203         for (y= 0; y<(int)height; y++) {
1204                 for (x= 0; x<(int)width; x++) {
1205                         int pixel= tmpibuf->x*y + x;
1206
1207                         if (tmpibuf->rect_float) {
1208                                 float *rrgbf= tmpibuf->rect_float + pixel*4;
1209                                 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
1210                         }
1211                         else {
1212                                 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
1213                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
1214                         }
1215                         fp++;
1216                 }
1217         }
1218
1219         IMB_freeImBuf(tmpibuf);
1220
1221         return pixels;
1222 }
1223
1224 static unsigned char *get_ucharbuf(ImBuf *ibuf)
1225 {
1226         int x, y;
1227         unsigned char *pixels, *cp;
1228
1229         cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
1230         for (y= 0; y<ibuf->y; y++) {
1231                 for (x= 0; x<ibuf->x; x++) {
1232                         int pixel= ibuf->x*y + x;
1233
1234                         if (ibuf->rect_float) {
1235                                 const float *rrgbf= ibuf->rect_float + pixel*4;
1236                                 const float grey_f= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
1237                                 *cp= FTOCHAR(grey_f);
1238                         }
1239                         else {
1240                                 const unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
1241                                 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
1242                         }
1243                         cp++;
1244                 }
1245         }
1246
1247         return pixels;
1248 }
1249
1250 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1251                         int *width_r, int *height_r, float pos[2], int origin[2])
1252 {
1253         ImBuf *tmpibuf;
1254         unsigned char *pixels;
1255
1256         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
1257         disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
1258
1259         *width_r= tmpibuf->x;
1260         *height_r= tmpibuf->y;
1261
1262         pixels= get_ucharbuf(tmpibuf);
1263
1264         IMB_freeImBuf(tmpibuf);
1265
1266         return pixels;
1267 }
1268
1269 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
1270 {
1271         ImBuf *ibuf;
1272         MovieClipUser user= context->user;
1273
1274         user.framenr= framenr;
1275
1276         ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag, MOVIECLIP_CACHE_SKIP);
1277
1278         return ibuf;
1279 }
1280
1281 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
1282                         MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
1283 {
1284         int framenr= marker->framenr;
1285         int a= marker-track->markers;
1286
1287         *marker_keyed= marker;
1288
1289         while (a>=0 && a<track->markersnr) {
1290                 int next= (context->backwards) ? a+1 : a-1;
1291                 int is_keyframed= 0;
1292                 MovieTrackingMarker *cur_marker= &track->markers[a];
1293                 MovieTrackingMarker *next_marker= NULL;
1294
1295                 if (next>=0 && next<track->markersnr)
1296                         next_marker= &track->markers[next];
1297
1298                 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
1299                 if (next_marker && next_marker->flag&MARKER_DISABLED)
1300                         is_keyframed= 1;
1301
1302                 is_keyframed|= (cur_marker->flag&MARKER_TRACKED)==0;
1303
1304                 if (is_keyframed) {
1305                         framenr= cur_marker->framenr;
1306                         *marker_keyed= cur_marker;
1307                         break;
1308                 }
1309
1310                 a= next;
1311         }
1312
1313         return get_frame_ibuf(context, framenr);
1314 }
1315
1316 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1317                         int curfra, MovieTrackingMarker **marker_keyed)
1318 {
1319         ImBuf *ibuf= NULL;
1320
1321         if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
1322                 ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed);
1323         }
1324         else {
1325                 ibuf= get_frame_ibuf(context, curfra);
1326
1327                 /* use current marker as keyframed position */
1328                 *marker_keyed= marker;
1329         }
1330
1331         return ibuf;
1332 }
1333
1334 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
1335 {
1336         int i, j;
1337
1338         for (i=0; i<track_context->pattern_size; i++) {
1339                 for (j=0; j<track_context->pattern_size; j++) {
1340                         track_context->warped[i*track_context->pattern_size+j]=
1341                                         image[(y+i-track_context->pattern_size/2)*width+x+j-track_context->pattern_size/2];
1342                 }
1343         }
1344 }
1345
1346 #endif
1347
1348 void BKE_tracking_sync(MovieTrackingContext *context)
1349 {
1350         MovieTracking *tracking= &context->clip->tracking;
1351         int newframe;
1352
1353         tracks_map_merge(context->tracks_map, tracking);
1354
1355         if (context->backwards) newframe= context->user.framenr+1;
1356         else newframe= context->user.framenr-1;
1357
1358         context->sync_frame= newframe;
1359 }
1360
1361 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
1362 {
1363         user->framenr= context->sync_frame;
1364 }
1365
1366 int BKE_tracking_next(MovieTrackingContext *context)
1367 {
1368         ImBuf *ibuf_new;
1369         int curfra= context->user.framenr;
1370         int a, ok= 0, map_size;
1371
1372         map_size= tracks_map_size(context->tracks_map);
1373
1374         /* nothing to track, avoid unneeded frames reading to save time and memory */
1375         if (!map_size)
1376                 return 0;
1377
1378         if (context->backwards) context->user.framenr--;
1379         else context->user.framenr++;
1380
1381         ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP);
1382         if (!ibuf_new)
1383                 return 0;
1384
1385         #pragma omp parallel for private(a) shared(ibuf_new, ok) if (map_size>1)
1386         for (a= 0; a<map_size; a++) {
1387                 TrackContext *track_context = NULL;
1388                 MovieTrackingTrack *track;
1389                 MovieTrackingMarker *marker;
1390
1391                 tracks_map_get(context->tracks_map, a, &track, (void**)&track_context);
1392
1393                 marker= BKE_tracking_exact_marker(track, curfra);
1394
1395                 if (marker && (marker->flag&MARKER_DISABLED)==0) {
1396 #ifdef WITH_LIBMV
1397                         int width, height, origin[2], tracked= 0, need_readjust= 0;
1398                         float pos[2], margin[2], dim[2];
1399                         double x1, y1, x2, y2;
1400                         ImBuf *ibuf= NULL;
1401                         MovieTrackingMarker marker_new, *marker_keyed;
1402                         int onbound= 0, nextfra;
1403
1404                         if (track->pattern_match==TRACK_MATCH_KEYFRAME)
1405                                 need_readjust= context->first_time;
1406                         else
1407                                 need_readjust= 1;
1408
1409                         if (context->backwards) nextfra= curfra-1;
1410                         else nextfra= curfra+1;
1411
1412                         /* margin from frame boundaries */
1413                         sub_v2_v2v2(dim, track->pat_max, track->pat_min);
1414                         margin[0]= margin[1]= MAX2(dim[0], dim[1]) / 2.0f;
1415
1416                         margin[0]= MAX2(margin[0], (float)track->margin / ibuf_new->x);
1417                         margin[1]= MAX2(margin[1], (float)track->margin / ibuf_new->y);
1418
1419                         /* do not track markers which are too close to boundary */
1420                         if (marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] ||
1421                            marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
1422                                 onbound= 1;
1423                         }
1424                         else if (ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
1425                                 float *patch_new;
1426
1427                                 if (need_readjust) {
1428                                         /* calculate patch for keyframed position */
1429                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1430
1431                                         if (track_context->patch)
1432                                                 MEM_freeN(track_context->patch);
1433
1434                                         track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin);
1435
1436                                         IMB_freeImBuf(ibuf);
1437                                 }
1438
1439                                 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1440
1441                                 x1= track_context->keyframed_pos[0];
1442                                 y1= track_context->keyframed_pos[1];
1443
1444                                 x2= pos[0];
1445                                 y2= pos[1];
1446
1447                                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1448                                                         width, height, x1, y1, &x2, &y2);
1449
1450                                 MEM_freeN(patch_new);
1451                         }
1452                         else if (track->tracker==TRACKER_SAD) {
1453                                 unsigned char *image_new;
1454                                 float correlation;
1455                                 float warp[3][2]={{0}};
1456
1457                                 if (need_readjust) {
1458                                         unsigned char *image;
1459
1460                                         /* calculate pattern for keyframed position */
1461                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1462
1463                                         image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1464
1465                                         memset(warp, 0, sizeof(warp));
1466                                         warp[0][0]= 1;
1467                                         warp[1][1]= 1;
1468                                         warp[2][0]= pos[0];
1469                                         warp[2][1]= pos[1];
1470
1471                                         if (!track_context->pattern) {
1472                                                 int square= track_context->pattern_size*track_context->pattern_size;
1473                                                 track_context->pattern= MEM_callocN(sizeof(unsigned char)*square, "trackking pattern");
1474                                         }
1475
1476                                         libmv_SADSamplePattern(image, width, warp, track_context->pattern, track_context->pattern_size);
1477
1478                                         MEM_freeN(image);
1479                                         IMB_freeImBuf(ibuf);
1480                                 }
1481
1482                                 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1483
1484                                 if (track_context->warped==NULL) {
1485                                         unsigned char *image_old;
1486
1487                                         ibuf= get_frame_ibuf(context, curfra);
1488
1489                                         if (track_context->warped==NULL) {
1490                                                 int square= track_context->pattern_size*track_context->pattern_size;
1491                                                 track_context->warped= MEM_callocN(sizeof(unsigned char)*square, "trackking warped");
1492                                         }
1493
1494                                         image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1495                                         get_warped(track_context, pos[0], pos[1], width, image_old);
1496                                         IMB_freeImBuf(ibuf);
1497                                         MEM_freeN(image_old);
1498                                 }
1499
1500                                 memset(warp, 0, sizeof(warp));
1501                                 warp[0][0]= 1;
1502                                 warp[1][1]= 1;
1503                                 warp[2][0]= pos[0];
1504                                 warp[2][1]= pos[1];
1505
1506                                 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped,
1507                                                         track_context->pattern_size, image_new, width, width, height, warp);
1508
1509                                 x2= warp[2][0];
1510                                 y2= warp[2][1];
1511
1512                                 tracked= track->minimum_correlation < correlation;
1513
1514                                 if (tracked)
1515                                         get_warped(track_context, x2, y2, width, image_new);
1516
1517                                 MEM_freeN(image_new);
1518                         }
1519
1520                         if (tracked && !onbound && finite(x2) && finite(y2)) {
1521                                 if (context->first_time) {
1522                                         #pragma omp critical
1523                                         {
1524                                                 /* check if there's no keyframe/tracked markers before tracking marker.
1525                                                  * if so -- create disabled marker before currently tracking "segment" */
1526                                                 put_disabled_marker(track, marker, !context->backwards, 0);
1527                                         }
1528                                 }
1529
1530                                 memset(&marker_new, 0, sizeof(marker_new));
1531
1532                                 if (!onbound) {
1533                                         marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1534                                         marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1535                                 }
1536                                 else {
1537                                         copy_v2_v2(marker_new.pos, marker->pos);
1538                                 }
1539
1540                                 marker_new.flag|= MARKER_TRACKED;
1541                                 marker_new.framenr= nextfra;
1542
1543                                 #pragma omp critical
1544                                 {
1545                                         BKE_tracking_insert_marker(track, &marker_new);
1546                                 }
1547
1548                                 /* make currently tracked segment be finished with disabled marker */
1549                                 #pragma omp critical
1550                                 {
1551                                         put_disabled_marker(track, &marker_new, context->backwards, 0);
1552                                 }
1553                         }
1554                         else {
1555                                 marker_new= *marker;
1556
1557                                 marker_new.framenr= nextfra;
1558                                 marker_new.flag|= MARKER_DISABLED;
1559
1560                                 #pragma omp critical
1561                                 {
1562                                         BKE_tracking_insert_marker(track, &marker_new);
1563                                 }
1564                         }
1565
1566                         ok= 1;
1567 #endif
1568                 }
1569         }
1570
1571         IMB_freeImBuf(ibuf_new);
1572
1573         context->first_time= 0;
1574         context->frames++;
1575
1576         return ok;
1577 }
1578
1579 /*********************** camera solving *************************/
1580
1581 typedef struct MovieReconstructContext {
1582 #ifdef WITH_LIBMV
1583         struct libmv_Tracks *tracks;
1584         int keyframe1, keyframe2;
1585         short refine_flags;
1586
1587         struct libmv_Reconstruction *reconstruction;
1588 #endif
1589         char object_name[MAX_NAME];
1590         int is_camera;
1591
1592         float focal_length;
1593         float principal_point[2];
1594         float k1, k2, k3;
1595
1596         float reprojection_error;
1597
1598         TracksMap *tracks_map;
1599
1600         int sfra, efra;
1601 } MovieReconstructContext;
1602
1603 typedef struct ReconstructProgressData {
1604         short *stop;
1605         short *do_update;
1606         float *progress;
1607         char *stats_message;
1608         int message_size;
1609 } ReconstructProgressData;
1610
1611 #if WITH_LIBMV
1612 static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
1613 {
1614         int tracknr= 0;
1615         MovieTrackingTrack *track;
1616         struct libmv_Tracks *tracks= libmv_tracksNew();
1617
1618         track= tracksbase->first;
1619         while (track) {
1620                 int a= 0;
1621
1622                 for (a= 0; a<track->markersnr; a++) {
1623                         MovieTrackingMarker *marker= &track->markers[a];
1624
1625                         if ((marker->flag&MARKER_DISABLED)==0)
1626                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1627                                                         marker->pos[0]*width, marker->pos[1]*height);
1628                 }
1629
1630                 track= track->next;
1631                 tracknr++;
1632         }
1633
1634         return tracks;
1635 }
1636
1637 static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking)
1638 {
1639         struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
1640         struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction);
1641
1642         float aspy= 1.0f/tracking->camera.pixel_aspect;
1643
1644         double focal_length, principal_x, principal_y, k1, k2, k3;
1645         int width, height;
1646
1647         libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y,
1648                         &k1, &k2, &k3, &width, &height);
1649
1650         tracking->camera.focal= focal_length;
1651         tracking->camera.principal[0]= principal_x;
1652
1653         /* todo: verify divide by aspy is correct */
1654         tracking->camera.principal[1]= principal_y / aspy;
1655         tracking->camera.k1= k1;
1656         tracking->camera.k2= k2;
1657 }
1658
1659 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
1660 {
1661         struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
1662         MovieTrackingReconstruction *reconstruction= NULL;
1663         MovieReconstructedCamera *reconstructed;
1664         MovieTrackingTrack *track;
1665         ListBase *tracksbase=  NULL;
1666         int ok= 1, tracknr= 0, a, origin_set= 0;
1667         int sfra= context->sfra, efra= context->efra;
1668         float imat[4][4];
1669
1670         if (context->is_camera) {
1671                 tracksbase= &tracking->tracks;
1672                 reconstruction= &tracking->reconstruction;
1673         }
1674         else {
1675                 MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name);
1676
1677                 tracksbase= &object->tracks;
1678                 reconstruction= &object->reconstruction;
1679         }
1680
1681         unit_m4(imat);
1682
1683         track= tracksbase->first;
1684         while (track) {
1685                 double pos[3];
1686
1687                 if (libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1688                         track->bundle_pos[0]= pos[0];
1689                         track->bundle_pos[1]= pos[1];
1690                         track->bundle_pos[2]= pos[2];
1691
1692                         track->flag|= TRACK_HAS_BUNDLE;
1693                         track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1694                 }
1695                 else {
1696                         track->flag&= ~TRACK_HAS_BUNDLE;
1697                         ok= 0;
1698
1699                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1700                 }
1701
1702                 track= track->next;
1703                 tracknr++;
1704         }
1705
1706         if (reconstruction->cameras)
1707                 MEM_freeN(reconstruction->cameras);
1708
1709         reconstruction->camnr= 0;
1710         reconstruction->cameras= NULL;
1711         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1712
1713         for (a= sfra; a<=efra; a++) {
1714                 double matd[4][4];
1715
1716                 if (libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1717                         int i, j;
1718                         float mat[4][4];
1719                         float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a);
1720
1721                         for (i=0; i<4; i++)
1722                                 for (j= 0; j<4; j++)
1723                                         mat[i][j]= matd[i][j];
1724
1725                         if (!origin_set) {
1726                                 copy_m4_m4(imat, mat);
1727                                 invert_m4(imat);
1728                                 origin_set= 1;
1729                         }
1730
1731                         if (origin_set)
1732                                 mult_m4_m4m4(mat, imat, mat);
1733
1734                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1735                         reconstructed[reconstruction->camnr].framenr= a;
1736                         reconstructed[reconstruction->camnr].error= error;
1737                         reconstruction->camnr++;
1738                 }
1739                 else {
1740                         ok= 0;
1741                         printf("No camera for frame %d\n", a);
1742                 }
1743         }
1744
1745         if (reconstruction->camnr) {
1746                 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1747                 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1748         }
1749
1750         if (origin_set) {
1751                 track= tracksbase->first;
1752                 while (track) {
1753                         if (track->flag&TRACK_HAS_BUNDLE)
1754                                 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
1755
1756                         track= track->next;
1757                 }
1758         }
1759
1760         MEM_freeN(reconstructed);
1761
1762         return ok;
1763 }
1764
1765 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
1766 {
1767         /* take the intrinscis back from libmv */
1768         retrieve_libmv_reconstruct_intrinscis(context, tracking);
1769
1770         return retrieve_libmv_reconstruct_tracks(context, tracking);
1771 }
1772
1773 static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
1774 {
1775         int refine= tracking->settings.refine_camera_intrinsics;
1776         int flags= 0;
1777
1778         if ((object->flag&TRACKING_OBJECT_CAMERA)==0)
1779                 return 0;
1780
1781         if (refine&REFINE_FOCAL_LENGTH)
1782                 flags|= LIBMV_REFINE_FOCAL_LENGTH;
1783
1784         if (refine&REFINE_PRINCIPAL_POINT)
1785                 flags|= LIBMV_REFINE_PRINCIPAL_POINT;
1786
1787         if (refine&REFINE_RADIAL_DISTORTION_K1)
1788                 flags|= REFINE_RADIAL_DISTORTION_K1;
1789
1790         if (refine&REFINE_RADIAL_DISTORTION_K2)
1791                 flags|= REFINE_RADIAL_DISTORTION_K2;
1792
1793         return flags;
1794 }
1795
1796 static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
1797 {
1798         int tot= 0;
1799         int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2;
1800         MovieTrackingTrack *track;
1801
1802         track= tracksbase->first;
1803         while (track) {
1804                 if (BKE_tracking_has_enabled_marker(track, frame1))
1805                         if (BKE_tracking_has_enabled_marker(track, frame2))
1806                                 tot++;
1807
1808                 track= track->next;
1809         }
1810
1811         return tot;
1812 }
1813 #endif
1814
1815 int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
1816 {
1817 #if WITH_LIBMV
1818         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
1819
1820         if (count_tracks_on_both_keyframes(tracking, tracksbase)<8) {
1821                 BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size);
1822                 return 0;
1823         }
1824
1825         return 1;
1826 #else
1827         BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size);
1828         (void)tracking;
1829         (void)object;
1830
1831         return 0;
1832 #endif
1833 }
1834
1835 MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking,
1836                         MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height)
1837 {
1838         MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
1839         MovieTrackingCamera *camera= &tracking->camera;
1840         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
1841         float aspy= 1.0f/tracking->camera.pixel_aspect;
1842         int num_tracks= BLI_countlist(tracksbase);
1843         int sfra= INT_MAX, efra= INT_MIN;
1844         MovieTrackingTrack *track;
1845
1846         BLI_strncpy(context->object_name, object->name, sizeof(context->object_name));
1847         context->is_camera = object->flag&TRACKING_OBJECT_CAMERA;
1848
1849         context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
1850
1851         track= tracksbase->first;
1852         while (track) {
1853                 int first= 0, last= track->markersnr-1;
1854                 MovieTrackingMarker *first_marker= &track->markers[0];
1855                 MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1];
1856
1857                 /* find first not-disabled marker */
1858                 while (first<=track->markersnr-1 && first_marker->flag&MARKER_DISABLED) {
1859                         first++;
1860                         first_marker++;
1861                 }
1862
1863                 /* find last not-disabled marker */
1864                 while (last>=0 && last_marker->flag&MARKER_DISABLED) {
1865                         last--;
1866                         last_marker--;
1867                 }
1868
1869                 if (first<track->markersnr-1)
1870                         sfra= MIN2(sfra, first_marker->framenr);
1871
1872                 if (last>=0)
1873                         efra= MAX2(efra, last_marker->framenr);
1874
1875                 tracks_map_insert(context->tracks_map, track, NULL);
1876
1877                 track= track->next;
1878         }
1879
1880         context->sfra= sfra;
1881         context->efra= efra;
1882
1883 #ifdef WITH_LIBMV
1884         context->tracks= create_libmv_tracks(tracksbase, width, height*aspy);
1885         context->keyframe1= keyframe1;
1886         context->keyframe2= keyframe2;
1887         context->refine_flags= get_refine_intrinsics_flags(tracking, object);
1888 #else
1889         (void) width;
1890         (void) height;
1891         (void) keyframe1;
1892         (void) keyframe2;
1893 #endif
1894
1895         context->focal_length= camera->focal;
1896         context->principal_point[0]= camera->principal[0];
1897         context->principal_point[1]= camera->principal[1]*aspy;
1898
1899         context->k1= camera->k1;
1900         context->k2= camera->k2;
1901         context->k3= camera->k3;
1902
1903         return context;
1904 }
1905
1906 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
1907 {
1908 #ifdef WITH_LIBMV
1909         if (context->reconstruction)
1910                         libmv_destroyReconstruction(context->reconstruction);
1911
1912         libmv_tracksDestroy(context->tracks);
1913 #endif
1914
1915         tracks_map_free(context->tracks_map, NULL);
1916
1917         MEM_freeN(context);
1918 }
1919
1920 #ifdef WITH_LIBMV
1921 static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message)
1922 {
1923         ReconstructProgressData *progressdata= customdata;
1924
1925         if (progressdata->progress) {
1926                 *progressdata->progress= progress;
1927                 *progressdata->do_update= 1;
1928         }
1929
1930         BLI_snprintf(progressdata->stats_message, progressdata->message_size,
1931                         "Solving camera | %s", message);
1932 }
1933 #endif
1934
1935 #if 0
1936 static int solve_reconstruction_testbreak_cb(void *customdata)
1937 {
1938         ReconstructProgressData *progressdata= customdata;
1939
1940         if (progressdata->stop && *progressdata->stop)
1941                 return 1;
1942
1943         return G.afbreek;
1944 }
1945 #endif
1946
1947 void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop,
1948                         short *do_update, float *progress, char *stats_message, int message_size)
1949 {
1950 #ifdef WITH_LIBMV
1951         float error;
1952
1953         ReconstructProgressData progressdata;
1954
1955         progressdata.stop= stop;
1956         progressdata.do_update= do_update;
1957         progressdata.progress= progress;
1958         progressdata.stats_message= stats_message;
1959         progressdata.message_size= message_size;
1960
1961         context->reconstruction = libmv_solveReconstruction(context->tracks,
1962                 context->keyframe1, context->keyframe2,
1963                 context->refine_flags,
1964                 context->focal_length,
1965                 context->principal_point[0], context->principal_point[1],
1966                 context->k1, context->k2, context->k3,
1967                 solve_reconstruction_update_cb, &progressdata);
1968
1969         error= libmv_reprojectionError(context->reconstruction);
1970
1971         context->reprojection_error= error;
1972 #else
1973         (void) context;
1974         (void) stop;
1975         (void) do_update;
1976         (void) progress;
1977         (void) stats_message;
1978         (void) message_size;
1979 #endif
1980 }
1981
1982 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
1983 {
1984         MovieTrackingReconstruction *reconstruction;
1985
1986         tracks_map_merge(context->tracks_map, tracking);
1987
1988         if (context->is_camera) {
1989                 reconstruction= &tracking->reconstruction;
1990         }
1991         else {
1992                 MovieTrackingObject *object;
1993
1994                 object= BKE_tracking_named_object(tracking, context->object_name);
1995                 reconstruction= &object->reconstruction;
1996         }
1997
1998         reconstruction->error= context->reprojection_error;
1999         reconstruction->flag|= TRACKING_RECONSTRUCTED;
2000
2001 #ifdef WITH_LIBMV
2002         if (!retrieve_libmv_reconstruct(context, tracking))
2003                 return 0;
2004 #endif
2005
2006         return 1;
2007 }
2008
2009 void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
2010 {
2011         BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
2012 }
2013
2014 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
2015 {
2016         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
2017         MovieTrackingTrack *track= tracksbase->first;
2018
2019         while (track) {
2020                 if (!strcmp(track->name, name))
2021                         return track;
2022
2023                 track= track->next;
2024         }
2025
2026         return NULL;
2027 }
2028
2029 static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
2030 {
2031         MovieReconstructedCamera *cameras= reconstruction->cameras;
2032         int a= 0, d= 1;
2033
2034         if (!reconstruction->camnr)
2035                 return -1;
2036
2037         if (framenr<cameras[0].framenr) {
2038                 if (nearest) return 0;
2039                 else return -1;
2040         }
2041
2042         if (framenr>cameras[reconstruction->camnr-1].framenr) {
2043                 if (nearest) return reconstruction->camnr-1;
2044                 else return -1;
2045         }
2046
2047         if (reconstruction->last_camera<reconstruction->camnr)
2048                 a= reconstruction->last_camera;
2049
2050         if (cameras[a].framenr>=framenr)
2051                 d= -1;
2052
2053         while (a>=0 && a<reconstruction->camnr) {
2054                 int cfra= cameras[a].framenr;
2055
2056                 /* check if needed framenr was "skipped" -- no data for requested frame */
2057
2058                 if (d>0 && cfra>framenr) {
2059                         /* interpolate with previous position */
2060                         if (nearest) return a-1;
2061                         else break;
2062                 }
2063
2064                 if (d<0 && cfra<framenr) {
2065                         /* interpolate with next position */
2066                         if (nearest) return a;
2067                         else break;
2068                 }
2069
2070                 if (cfra==framenr) {
2071                         reconstruction->last_camera= a;
2072
2073                         return a;
2074                 }
2075
2076                 a+= d;
2077         }
2078
2079         return -1;
2080 }
2081
2082 static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4])
2083 {
2084         if ((object->flag&TRACKING_OBJECT_CAMERA)==0) {
2085                 float smat[4][4];
2086
2087                 scale_m4_fl(smat, 1.0f/object->scale);
2088                 mult_m4_m4m4(mat, mat, smat);
2089         }
2090 }
2091
2092 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
2093                         MovieTrackingObject *object, int framenr)
2094 {
2095         MovieTrackingReconstruction *reconstruction;
2096         int a;
2097
2098         reconstruction= BKE_tracking_object_reconstruction(tracking, object);
2099         a= reconstruction_camera_index(reconstruction, framenr, 0);
2100
2101         if (a==-1)
2102                 return NULL;
2103
2104         return &reconstruction->cameras[a];
2105 }
2106
2107 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
2108                         int framenr, float mat[4][4])
2109 {
2110         MovieTrackingReconstruction *reconstruction;
2111         MovieReconstructedCamera *cameras;
2112         int a;
2113
2114         reconstruction= BKE_tracking_object_reconstruction(tracking, object);
2115         cameras= reconstruction->cameras;
2116         a= reconstruction_camera_index(reconstruction, framenr, 1);
2117
2118         if (a==-1) {
2119                 unit_m4(mat);
2120                 return;
2121         }
2122
2123         if (cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
2124                 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
2125
2126                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
2127         }
2128         else {
2129                 copy_m4_m4(mat, cameras[a].mat);
2130         }
2131
2132         scale_reconstructed_camera(object, mat);
2133 }
2134
2135 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
2136 {
2137         if (!ob) {
2138                 if (scene->camera) ob= scene->camera;
2139                 else ob= scene_find_camera(scene);
2140         }
2141
2142         if (ob)
2143                 where_is_object_mat(scene, ob, mat);
2144         else
2145                 unit_m4(mat);
2146 }
2147
2148 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
2149 {
2150         *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx;
2151         *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx;
2152 }
2153
2154 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
2155 {
2156         float focal= tracking->camera.focal;
2157
2158         camera->sensor_x= tracking->camera.sensor_width;
2159         camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO;
2160         camera->lens= focal*camera->sensor_x/width;
2161
2162         scene->r.xsch= width*tracking->camera.pixel_aspect;
2163         scene->r.ysch= height;
2164
2165         scene->r.xasp= 1.0f;
2166         scene->r.yasp= 1.0f;
2167
2168         BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
2169 }
2170
2171 void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
2172                         int framenr, int winx, int winy, float mat[4][4])
2173 {
2174         MovieReconstructedCamera *camera;
2175         float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
2176         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
2177         float winmat[4][4];
2178         float ycor= 1.0f/tracking->camera.pixel_aspect;
2179         float shiftx, shifty, winside= MAX2(winx, winy);
2180
2181         BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
2182
2183         clipsta= 0.1f;
2184         clipend= 1000.0f;
2185
2186         if (winx >= winy)
2187                 viewfac= (lens*winx)/tracking->camera.sensor_width;
2188         else
2189                 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
2190
2191         pixsize= clipsta/viewfac;
2192
2193         left= -0.5f*(float)winx + shiftx*winside;
2194         bottom= -0.5f*(ycor)*(float)winy + shifty*winside;
2195         right=  0.5f*(float)winx + shiftx*winside;
2196         top=  0.5f*(ycor)*(float)winy + shifty*winside;
2197
2198         left *= pixsize;
2199         right *= pixsize;
2200         bottom *= pixsize;
2201         top *= pixsize;
2202
2203         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
2204
2205         camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
2206
2207         if (camera) {
2208                 float imat[4][4];
2209
2210                 invert_m4_m4(imat, camera->mat);
2211                 mult_m4_m4m4(mat, winmat, imat);
2212         }
2213         else copy_m4_m4(mat, winmat);
2214 }
2215
2216 ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
2217 {
2218         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
2219
2220         if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2221                 return &object->tracks;
2222         }
2223
2224         return &tracking->tracks;
2225 }
2226
2227 MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
2228 {
2229         ListBase *tracksbase;
2230
2231         if (!tracking->act_track)
2232                 return NULL;
2233
2234         tracksbase= BKE_tracking_get_tracks(tracking);
2235
2236         /* check that active track is in current tracks list */
2237         if (BLI_findindex(tracksbase, tracking->act_track) >= 0)
2238                 return tracking->act_track;
2239
2240         return NULL;
2241 }
2242
2243 MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
2244 {
2245         return BLI_findlink(&tracking->objects, tracking->objectnr);
2246 }
2247
2248 MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
2249 {
2250         MovieTrackingObject *object= tracking->objects.first;
2251
2252         while (object) {
2253                 if (object->flag & TRACKING_OBJECT_CAMERA)
2254                         return object;
2255
2256                 object= object->next;
2257         }
2258
2259         return NULL;
2260 }
2261
2262 ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
2263 {
2264         if (object->flag & TRACKING_OBJECT_CAMERA) {
2265                 return &tracking->tracks;
2266         }
2267
2268         return &object->tracks;
2269 }
2270
2271 MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
2272 {
2273         if (object->flag & TRACKING_OBJECT_CAMERA) {
2274                 return &tracking->reconstruction;
2275         }
2276
2277         return &object->reconstruction;
2278 }
2279
2280 MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
2281 {
2282         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
2283
2284         return BKE_tracking_object_reconstruction(tracking, object);
2285 }
2286
2287 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2288 {
2289         MovieTrackingCamera *camera= &tracking->camera;
2290
2291 #ifdef WITH_LIBMV
2292         double x, y;
2293         float aspy= 1.0f/tracking->camera.pixel_aspect;
2294
2295         /* normalize coords */
2296         x= (co[0]-camera->principal[0]) / camera->focal;
2297         y= (co[1]-camera->principal[1] * aspy) / camera->focal;
2298
2299         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2300                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2301
2302         /* result is in image coords already */
2303         nco[0]= x;
2304         nco[1]= y;
2305 #else
2306         (void)camera;
2307         (void)co;
2308         (void)nco;
2309 #endif
2310 }
2311
2312 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2313 {
2314         MovieTrackingCamera *camera= &tracking->camera;
2315
2316 #ifdef WITH_LIBMV
2317         double x= co[0], y= co[1];
2318         float aspy= 1.0f/tracking->camera.pixel_aspect;
2319
2320         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2321                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2322
2323         nco[0]= x * camera->focal + camera->principal[0];
2324         nco[1]= y * camera->focal + camera->principal[1] * aspy;
2325 #else
2326         (void)camera;
2327         (void)co;
2328         (void)nco;
2329 #endif
2330 }
2331
2332 #ifdef WITH_LIBMV
2333 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
2334 {
2335         int i, prev;
2336         int count= 0;
2337         bGPDspoint *points= stroke->points;
2338
2339         prev= stroke->totpoints-1;
2340
2341         for (i= 0; i<stroke->totpoints; i++) {
2342                 if ((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) {
2343                         float fac= (y-points[i].y)/(points[prev].y-points[i].y);
2344
2345                         if (points[i].x+fac*(points[prev].x-points[i].x)<x)
2346                                 count++;
2347                 }
2348
2349                 prev= i;
2350         }
2351
2352         return count%2;
2353 }
2354
2355 static int point_in_layer(bGPDlayer *layer, float x, float y)
2356 {
2357         bGPDframe *frame= layer->frames.first;
2358
2359         while (frame) {
2360                 bGPDstroke *stroke= frame->strokes.first;
2361                 while (stroke) {
2362                         if (point_in_stroke(stroke, x, y))
2363                                 return 1;
2364
2365                         stroke= stroke->next;
2366                 }
2367                 frame= frame->next;
2368         }
2369
2370         return 0;
2371 }
2372
2373 static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
2374                         struct libmv_Features *features, int framenr, int width, int height,
2375                         bGPDlayer *layer, int place_outside_layer)
2376 {
2377         int a;
2378
2379         a= libmv_countFeatures(features);
2380         while (a--) {
2381                 MovieTrackingTrack *track;
2382                 double x, y, size, score;
2383                 int ok= 1;
2384                 float xu, yu;
2385
2386                 libmv_getFeature(features, a, &x, &y, &score, &size);
2387
2388                 xu= x/width;
2389                 yu= y/height;
2390
2391                 if (layer)
2392                         ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
2393
2394                 if (ok) {
2395                         track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
2396                         track->flag|= SELECT;
2397                         track->pat_flag|= SELECT;
2398                         track->search_flag|= SELECT;
2399                 }
2400         }
2401 }
2402 #endif
2403
2404 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
2405                         int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
2406                         int place_outside_layer)
2407 {
2408 #ifdef WITH_LIBMV
2409         struct libmv_Features *features;
2410         unsigned char *pixels= get_ucharbuf(ibuf);
2411
2412         features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
2413                         margin, min_trackness, min_distance);
2414
2415         MEM_freeN(pixels);
2416
2417         retrieve_libmv_features(tracking, tracksbase, features, framenr,
2418                         ibuf->x, ibuf->y, layer, place_outside_layer);
2419
2420         libmv_destroyFeatures(features);
2421 #else
2422         (void)tracking;
2423         (void)tracksbase;
2424         (void)ibuf;
2425         (void)framenr;
2426         (void)margin;
2427         (void)min_trackness;
2428         (void)min_distance;
2429         (void)layer;
2430         (void)place_outside_layer;
2431 #endif
2432 }
2433
2434 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
2435 {
2436         MovieTrackingObject *object;
2437         int cur= 1;
2438
2439         object= tracking->objects.first;
2440         while (object) {
2441                 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
2442                 MovieTrackingTrack *track= tracksbase->first;
2443
2444                 while (track) {
2445                         if (track->flag&TRACK_HAS_BUNDLE) {
2446                                 if (cur==tracknr) {
2447                                         *tracksbase_r= tracksbase;
2448                                         return track;
2449                                 }
2450
2451                                 cur++;
2452                         }
2453
2454                         track= track->next;
2455                 }
2456
2457                 object= object->next;
2458         }
2459
2460         *tracksbase_r= NULL;
2461
2462         return NULL;
2463 }
2464
2465 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
2466 {
2467         int ok= 0;
2468         float min[2], max[2];
2469         MovieTrackingTrack *track;
2470
2471         INIT_MINMAX2(min, max);
2472
2473         (void) tracking;
2474
2475         track= tracking->tracks.first;
2476         while (track) {
2477                 if (track->flag&TRACK_USE_2D_STAB) {
2478                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
2479
2480                         DO_MINMAX2(marker->pos, min, max);
2481
2482                         ok= 1;
2483                 }
2484
2485                 track= track->next;
2486         }
2487
2488         median[0]= (max[0]+min[0])/2.0f;
2489         median[1]= (max[1]+min[1])/2.0f;
2490
2491         return ok;
2492 }
2493
2494 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
2495                         float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
2496 {
2497         MovieTrackingStabilization *stab= &tracking->stabilization;
2498
2499         *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f;
2500         *angle= 0.0f;
2501
2502         loc[0]= (firstmedian[0]-median[0])*width*(*scale);
2503         loc[1]= (firstmedian[1]-median[1])*height*(*scale);
2504
2505         mul_v2_fl(loc, stab->locinf);
2506
2507         if ((stab->flag&TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) {
2508                 MovieTrackingMarker *marker;
2509                 float a[2], b[2];
2510                 float x0= (float)width/2.0f, y0= (float)height/2.0f;
2511                 float x= median[0]*width, y= median[1]*height;
2512
2513                 marker= BKE_tracking_get_marker(stab->rot_track, 1);
2514                 sub_v2_v2v2(a, marker->pos, firstmedian);
2515                 a[0]*= width;
2516                 a[1]*= height;
2517
2518                 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
2519                 sub_v2_v2v2(b, marker->pos, median);
2520                 b[0]*= width;
2521                 b[1]*= height;
2522
2523                 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
2524                 *angle*= stab->rotinf;
2525
2526                 /* convert to rotation around image center */
2527                 loc[0]-= (x0 + (x-x0)*cosf(*angle)-(y-y0)*sinf(*angle) - x)*(*scale);
2528                 loc[1]-= (y0 + (x-x0)*sinf(*angle)+(y-y0)*cosf(*angle) - y)*(*scale);
2529         }
2530 }
2531
2532 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
2533 {
2534         float firstmedian[2];
2535         MovieTrackingStabilization *stab= &tracking->stabilization;
2536         float aspect= tracking->camera.pixel_aspect;
2537
2538         if (stab->ok)
2539                 return stab->scale;
2540
2541         if (stabilization_median_point(tracking, 1, firstmedian)) {
2542                 int sfra= INT_MAX, efra= INT_MIN, cfra;
2543                 float scale= 1.0f;
2544                 MovieTrackingTrack *track;
2545
2546                 stab->scale= 1.0f;
2547
2548                 track= tracking->tracks.first;
2549                 while (track) {
2550                         if (track->flag&TRACK_USE_2D_STAB ||
2551                            ((stab->flag&TRACKING_STABILIZE_ROTATION) && track==stab->rot_track)) {
2552                                 sfra= MIN2(sfra, track->markers[0].framenr);
2553                                 efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
2554                         }
2555
2556                         track= track->next;
2557                 }
2558
2559                 for (cfra=sfra; cfra<=efra; cfra++) {
2560                         float median[2];
2561                         float loc[2], angle, tmp_scale;
2562                         int i;
2563                         float mat[4][4];
2564                         float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
2565                         float si, co;
2566
2567                         stabilization_median_point(tracking, cfra, median);
2568
2569                         calculate_stabdata(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle);
2570
2571                         BKE_tracking_stabdata_to_mat4(width, height, aspect, loc, 1.0f, angle, mat);
2572
2573                         si = sin(angle);
2574                         co = cos(angle);
2575
2576                         for (i= 0; i<4; i++) {
2577                                 int j;
2578                                 float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f};
2579
2580                                 copy_v3_v3(a, points[i]);
2581                                 copy_v3_v3(b, points[(i+1)%4]);
2582
2583                                 mul_m4_v3(mat, a);
2584                                 mul_m4_v3(mat, b);
2585
2586                                 for (j= 0; j<4; j++) {
2587                                         float point[3]= {points[j][0], points[j][1], 0.0f};
2588                                         float v1[3], v2[3];
2589
2590                                         sub_v3_v3v3(v1, b, a);
2591                                         sub_v3_v3v3(v2, point, a);
2592
2593                                         if (cross_v2v2(v1, v2) >= 0.0f) {
2594                                                 const float rotDx[4][2] = {{1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}};
2595                                                 const float rotDy[4][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}};
2596
2597                                                 float dx = loc[0] * rotDx[j][0] + loc[1] * rotDx[j][1],
2598                                                       dy = loc[0] * rotDy[j][0] + loc[1] * rotDy[j][1];
2599
2600                                                 float w, h, E, F, G, H, I, J, K, S;
2601
2602                                                 if (j % 2) {
2603                                                         w = (float)height / 2.0f;
2604                                                         h = (float)width / 2.0f;
2605                                                 }
2606                                                 else {
2607                                                         w = (float)width / 2.0f;
2608                                                         h = (float)height / 2.0f;
2609                                                 }
2610
2611                                                 E = -w*co + h*si;
2612                                                 F = -h*co - w*si;
2613
2614                                                 if ((i % 2) == (j % 2)) {
2615                                                         G = -w*co - h*si;
2616                                                         H = h*co - w*si;
2617                                                 }
2618                                                 else {
2619                                                         G = w*co + h*si;
2620                                                         H = -h*co + w*si;
2621                                                 }
2622
2623                                                 I = F - H;
2624                                                 J = G - E;
2625                                                 K = G*F - E*H;
2626
2627                                                 S = (-w*I - h*J) / (dx*I + dy*J + K);
2628
2629                                                 scale = MAX2(scale, S);
2630                                         }
2631                                 }
2632                         }
2633                 }
2634
2635                 stab->scale= scale;
2636
2637                 if (stab->maxscale>0.0f)
2638                         stab->scale= MIN2(stab->scale, stab->maxscale);
2639         }
2640         else {
2641                 stab->scale= 1.0f;
2642         }
2643
2644         stab->ok= 1;
2645
2646         return stab->scale;
2647 }
2648
2649 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
2650 {
2651         int flags;
2652
2653         if (cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
2654                 IMB_freeImBuf(cacheibuf);
2655                 cacheibuf= NULL;
2656         }
2657
2658         flags= IB_rect;
2659
2660         if (srcibuf->rect_float)
2661                 flags|= IB_rectfloat;
2662
2663         if (cacheibuf) {
2664                 if (fill) {
2665                         float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
2666                         IMB_rectfill(cacheibuf, col);
2667                 }
2668         }
2669         else {
2670                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags);
2671                 cacheibuf->profile= srcibuf->profile;
2672         }
2673
2674         return cacheibuf;
2675 }
2676
2677 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
2678 {
2679         float firstmedian[2], median[2];
2680         MovieTrackingStabilization *stab= &tracking->stabilization;
2681
2682         if ((stab->flag&TRACKING_2D_STABILIZATION)==0) {
2683                 zero_v2(loc);
2684                 *scale= 1.0f;
2685                 *angle= 0.0f;
2686
2687                 return;
2688         }
2689
2690         if (stabilization_median_point(tracking, 1, firstmedian)) {
2691                 stabilization_median_point(tracking, framenr, median);
2692
2693                 if ((stab->flag&TRACKING_AUTOSCALE)==0)
2694                         stab->scale= 1.0f;
2695
2696                 if (!stab->ok) {
2697                         if (stab->flag&TRACKING_AUTOSCALE)
2698                                 stabilization_auto_scale_factor(tracking, width, height);
2699
2700                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
2701
2702                         stab->ok= 1;
2703                 }
2704                 else {
2705                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
2706                 }
2707         }
2708         else {
2709                 zero_v2(loc);
2710                 *scale= 1.0f;
2711                 *angle= 0.0f;
2712         }
2713 }
2714
2715 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
2716 {
2717         float tloc[2], tscale, tangle;
2718         MovieTrackingStabilization *stab= &tracking->stabilization;
2719         ImBuf *tmpibuf;
2720         float width= ibuf->x, height= ibuf->y;
2721         float aspect= tracking->camera.pixel_aspect;
2722
2723         if (loc)                copy_v2_v2(tloc, loc);
2724         if (scale)      tscale= *scale;
2725
2726         if ((stab->flag&TRACKING_2D_STABILIZATION)==0) {
2727                 if (loc)                zero_v2(loc);
2728                 if (scale)      *scale= 1.0f;
2729
2730                 return ibuf;
2731         }
2732
2733         BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
2734
2735         tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
2736
2737         /* scale would be handled by matrix transformation when angle is non-zero */
2738         if (tscale!=1.0f && tangle==0.0f) {
2739                 ImBuf *scaleibuf;
2740
2741                 stabilization_auto_scale_factor(tracking, width, height);
2742
2743                 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
2744                 stab->scaleibuf= scaleibuf;
2745
2746                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
2747                 IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale);
2748
2749                 ibuf= scaleibuf;
2750         }
2751
2752         if (tangle==0.0f) {
2753                 /* if angle is zero, then it's much faster to use rect copy
2754                  * but could be issues with subpixel precisions */
2755                 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);
2756         }
2757         else {
2758                 float mat[4][4];
2759                 int i, j, filter= tracking->stabilization.filter;
2760                 void (*interpolation) (struct ImBuf*, struct ImBuf*, float, float, int, int) = NULL;
2761
2762                 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat);
2763                 invert_m4(mat);
2764
2765                 if (filter == TRACKING_FILTER_NEAREAST)
2766                         interpolation = neareast_interpolation;
2767                 else if (filter == TRACKING_FILTER_BILINEAR)
2768                         interpolation = bilinear_interpolation;
2769                 else if (filter == TRACKING_FILTER_BICUBIC)
2770                         interpolation = bicubic_interpolation;
2771                 else
2772                         /* fallback to default interpolation method */
2773                         interpolation = neareast_interpolation;
2774
2775                 for (j=0; j<tmpibuf->y; j++) {
2776                         for (i=0; i<tmpibuf->x;i++) {
2777                                 float vec[3]= {i, j, 0};
2778
2779                                 mul_v3_m4v3(vec, mat, vec);
2780
2781                                 interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
2782                         }
2783                 }
2784         }
2785
2786         tmpibuf->userflags|= IB_MIPMAP_INVALID;
2787
2788         if (tmpibuf->rect_float)
2789                 tmpibuf->userflags|= IB_RECT_INVALID;
2790
2791         if (loc)                copy_v2_v2(loc, tloc);
2792         if (scale)      *scale= tscale;
2793         if (angle)      *angle= tangle;
2794
2795         return tmpibuf;
2796 }
2797
2798 void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, float loc[2], float scale, float angle, float mat[4][4])
2799 {
2800         float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4], amat[4][4], iamat[4][4];
2801         float svec[3]= {scale, scale, scale};
2802
2803         unit_m4(rmat);
2804         unit_m4(lmat);
2805         unit_m4(smat);
2806         unit_m4(cmat);
2807         unit_m4(amat);
2808
2809         /* aspect ratio correction matrix */
2810         amat[0][0] = 1.0f / aspect;
2811         invert_m4_m4(iamat, amat);
2812
2813         /* image center as rotation center */
2814         cmat[3][0]= (float)width/2.0f;
2815         cmat[3][1]= (float)height/2.0f;
2816         invert_m4_m4(icmat, cmat);
2817
2818         size_to_mat4(smat, svec);               /* scale matrix */
2819         add_v2_v2(lmat[3], loc);                /* translation matrix */
2820         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
2821
2822         /* compose transformation matrix */
2823         mul_serie_m4(mat, lmat, cmat, amat, rmat, iamat, smat, icmat, NULL);
2824 }
2825
2826 MovieDistortion *BKE_tracking_distortion_create(void)
2827 {
2828         MovieDistortion *distortion;
2829
2830         distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2831
2832         return distortion;
2833 }
2834
2835 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
2836 {
2837         MovieDistortion *new_distortion;
2838
2839         new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2840
2841 #ifdef WITH_LIBMV
2842         new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics);
2843 #else
2844         (void)distortion;
2845 #endif
2846
2847         return new_distortion;
2848 }
2849
2850 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
2851 {
2852         MovieTrackingCamera *camera= &tracking->camera;
2853         float aspy= 1.0f/tracking->camera.pixel_aspect;
2854
2855 #ifdef WITH_LIBMV
2856         if (!distortion->intrinsics) {
2857                 distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal,
2858                                 camera->principal[0], camera->principal[1] * aspy,
2859                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2860         }
2861         else {
2862                 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
2863                                 camera->principal[0], camera->principal[1] * aspy,
2864                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2865         }
2866 #else
2867         (void)distortion;
2868         (void)width;
2869         (void)height;
2870         (void)camera;
2871         (void)aspy;
2872 #endif
2873 }
2874
2875 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
2876                         ImBuf *ibuf, int width, int height, float overscan, int undistort)
2877 {
2878         ImBuf *resibuf;
2879
2880         BKE_tracking_distortion_update(distortion, tracking, width, height);
2881
2882         resibuf= IMB_dupImBuf(ibuf);
2883
2884         if (ibuf->rect_float) {
2885 #ifdef WITH_LIBMV
2886                 if (undistort) {
2887                         libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
2888                                                 ibuf->rect_float, resibuf->rect_float,
2889                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2890                 }
2891                 else {
2892                         libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
2893                                                 ibuf->rect_float, resibuf->rect_float,
2894                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2895                 }
2896 #endif
2897
2898                 ibuf->userflags|= IB_RECT_INVALID;
2899         }
2900         else {
2901 #ifdef WITH_LIBMV
2902                 if (undistort) {
2903                                 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
2904                                                         (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2905                                                         ibuf->x, ibuf->y, overscan, ibuf->channels);
2906                 }
2907                 else {
2908                         libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
2909                                                 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2910                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2911                 }
2912 #endif
2913         }
2914
2915 #ifndef WITH_LIBMV
2916         (void)overscan;
2917         (void)undistort;
2918 #endif
2919
2920         return resibuf;
2921 }
2922
2923 void BKE_tracking_distortion_destroy(MovieDistortion *distortion)
2924 {
2925 #ifdef WITH_LIBMV
2926         libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
2927 #endif
2928
2929         MEM_freeN(distortion);
2930 }
2931
2932 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2933 {
2934         MovieTrackingCamera *camera= &tracking->camera;
2935
2936         if (camera->intrinsics == NULL)
2937                 camera->intrinsics= BKE_tracking_distortion_create();
2938
2939         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1);
2940 }
2941
2942 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2943 {
2944         MovieTrackingCamera *camera= &tracking->camera;
2945
2946         if (camera->intrinsics == NULL)
2947                 camera->intrinsics= BKE_tracking_distortion_create();
2948
2949         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0);
2950 }
2951
2952 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
2953 void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
2954 {
2955         if (extend) {
2956                 BKE_tracking_track_flag(track, area, SELECT, 0);
2957         }
2958         else {
2959                 MovieTrackingTrack *cur= tracksbase->first;
2960
2961                 while (cur) {
2962                         if ((cur->flag & TRACK_HIDDEN) == 0) {
2963                                 if (cur==track) {
2964                                         BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2965                                         BKE_tracking_track_flag(cur, area, SELECT, 0);
2966                                 }
2967                                 else {
2968                                         BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2969                                 }
2970                         }
2971
2972                         cur= cur->next;
2973                 }
2974         }
2975 }
2976
2977 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
2978 {
2979         BKE_tracking_track_flag(track, area, SELECT, 1);
2980 }
2981
2982 MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name)
2983 {
2984         MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
2985
2986         if (tracking->tot_object==0) {
2987                 /* first object is always camera */
2988                 BLI_strncpy(object->name, "Camera", sizeof(object->name));
2989
2990                 object->flag|= TRACKING_OBJECT_CAMERA;
2991         }
2992         else {
2993                 BLI_strncpy(object->name, name, sizeof(object->name));
2994         }
2995
2996         BLI_addtail(&tracking->objects, object);
2997
2998         tracking->tot_object++;
2999         tracking->objectnr= BLI_countlist(&tracking->objects) - 1;
3000
3001         object->scale= 1.0f;
3002
3003         BKE_tracking_object_unique_name(tracking, object);
3004
3005         return object;
3006 }
3007
3008 void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object)
3009 {
3010         MovieTrackingTrack *track;
3011         int index= BLI_findindex(&tracking->objects, object);
3012
3013         if (index<0)
3014                 return;
3015
3016         if (object->flag & TRACKING_OBJECT_CAMERA) {
3017                 /* object used for camera solving can't be deleted */
3018                 return;
3019         }
3020
3021         track= object->tracks.first;
3022         while (track) {
3023                 if (track==tracking->act_track)
3024                         tracking->act_track= NULL;
3025
3026                 track= track->next;
3027         }
3028
3029         tracking_object_free(object);
3030         BLI_freelinkN(&tracking->objects, object);
3031
3032         tracking->tot_object--;
3033
3034         if (index>0)
3035                 tracking->objectnr= index-1;
3036         else
3037                 tracking->objectnr= 0;
3038 }
3039
3040 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
3041 {
3042         BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name));
3043 }
3044
3045 MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name)
3046 {
3047         MovieTrackingObject *object= tracking->objects.first;
3048
3049         while (object) {
3050                 if (!strcmp(object->name, name))
3051                         return object;
3052
3053                 object= object->next;
3054         }
3055
3056         return NULL;
3057 }