Camera tracking: libmv distortion API now also uses camera intrinsics
[blender.git] / source / blender / blenkernel / intern / tracking.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *                 Keir Mierle
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/tracking.c
29  *  \ingroup bke
30  */
31
32 #include <stddef.h>
33 #include <limits.h>
34 #include <math.h>
35 #include <memory.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_gpencil_types.h"
40 #include "DNA_camera_types.h"
41 #include "DNA_movieclip_types.h"
42 #include "DNA_object_types.h"   /* SELECT */
43 #include "DNA_scene_types.h"
44
45 #include "BLI_utildefines.h"
46 #include "BLI_math.h"
47 #include "BLI_math_base.h"
48 #include "BLI_listbase.h"
49 #include "BLI_ghash.h"
50 #include "BLI_path_util.h"
51 #include "BLI_string.h"
52 #include "BLI_threads.h"
53
54 #include "BLF_translation.h"
55
56 #include "BKE_global.h"
57 #include "BKE_tracking.h"
58 #include "BKE_movieclip.h"
59 #include "BKE_object.h"
60 #include "BKE_scene.h"
61
62 #include "IMB_imbuf_types.h"
63 #include "IMB_imbuf.h"
64
65 #include "raskter.h"
66
67 #ifdef WITH_LIBMV
68 #  include "libmv-capi.h"
69 #else
70 struct libmv_Features;
71 #endif
72
73 typedef struct MovieDistortion {
74         struct libmv_CameraIntrinsics *intrinsics;
75 } MovieDistortion;
76
77 static struct {
78         ListBase tracks;
79 } tracking_clipboard;
80
81 /*********************** Common functions  *************************/
82
83 static MovieTrackingTrack *tracking_track_duplicate(MovieTrackingTrack *track)
84 {
85         MovieTrackingTrack *new_track;
86
87         new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track");
88
89         *new_track = *track;
90         new_track->next = new_track->prev = NULL;
91
92         new_track->markers = MEM_dupallocN(new_track->markers);
93
94         return new_track;
95 }
96
97 static void tracking_tracks_free(ListBase *tracks)
98 {
99         MovieTrackingTrack *track;
100
101         for (track = tracks->first; track; track = track->next) {
102                 BKE_tracking_track_free(track);
103         }
104
105         BLI_freelistN(tracks);
106 }
107
108 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
109 {
110         if (reconstruction->cameras)
111                 MEM_freeN(reconstruction->cameras);
112 }
113
114 static void tracking_object_free(MovieTrackingObject *object)
115 {
116         tracking_tracks_free(&object->tracks);
117         tracking_reconstruction_free(&object->reconstruction);
118 }
119
120 static void tracking_objects_free(ListBase *objects)
121 {
122         MovieTrackingObject *object;
123
124         for (object = objects->first; object; object = object->next)
125                 tracking_object_free(object);
126
127         BLI_freelistN(objects);
128 }
129
130 static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
131 {
132         MovieTrackingDopesheetChannel *channel;
133
134         channel = dopesheet->channels.first;
135         while (channel) {
136                 if (channel->segments) {
137                         MEM_freeN(channel->segments);
138                 }
139
140                 channel = channel->next;
141         }
142
143         BLI_freelistN(&dopesheet->channels);
144         BLI_freelistN(&dopesheet->coverage_segments);
145
146         dopesheet->channels.first = dopesheet->channels.last = NULL;
147         dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL;
148         dopesheet->tot_channel = 0;
149 }
150
151 void BKE_tracking_free(MovieTracking *tracking)
152 {
153         tracking_tracks_free(&tracking->tracks);
154         tracking_reconstruction_free(&tracking->reconstruction);
155         tracking_objects_free(&tracking->objects);
156
157         if (tracking->stabilization.scaleibuf)
158                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
159
160         if (tracking->camera.intrinsics)
161                 BKE_tracking_distortion_free(tracking->camera.intrinsics);
162
163         tracking_dopesheet_free(&tracking->dopesheet);
164 }
165
166 void BKE_tracking_settings_init(MovieTracking *tracking)
167 {
168         tracking->camera.sensor_width = 35.0f;
169         tracking->camera.pixel_aspect = 1.0f;
170         tracking->camera.units = CAMERA_UNITS_MM;
171
172         tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
173         tracking->settings.default_minimum_correlation = 0.75;
174         tracking->settings.default_pattern_size = 15;
175         tracking->settings.default_search_size = 61;
176         tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
177         tracking->settings.dist = 1;
178         tracking->settings.object_distance = 1;
179         tracking->settings.reconstruction_success_threshold = 1e-3;
180
181         tracking->stabilization.scaleinf = 1.0f;
182         tracking->stabilization.locinf = 1.0f;
183         tracking->stabilization.rotinf = 1.0f;
184         tracking->stabilization.maxscale = 2.0f;
185
186         BKE_tracking_object_add(tracking, "Camera");
187 }
188
189 ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
190 {
191         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
192
193         if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
194                 return &object->tracks;
195         }
196
197         return &tracking->tracks;
198 }
199
200 MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
201 {
202         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
203
204         return BKE_tracking_object_get_reconstruction(tracking, object);
205 }
206
207 void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4][4])
208 {
209         if (!ob) {
210                 if (scene->camera)
211                         ob = scene->camera;
212                 else
213                         ob = BKE_scene_camera_find(scene);
214         }
215
216         if (ob)
217                 BKE_object_where_is_calc_mat4(scene, ob, mat);
218         else
219                 unit_m4(mat);
220 }
221
222 void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
223                                         int framenr, int winx, int winy, float mat[4][4])
224 {
225         MovieReconstructedCamera *camera;
226         float lens = tracking->camera.focal * tracking->camera.sensor_width / (float)winx;
227         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
228         float winmat[4][4];
229         float ycor =  1.0f / tracking->camera.pixel_aspect;
230         float shiftx, shifty, winside = (float)min_ii(winx, winy);
231
232         BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty);
233
234         clipsta = 0.1f;
235         clipend = 1000.0f;
236
237         if (winx >= winy)
238                 viewfac = (lens * winx) / tracking->camera.sensor_width;
239         else
240                 viewfac = (ycor * lens * winy) / tracking->camera.sensor_width;
241
242         pixsize = clipsta / viewfac;
243
244         left = -0.5f * (float)winx + shiftx * winside;
245         bottom = -0.5f * (ycor) * (float)winy + shifty * winside;
246         right =  0.5f * (float)winx + shiftx * winside;
247         top =  0.5f * (ycor) * (float)winy + shifty * winside;
248
249         left *= pixsize;
250         right *= pixsize;
251         bottom *= pixsize;
252         top *= pixsize;
253
254         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
255
256         camera = BKE_tracking_camera_get_reconstructed(tracking, object, framenr);
257
258         if (camera) {
259                 float imat[4][4];
260
261                 invert_m4_m4(imat, camera->mat);
262                 mult_m4_m4m4(mat, winmat, imat);
263         }
264         else copy_m4_m4(mat, winmat);
265 }
266
267 /* **** space transformation functions  **** */
268
269 /* Three coordinate frames: Frame, Search, and Marker
270  * Two units: Pixels, Unified
271  * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
272  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
273  * coordinates relative to the entire frame.
274  */
275 static void unified_to_pixel(int frame_width, int frame_height,
276                              const float unified_coords[2], float pixel_coords[2])
277 {
278         pixel_coords[0] = unified_coords[0] * frame_width;
279         pixel_coords[1] = unified_coords[1] * frame_height;
280 }
281
282 static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2],
283                                     float frame_unified_coords[2])
284 {
285         frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
286         frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
287 }
288
289 static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height,
290                                                       const MovieTrackingMarker *marker,
291                                                       const float marker_unified_coords[2],
292                                                       float frame_pixel_coords[2])
293 {
294         marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
295         unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
296 }
297
298 static void get_search_origin_frame_pixel(int frame_width, int frame_height,
299                                           const MovieTrackingMarker *marker, float frame_pixel[2])
300 {
301         /* Get the lower left coordinate of the search window and snap to pixel coordinates */
302         marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel);
303         frame_pixel[0] = (int)frame_pixel[0];
304         frame_pixel[1] = (int)frame_pixel[1];
305 }
306
307 #ifdef WITH_LIBMV
308 static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
309 {
310         unified_coords[0] = pixel_coords[0] / frame_width;
311         unified_coords[1] = pixel_coords[1] / frame_height;
312 }
313
314 static void marker_unified_to_search_pixel(int frame_width, int frame_height,
315                                            const MovieTrackingMarker *marker,
316                                            const float marker_unified[2], float search_pixel[2])
317 {
318         float frame_pixel[2];
319         float search_origin_frame_pixel[2];
320
321         marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel);
322         get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
323         sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
324 }
325
326 static void search_pixel_to_marker_unified(int frame_width, int frame_height,
327                                            const MovieTrackingMarker *marker,
328                                            const float search_pixel[2], float marker_unified[2])
329 {
330         float frame_unified[2];
331         float search_origin_frame_pixel[2];
332
333         get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
334         add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
335         pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
336
337         /* marker pos is in frame unified */
338         sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
339 }
340
341 /* Each marker has 5 coordinates associated with it that get warped with
342  * tracking: the four corners ("pattern_corners"), and the center ("pos").
343  * This function puts those 5 points into the appropriate frame for tracking
344  * (the "search" coordinate frame).
345  */
346 static void get_marker_coords_for_tracking(int frame_width, int frame_height,
347                                            const MovieTrackingMarker *marker,
348                                            double search_pixel_x[5], double search_pixel_y[5])
349 {
350         int i;
351         float unified_coords[2];
352         float pixel_coords[2];
353
354         /* Convert the corners into search space coordinates. */
355         for (i = 0; i < 4; i++) {
356                 marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
357                 search_pixel_x[i] = pixel_coords[0];
358                 search_pixel_y[i] = pixel_coords[1];
359         }
360
361         /* Convert the center position (aka "pos"); this is the origin */
362         unified_coords[0] = 0.0;
363         unified_coords[1] = 0.0;
364         marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
365
366         search_pixel_x[4] = pixel_coords[0];
367         search_pixel_y[4] = pixel_coords[1];
368 }
369
370 /* Inverse of above. */
371 static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker,
372                                             const double search_pixel_x[5], const double search_pixel_y[5])
373 {
374         int i;
375         float marker_unified[2];
376         float search_pixel[2];
377
378         /* Convert the corners into search space coordinates. */
379         for (i = 0; i < 4; i++) {
380                 search_pixel[0] = search_pixel_x[i];
381                 search_pixel[1] = search_pixel_y[i];
382                 search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
383         }
384
385         /* Convert the center position (aka "pos"); this is the origin */
386         search_pixel[0] = search_pixel_x[4];
387         search_pixel[1] = search_pixel_y[4];
388         search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
389
390         /* If the tracker tracked nothing, then "marker_unified" would be zero.
391          * Otherwise, the entire patch shifted, and that delta should be applied to
392          * all the coordinates.
393          */
394         for (i = 0; i < 4; i++) {
395                 marker->pattern_corners[i][0] -= marker_unified[0];
396                 marker->pattern_corners[i][1] -= marker_unified[1];
397         }
398
399         marker->pos[0] += marker_unified[0];
400         marker->pos[1] += marker_unified[1];
401 }
402 #endif
403
404 /*********************** clipboard *************************/
405
406 void BKE_tracking_clipboard_free(void)
407 {
408         MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
409
410         while (track) {
411                 next_track = track->next;
412
413                 BKE_tracking_track_free(track);
414                 MEM_freeN(track);
415
416                 track = next_track;
417         }
418
419         tracking_clipboard.tracks.first = tracking_clipboard.tracks.last = NULL;
420 }
421
422 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
423 {
424         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
425         MovieTrackingTrack *track = tracksbase->first;
426
427         BKE_tracking_clipboard_free();
428
429         while (track) {
430                 if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) {
431                         MovieTrackingTrack *new_track = tracking_track_duplicate(track);
432
433                         BLI_addtail(&tracking_clipboard.tracks, new_track);
434                 }
435
436                 track = track->next;
437         }
438 }
439
440 int BKE_tracking_clipboard_has_tracks(void)
441 {
442         return tracking_clipboard.tracks.first != NULL;
443 }
444
445 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
446 {
447         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
448         MovieTrackingTrack *track = tracking_clipboard.tracks.first;
449
450         while (track) {
451                 MovieTrackingTrack *new_track = tracking_track_duplicate(track);
452
453                 BLI_addtail(tracksbase, new_track);
454                 BKE_tracking_track_unique_name(tracksbase, new_track);
455
456                 track = track->next;
457         }
458 }
459
460 /*********************** Tracks  *************************/
461
462 static void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker,
463                                             int before, int overwrite)
464 {
465         MovieTrackingMarker marker_new;
466
467         marker_new = *ref_marker;
468         marker_new.flag &= ~MARKER_TRACKED;
469         marker_new.flag |= MARKER_DISABLED;
470
471         if (before)
472                 marker_new.framenr--;
473         else
474                 marker_new.framenr++;
475
476         if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr))
477                 BKE_tracking_marker_insert(track, &marker_new);
478 }
479
480 MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
481                                            int framenr, int width, int height)
482 {
483         MovieTrackingTrack *track;
484         MovieTrackingMarker marker;
485         MovieTrackingSettings *settings = &tracking->settings;
486
487         float half_pattern = (float)settings->default_pattern_size / 2.0f;
488         float half_search = (float)settings->default_search_size / 2.0f;
489         float pat[2], search[2];
490
491         pat[0] = half_pattern / (float)width;
492         pat[1] = half_pattern / (float)height;
493
494         search[0] = half_search / (float)width;
495         search[1] = half_search / (float)height;
496
497         track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
498         strcpy(track->name, "Track");
499
500         /* fill track's settings from default settings */
501         track->motion_model = settings->default_motion_model;
502         track->minimum_correlation = settings->default_minimum_correlation;
503         track->margin = settings->default_margin;
504         track->pattern_match = settings->default_pattern_match;
505         track->frames_limit = settings->default_frames_limit;
506         track->flag = settings->default_flag;
507         track->algorithm_flag = settings->default_algorithm_flag;
508
509         memset(&marker, 0, sizeof(marker));
510         marker.pos[0] = x;
511         marker.pos[1] = y;
512         marker.framenr = framenr;
513
514         marker.pattern_corners[0][0] = -pat[0];
515         marker.pattern_corners[0][1] = -pat[1];
516
517         marker.pattern_corners[1][0] = pat[0];
518         marker.pattern_corners[1][1] = -pat[1];
519
520         negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]);
521         negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]);
522
523         copy_v2_v2(marker.search_max, search);
524         negate_v2_v2(marker.search_min, search);
525
526         BKE_tracking_marker_insert(track, &marker);
527
528         BLI_addtail(tracksbase, track);
529         BKE_tracking_track_unique_name(tracksbase, track);
530
531         return track;
532 }
533
534 void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
535 {
536         BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
537 }
538
539 void BKE_tracking_track_free(MovieTrackingTrack *track)
540 {
541         if (track->markers)
542                 MEM_freeN(track->markers);
543 }
544
545 void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag)
546 {
547         if (area == TRACK_AREA_NONE)
548                 return;
549
550         if (area & TRACK_AREA_POINT)
551                 track->flag |= flag;
552         if (area & TRACK_AREA_PAT)
553                 track->pat_flag |= flag;
554         if (area & TRACK_AREA_SEARCH)
555                 track->search_flag |= flag;
556 }
557
558 void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag)
559 {
560         if (area == TRACK_AREA_NONE)
561                 return;
562
563         if (area & TRACK_AREA_POINT)
564                 track->flag &= ~flag;
565         if (area & TRACK_AREA_PAT)
566                 track->pat_flag &= ~flag;
567         if (area & TRACK_AREA_SEARCH)
568                 track->search_flag &= ~flag;
569 }
570
571 int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
572 {
573         return BKE_tracking_marker_get_exact(track, framenr) != 0;
574 }
575
576 int BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
577 {
578         MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
579
580         return marker && (marker->flag & MARKER_DISABLED) == 0;
581 }
582
583 void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int action)
584 {
585         int a;
586
587         if (action == TRACK_CLEAR_REMAINED) {
588                 a = 1;
589
590                 while (a < track->markersnr) {
591                         if (track->markers[a].framenr > ref_frame) {
592                                 track->markersnr = a;
593                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
594
595                                 break;
596                         }
597
598                         a++;
599                 }
600
601                 if (track->markersnr)
602                         tracking_marker_insert_disabled(track, &track->markers[track->markersnr - 1], FALSE, TRUE);
603         }
604         else if (action == TRACK_CLEAR_UPTO) {
605                 a = track->markersnr - 1;
606
607                 while (a >= 0) {
608                         if (track->markers[a].framenr <= ref_frame) {
609                                 memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker));
610
611                                 track->markersnr = track->markersnr - a;
612                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
613
614                                 break;
615                         }
616
617                         a--;
618                 }
619
620                 if (track->markersnr)
621                         tracking_marker_insert_disabled(track, &track->markers[0], TRUE, TRUE);
622         }
623         else if (action == TRACK_CLEAR_ALL) {
624                 MovieTrackingMarker *marker, marker_new;
625
626                 marker = BKE_tracking_marker_get(track, ref_frame);
627                 marker_new = *marker;
628
629                 MEM_freeN(track->markers);
630                 track->markers = NULL;
631                 track->markersnr = 0;
632
633                 BKE_tracking_marker_insert(track, &marker_new);
634
635                 tracking_marker_insert_disabled(track, &marker_new, TRUE, TRUE);
636                 tracking_marker_insert_disabled(track, &marker_new, FALSE, TRUE);
637         }
638 }
639
640 void BKE_tracking_tracks_join(MovieTracking *tracking, MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
641 {
642         int i = 0, a = 0, b = 0, tot;
643         MovieTrackingMarker *markers;
644
645         tot = dst_track->markersnr + src_track->markersnr;
646         markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks");
647
648         while (a < src_track->markersnr || b < dst_track->markersnr) {
649                 if (b >= dst_track->markersnr) {
650                         markers[i] = src_track->markers[a++];
651                 }
652                 else if (a >= src_track->markersnr) {
653                         markers[i] = dst_track->markers[b++];
654                 }
655                 else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) {
656                         markers[i] = src_track->markers[a++];
657                 }
658                 else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) {
659                         markers[i] = dst_track->markers[b++];
660                 }
661                 else {
662                         if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) {
663                                 if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) {
664                                         /* both tracks are enabled on this frame, so find the whole segment
665                                          * on which tracks are intersecting and blend tracks using linear
666                                          * interpolation to prevent jumps
667                                          */
668
669                                         MovieTrackingMarker *marker_a, *marker_b;
670                                         int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
671                                         int j, inverse = 0;
672
673                                         inverse = (b == 0) ||
674                                                   (dst_track->markers[b - 1].flag & MARKER_DISABLED) ||
675                                                   (dst_track->markers[b - 1].framenr != frame - 1);
676
677                                         /* find length of intersection */
678                                         while (a < src_track->markersnr && b < dst_track->markersnr) {
679                                                 marker_a = &src_track->markers[a];
680                                                 marker_b = &dst_track->markers[b];
681
682                                                 if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED)
683                                                         break;
684
685                                                 if (marker_a->framenr != frame || marker_b->framenr != frame)
686                                                         break;
687
688                                                 frame++;
689                                                 len++;
690                                                 a++;
691                                                 b++;
692                                         }
693
694                                         a = start_a;
695                                         b = start_b;
696
697                                         /* linear interpolation for intersecting frames */
698                                         for (j = 0; j < len; j++) {
699                                                 float fac = 0.5f;
700
701                                                 if (len > 1)
702                                                         fac = 1.0f / (len - 1) * j;
703
704                                                 if (inverse)
705                                                         fac = 1.0f - fac;
706
707                                                 marker_a = &src_track->markers[a];
708                                                 marker_b = &dst_track->markers[b];
709
710                                                 markers[i] = dst_track->markers[b];
711                                                 interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac);
712                                                 a++;
713                                                 b++;
714                                                 i++;
715                                         }
716
717                                         /* this values will be incremented at the end of the loop cycle */
718                                         a--; b--; i--;
719                                 }
720                                 else {
721                                         markers[i] = src_track->markers[a];
722                                 }
723                         }
724                         else {
725                                 markers[i] = dst_track->markers[b];
726                         }
727
728                         a++;
729                         b++;
730                 }
731
732                 i++;
733         }
734
735         MEM_freeN(dst_track->markers);
736
737         dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks");
738         memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker));
739
740         dst_track->markersnr = i;
741
742         MEM_freeN(markers);
743
744         BKE_tracking_dopesheet_tag_update(tracking);
745 }
746
747 MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
748 {
749         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
750         MovieTrackingTrack *track = tracksbase->first;
751
752         while (track) {
753                 if (!strcmp(track->name, name))
754                         return track;
755
756                 track = track->next;
757         }
758
759         return NULL;
760 }
761
762 MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
763 {
764         MovieTrackingObject *object;
765         int cur = 1;
766
767         object = tracking->objects.first;
768         while (object) {
769                 ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
770                 MovieTrackingTrack *track = tracksbase->first;
771
772                 while (track) {
773                         if (track->flag & TRACK_HAS_BUNDLE) {
774                                 if (cur == tracknr) {
775                                         *tracksbase_r = tracksbase;
776                                         return track;
777                                 }
778
779                                 cur++;
780                         }
781
782                         track = track->next;
783                 }
784
785                 object = object->next;
786         }
787
788         *tracksbase_r = NULL;
789
790         return NULL;
791 }
792
793 MovieTrackingTrack *BKE_tracking_track_get_active(MovieTracking *tracking)
794 {
795         ListBase *tracksbase;
796
797         if (!tracking->act_track)
798                 return NULL;
799
800         tracksbase = BKE_tracking_get_active_tracks(tracking);
801
802         /* check that active track is in current tracks list */
803         if (BLI_findindex(tracksbase, tracking->act_track) >= 0)
804                 return tracking->act_track;
805
806         return NULL;
807 }
808
809 static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track)
810 {
811         bGPDlayer *layer;
812
813         if (!track->gpd)
814                 return NULL;
815
816         layer = track->gpd->layers.first;
817
818         while (layer) {
819                 if (layer->flag & GP_LAYER_ACTIVE) {
820                         bGPDframe *frame = layer->frames.first;
821                         int ok = FALSE;
822
823                         while (frame) {
824                                 if (frame->strokes.first) {
825                                         ok = TRUE;
826                                 }
827
828                                 frame = frame->next;
829                         }
830
831                         if (ok)
832                                 return layer;
833                 }
834
835                 layer = layer->next;
836         }
837
838         return NULL;
839 }
840
841 static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height,
842                                                MovieTrackingMarker *marker, bGPDlayer *layer,
843                                                float *mask, int mask_width, int mask_height)
844 {
845         bGPDframe *frame = layer->frames.first;
846
847         while (frame) {
848                 bGPDstroke *stroke = frame->strokes.first;
849
850                 while (stroke) {
851                         bGPDspoint *stroke_points = stroke->points;
852                         float *mask_points, *fp;
853                         int i;
854
855                         if (stroke->flag & GP_STROKE_2DSPACE) {
856                                 fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float),
857                                                                "track mask rasterization points");
858
859                                 for (i = 0; i < stroke->totpoints; i++, fp += 2) {
860                                         fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width;
861                                         fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height;
862                                 }
863
864                                 /* TODO: add an option to control whether AA is enabled or not */
865                                 PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height);
866
867                                 MEM_freeN(mask_points);
868                         }
869
870                         stroke = stroke->next;
871                 }
872
873                 frame = frame->next;
874         }
875 }
876
877 float *BKE_tracking_track_get_mask(int frame_width, int frame_height,
878                                    MovieTrackingTrack *track, MovieTrackingMarker *marker)
879 {
880         float *mask = NULL;
881         bGPDlayer *layer = track_mask_gpencil_layer_get(track);
882         int mask_width, mask_height;
883
884         mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width;
885         mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height;
886
887         if (layer) {
888                 mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask");
889
890                 track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer,
891                                                    mask, mask_width, mask_height);
892         }
893
894         return mask;
895 }
896
897 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
898 void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
899 {
900         if (extend) {
901                 BKE_tracking_track_flag_set(track, area, SELECT);
902         }
903         else {
904                 MovieTrackingTrack *cur = tracksbase->first;
905
906                 while (cur) {
907                         if ((cur->flag & TRACK_HIDDEN) == 0) {
908                                 if (cur == track) {
909                                         BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT);
910                                         BKE_tracking_track_flag_set(cur, area, SELECT);
911                                 }
912                                 else {
913                                         BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT);
914                                 }
915                         }
916
917                         cur = cur->next;
918                 }
919         }
920 }
921
922 void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
923 {
924         BKE_tracking_track_flag_clear(track, area, SELECT);
925 }
926
927 /*********************** Marker *************************/
928
929 MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
930 {
931         MovieTrackingMarker *old_marker = NULL;
932
933         if (track->markersnr)
934                 old_marker = BKE_tracking_marker_get_exact(track, marker->framenr);
935
936         if (old_marker) {
937                 /* simply replace settings for already allocated marker */
938                 *old_marker = *marker;
939
940                 return old_marker;
941         }
942         else {
943                 int a = track->markersnr;
944
945                 /* find position in array where to add new marker */
946                 while (a--) {
947                         if (track->markers[a].framenr < marker->framenr)
948                                 break;
949                 }
950
951                 track->markersnr++;
952
953                 if (track->markers)
954                         track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
955                 else
956                         track->markers = MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
957
958                 /* shift array to "free" space for new marker */
959                 memmove(track->markers + a + 2, track->markers + a + 1,
960                         (track->markersnr - a - 2) * sizeof(MovieTrackingMarker));
961
962                 /* put new marker */
963                 track->markers[a + 1] = *marker;
964
965                 track->last_marker = a + 1;
966
967                 return &track->markers[a + 1];
968         }
969 }
970
971 void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr)
972 {
973         int a = 0;
974
975         while (a < track->markersnr) {
976                 if (track->markers[a].framenr == framenr) {
977                         if (track->markersnr > 1) {
978                                 memmove(track->markers + a, track->markers + a + 1,
979                                         (track->markersnr - a - 1) * sizeof(MovieTrackingMarker));
980                                 track->markersnr--;
981                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
982                         }
983                         else {
984                                 MEM_freeN(track->markers);
985                                 track->markers = NULL;
986                                 track->markersnr = 0;
987                         }
988
989                         break;
990                 }
991
992                 a++;
993         }
994 }
995
996 void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
997 {
998         int a;
999         float pat_min[2], pat_max[2];
1000
1001         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1002
1003         if (event == CLAMP_PAT_DIM) {
1004                 for (a = 0; a < 2; a++) {
1005                         /* search shouldn't be resized smaller than pattern */
1006                         marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
1007                         marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
1008                 }
1009         }
1010         else if (event == CLAMP_PAT_POS) {
1011                 float dim[2];
1012
1013                 sub_v2_v2v2(dim, pat_max, pat_min);
1014
1015                 for (a = 0; a < 2; a++) {
1016                         int b;
1017                         /* pattern shouldn't be moved outside of search */
1018                         if (pat_min[a] < marker->search_min[a]) {
1019                                 for (b = 0; b < 4; b++)
1020                                         marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a];
1021                         }
1022                         if (pat_max[a] > marker->search_max[a]) {
1023                                 for (b = 0; b < 4; b++)
1024                                         marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a];
1025                         }
1026                 }
1027         }
1028         else if (event == CLAMP_SEARCH_DIM) {
1029                 for (a = 0; a < 2; a++) {
1030                         /* search shouldn't be resized smaller than pattern */
1031                         marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
1032                         marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
1033                 }
1034         }
1035         else if (event == CLAMP_SEARCH_POS) {
1036                 float dim[2];
1037
1038                 sub_v2_v2v2(dim, marker->search_max, marker->search_min);
1039
1040                 for (a = 0; a < 2; a++) {
1041                         /* search shouldn't be moved inside pattern */
1042                         if (marker->search_min[a] > pat_min[a]) {
1043                                 marker->search_min[a] = pat_min[a];
1044                                 marker->search_max[a] = marker->search_min[a] + dim[a];
1045                         }
1046                         if (marker->search_max[a] < pat_max[a]) {
1047                                 marker->search_max[a] = pat_max[a];
1048                                 marker->search_min[a] = marker->search_max[a] - dim[a];
1049                         }
1050                 }
1051         }
1052 }
1053
1054 MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
1055 {
1056         int a = track->markersnr - 1;
1057
1058         if (!track->markersnr)
1059                 return NULL;
1060
1061         /* approximate pre-first framenr marker with first marker */
1062         if (framenr < track->markers[0].framenr)
1063                 return &track->markers[0];
1064
1065         if (track->last_marker < track->markersnr)
1066                 a = track->last_marker;
1067
1068         if (track->markers[a].framenr <= framenr) {
1069                 while (a < track->markersnr && track->markers[a].framenr <= framenr) {
1070                         if (track->markers[a].framenr == framenr) {
1071                                 track->last_marker = a;
1072
1073                                 return &track->markers[a];
1074                         }
1075                         a++;
1076                 }
1077
1078                 /* if there's no marker for exact position, use nearest marker from left side */
1079                 return &track->markers[a - 1];
1080         }
1081         else {
1082                 while (a >= 0 && track->markers[a].framenr >= framenr) {
1083                         if (track->markers[a].framenr == framenr) {
1084                                 track->last_marker = a;
1085
1086                                 return &track->markers[a];
1087                         }
1088
1089                         a--;
1090                 }
1091
1092                 /* if there's no marker for exact position, use nearest marker from left side */
1093                 return &track->markers[a];
1094         }
1095
1096         return NULL;
1097 }
1098
1099 MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr)
1100 {
1101         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1102
1103         if (marker->framenr != framenr)
1104                 return NULL;
1105
1106         return marker;
1107 }
1108
1109 MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int framenr)
1110 {
1111         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1112
1113         if (marker->framenr != framenr) {
1114                 MovieTrackingMarker marker_new;
1115
1116                 marker_new = *marker;
1117                 marker_new.framenr = framenr;
1118
1119                 BKE_tracking_marker_insert(track, &marker_new);
1120                 marker = BKE_tracking_marker_get(track, framenr);
1121         }
1122
1123         return marker;
1124 }
1125
1126 void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2])
1127 {
1128         INIT_MINMAX2(min, max);
1129
1130         minmax_v2v2_v2(min, max, marker->pattern_corners[0]);
1131         minmax_v2v2_v2(min, max, marker->pattern_corners[1]);
1132         minmax_v2v2_v2(min, max, marker->pattern_corners[2]);
1133         minmax_v2v2_v2(min, max, marker->pattern_corners[3]);
1134 }
1135
1136 void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2])
1137 {
1138         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, (int) framenr);
1139         MovieTrackingMarker *marker_last = track->markers + (track->markersnr - 1);
1140
1141         if (marker != marker_last) {
1142                 MovieTrackingMarker *marker_next = marker + 1;
1143
1144                 if (marker_next->framenr == marker->framenr + 1) {
1145                         /* currently only do subframing inside tracked ranges, do not extrapolate tracked segments
1146                          * could be changed when / if mask parent would be interpolating position in-between
1147                          * tracked segments
1148                          */
1149
1150                         float fac = (framenr - (int) framenr) / (marker_next->framenr - marker->framenr);
1151
1152                         interp_v2_v2v2(pos, marker->pos, marker_next->pos, fac);
1153                 }
1154                 else {
1155                         copy_v2_v2(pos, marker->pos);
1156                 }
1157         }
1158         else {
1159                 copy_v2_v2(pos, marker->pos);
1160         }
1161
1162         /* currently track offset is always wanted to be applied here, could be made an option later */
1163         add_v2_v2(pos, track->offset);
1164 }
1165
1166 /*********************** Object *************************/
1167
1168 MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
1169 {
1170         MovieTrackingObject *object = MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
1171
1172         if (tracking->tot_object == 0) {
1173                 /* first object is always camera */
1174                 BLI_strncpy(object->name, "Camera", sizeof(object->name));
1175
1176                 object->flag |= TRACKING_OBJECT_CAMERA;
1177         }
1178         else {
1179                 BLI_strncpy(object->name, name, sizeof(object->name));
1180         }
1181
1182         BLI_addtail(&tracking->objects, object);
1183
1184         tracking->tot_object++;
1185         tracking->objectnr = BLI_countlist(&tracking->objects) - 1;
1186
1187         object->scale = 1.0f;
1188         object->keyframe1 = 1;
1189         object->keyframe2 = 30;
1190
1191         BKE_tracking_object_unique_name(tracking, object);
1192
1193         return object;
1194 }
1195
1196 int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object)
1197 {
1198         MovieTrackingTrack *track;
1199         int index = BLI_findindex(&tracking->objects, object);
1200
1201         if (index == -1)
1202                 return FALSE;
1203
1204         if (object->flag & TRACKING_OBJECT_CAMERA) {
1205                 /* object used for camera solving can't be deleted */
1206                 return FALSE;
1207         }
1208
1209         track = object->tracks.first;
1210         while (track) {
1211                 if (track == tracking->act_track)
1212                         tracking->act_track = NULL;
1213
1214                 track = track->next;
1215         }
1216
1217         tracking_object_free(object);
1218         BLI_freelinkN(&tracking->objects, object);
1219
1220         tracking->tot_object--;
1221
1222         if (index != 0)
1223                 tracking->objectnr = index - 1;
1224         else
1225                 tracking->objectnr = 0;
1226         return TRUE;
1227 }
1228
1229 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
1230 {
1231         BLI_uniquename(&tracking->objects, object, "Object", '.',
1232                        offsetof(MovieTrackingObject, name), sizeof(object->name));
1233 }
1234
1235 MovieTrackingObject *BKE_tracking_object_get_named(MovieTracking *tracking, const char *name)
1236 {
1237         MovieTrackingObject *object = tracking->objects.first;
1238
1239         while (object) {
1240                 if (!strcmp(object->name, name))
1241                         return object;
1242
1243                 object = object->next;
1244         }
1245
1246         return NULL;
1247 }
1248
1249 MovieTrackingObject *BKE_tracking_object_get_active(MovieTracking *tracking)
1250 {
1251         return BLI_findlink(&tracking->objects, tracking->objectnr);
1252 }
1253
1254 MovieTrackingObject *BKE_tracking_object_get_camera(MovieTracking *tracking)
1255 {
1256         MovieTrackingObject *object = tracking->objects.first;
1257
1258         while (object) {
1259                 if (object->flag & TRACKING_OBJECT_CAMERA)
1260                         return object;
1261
1262                 object = object->next;
1263         }
1264
1265         return NULL;
1266 }
1267
1268 ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingObject *object)
1269 {
1270         if (object->flag & TRACKING_OBJECT_CAMERA) {
1271                 return &tracking->tracks;
1272         }
1273
1274         return &object->tracks;
1275 }
1276
1277 MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking,
1278                                                                     MovieTrackingObject *object)
1279 {
1280         if (object->flag & TRACKING_OBJECT_CAMERA) {
1281                 return &tracking->reconstruction;
1282         }
1283
1284         return &object->reconstruction;
1285 }
1286
1287 /*********************** Camera *************************/
1288
1289 static int reconstructed_camera_index_get(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
1290 {
1291         MovieReconstructedCamera *cameras = reconstruction->cameras;
1292         int a = 0, d = 1;
1293
1294         if (!reconstruction->camnr)
1295                 return -1;
1296
1297         if (framenr < cameras[0].framenr) {
1298                 if (nearest)
1299                         return 0;
1300                 else
1301                         return -1;
1302         }
1303
1304         if (framenr > cameras[reconstruction->camnr - 1].framenr) {
1305                 if (nearest)
1306                         return reconstruction->camnr - 1;
1307                 else
1308                         return -1;
1309         }
1310
1311         if (reconstruction->last_camera < reconstruction->camnr)
1312                 a = reconstruction->last_camera;
1313
1314         if (cameras[a].framenr >= framenr)
1315                 d = -1;
1316
1317         while (a >= 0 && a < reconstruction->camnr) {
1318                 int cfra = cameras[a].framenr;
1319
1320                 /* check if needed framenr was "skipped" -- no data for requested frame */
1321
1322                 if (d > 0 && cfra > framenr) {
1323                         /* interpolate with previous position */
1324                         if (nearest)
1325                                 return a - 1;
1326                         else
1327                                 break;
1328                 }
1329
1330                 if (d < 0 && cfra < framenr) {
1331                         /* interpolate with next position */
1332                         if (nearest)
1333                                 return a;
1334                         else
1335                                 break;
1336                 }
1337
1338                 if (cfra == framenr) {
1339                         reconstruction->last_camera = a;
1340
1341                         return a;
1342                 }
1343
1344                 a += d;
1345         }
1346
1347         return -1;
1348 }
1349
1350 static void reconstructed_camera_scale_set(MovieTrackingObject *object, float mat[4][4])
1351 {
1352         if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) {
1353                 float smat[4][4];
1354
1355                 scale_m4_fl(smat, 1.0f / object->scale);
1356                 mult_m4_m4m4(mat, mat, smat);
1357         }
1358 }
1359
1360
1361 /* converts principal offset from center to offset of blender's camera */
1362 void BKE_tracking_camera_shift_get(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
1363 {
1364         /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */
1365         *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx;
1366         *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx;
1367 }
1368
1369 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
1370 {
1371         float focal = tracking->camera.focal;
1372
1373         camera->sensor_x = tracking->camera.sensor_width;
1374         camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
1375         camera->lens = focal * camera->sensor_x / width;
1376
1377         scene->r.xsch = width * tracking->camera.pixel_aspect;
1378         scene->r.ysch = height;
1379
1380         scene->r.xasp = 1.0f;
1381         scene->r.yasp = 1.0f;
1382
1383         BKE_tracking_camera_shift_get(tracking, width, height, &camera->shiftx, &camera->shifty);
1384 }
1385
1386 MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(MovieTracking *tracking,
1387                                                                 MovieTrackingObject *object, int framenr)
1388 {
1389         MovieTrackingReconstruction *reconstruction;
1390         int a;
1391
1392         reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
1393         a = reconstructed_camera_index_get(reconstruction, framenr, FALSE);
1394
1395         if (a == -1)
1396                 return NULL;
1397
1398         return &reconstruction->cameras[a];
1399 }
1400
1401 void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, MovieTrackingObject *object,
1402                                                        int framenr, float mat[4][4])
1403 {
1404         MovieTrackingReconstruction *reconstruction;
1405         MovieReconstructedCamera *cameras;
1406         int a;
1407
1408         reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
1409         cameras = reconstruction->cameras;
1410         a = reconstructed_camera_index_get(reconstruction, framenr, 1);
1411
1412         if (a == -1) {
1413                 unit_m4(mat);
1414
1415                 return;
1416         }
1417
1418         if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) {
1419                 float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr);
1420
1421                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);
1422         }
1423         else {
1424                 copy_m4_m4(mat, cameras[a].mat);
1425         }
1426
1427         reconstructed_camera_scale_set(object, mat);
1428 }
1429
1430 /*********************** Distortion/Undistortion *************************/
1431
1432 #ifdef WITH_LIBMV
1433 static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
1434                                                 MovieTracking *tracking, int calibration_width, int calibration_height)
1435 {
1436         MovieTrackingCamera *camera = &tracking->camera;
1437         float aspy = 1.0f / tracking->camera.pixel_aspect;
1438
1439         camera_intrinsics_options->focal_length = camera->focal;
1440
1441         camera_intrinsics_options->principal_point_x = camera->principal[0];
1442         camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
1443
1444         camera_intrinsics_options->k1 = camera->k1;
1445         camera_intrinsics_options->k2 = camera->k2;
1446         camera_intrinsics_options->k3 = camera->k3;
1447
1448         camera_intrinsics_options->image_width = calibration_width;
1449         camera_intrinsics_options->image_height = (double) calibration_height * aspy;
1450 }
1451 #endif
1452
1453 MovieDistortion *BKE_tracking_distortion_new(void)
1454 {
1455         MovieDistortion *distortion;
1456
1457         distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
1458
1459         return distortion;
1460 }
1461
1462 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
1463                                     int calibration_width, int calibration_height)
1464 {
1465 #ifdef WITH_LIBMV
1466         libmv_cameraIntrinsicsOptions camera_intrinsics_options;
1467
1468         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
1469                                             calibration_width, calibration_height);
1470
1471         if (!distortion->intrinsics) {
1472                 distortion->intrinsics = libmv_CameraIntrinsicsNew(&camera_intrinsics_options);
1473         }
1474         else {
1475                 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options);
1476         }
1477 #else
1478         (void) distortion;
1479         (void) calibration_width;
1480         (void) calibration_height;
1481         (void) camera;
1482         (void) aspy;
1483 #endif
1484 }
1485
1486 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
1487 {
1488         MovieDistortion *new_distortion;
1489
1490         new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
1491
1492 #ifdef WITH_LIBMV
1493         new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics);
1494 #else
1495         (void) distortion;
1496 #endif
1497
1498         return new_distortion;
1499 }
1500
1501 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf,
1502                                     int calibration_width, int calibration_height, float overscan, int undistort)
1503 {
1504         ImBuf *resibuf;
1505
1506         BKE_tracking_distortion_update(distortion, tracking, calibration_width, calibration_height);
1507
1508         resibuf = IMB_dupImBuf(ibuf);
1509
1510 #ifdef WITH_LIBMV
1511         if (ibuf->rect_float) {
1512                 if (undistort) {
1513                         libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
1514                                                              ibuf->rect_float, resibuf->rect_float,
1515                                                              ibuf->x, ibuf->y, overscan, ibuf->channels);
1516                 }
1517                 else {
1518                         libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
1519                                                            ibuf->rect_float, resibuf->rect_float,
1520                                                            ibuf->x, ibuf->y, overscan, ibuf->channels);
1521                 }
1522
1523                 if (ibuf->rect)
1524                         imb_freerectImBuf(ibuf);
1525         }
1526         else {
1527                 if (undistort) {
1528                         libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
1529                                                             (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
1530                                                             ibuf->x, ibuf->y, overscan, ibuf->channels);
1531                 }
1532                 else {
1533                         libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
1534                                                           (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
1535                                                           ibuf->x, ibuf->y, overscan, ibuf->channels);
1536                 }
1537         }
1538 #else
1539         (void) overscan;
1540         (void) undistort;
1541
1542         if (ibuf->rect_float && ibuf->rect)
1543                 imb_freerectImBuf(ibuf);
1544 #endif
1545
1546         return resibuf;
1547 }
1548
1549 void BKE_tracking_distortion_free(MovieDistortion *distortion)
1550 {
1551 #ifdef WITH_LIBMV
1552         libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
1553 #endif
1554
1555         MEM_freeN(distortion);
1556 }
1557
1558 void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
1559 {
1560         MovieTrackingCamera *camera = &tracking->camera;
1561
1562 #ifdef WITH_LIBMV
1563         libmv_cameraIntrinsicsOptions camera_intrinsics_options;
1564         double x, y;
1565         float aspy = 1.0f / tracking->camera.pixel_aspect;
1566
1567         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
1568
1569         /* normalize coords */
1570         x = (co[0] - camera->principal[0]) / camera->focal;
1571         y = (co[1] - camera->principal[1] * aspy) / camera->focal;
1572
1573         libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
1574
1575         /* result is in image coords already */
1576         r_co[0] = x;
1577         r_co[1] = y;
1578 #else
1579         (void) camera;
1580         (void) co;
1581         zero_v2(r_co);
1582 #endif
1583 }
1584
1585 void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
1586 {
1587         MovieTrackingCamera *camera = &tracking->camera;
1588
1589 #ifdef WITH_LIBMV
1590         libmv_cameraIntrinsicsOptions camera_intrinsics_options;
1591         double x = co[0], y = co[1];
1592         float aspy = 1.0f / tracking->camera.pixel_aspect;
1593
1594         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
1595
1596         libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
1597
1598         r_co[0] = x * camera->focal + camera->principal[0];
1599         r_co[1] = y * camera->focal + camera->principal[1] * aspy;
1600 #else
1601         (void) camera;
1602         (void) co;
1603         zero_v2(r_co);
1604 #endif
1605 }
1606
1607 ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width,
1608                                     int calibration_height, float overscan)
1609 {
1610         MovieTrackingCamera *camera = &tracking->camera;
1611
1612         if (camera->intrinsics == NULL)
1613                 camera->intrinsics = BKE_tracking_distortion_new();
1614
1615         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
1616                                             calibration_height, overscan, TRUE);
1617 }
1618
1619 ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width,
1620                                   int calibration_height, float overscan)
1621 {
1622         MovieTrackingCamera *camera = &tracking->camera;
1623
1624         if (camera->intrinsics == NULL)
1625                 camera->intrinsics = BKE_tracking_distortion_new();
1626
1627         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
1628                                             calibration_height, overscan, FALSE);
1629 }
1630
1631 void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
1632 {
1633         int a;
1634         float pos[2], warped_pos[2];
1635         const int coord_delta = 5;
1636
1637         delta[0] = delta[1] = -FLT_MAX;
1638
1639         for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
1640                 if (a > rect->xmax)
1641                         a = rect->xmax;
1642
1643                 /* bottom edge */
1644                 pos[0] = a;
1645                 pos[1] = rect->ymin;
1646
1647                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
1648
1649                 delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
1650                 delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
1651
1652                 /* top edge */
1653                 pos[0] = a;
1654                 pos[1] = rect->ymax;
1655
1656                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
1657
1658                 delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
1659                 delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
1660
1661                 if (a >= rect->xmax)
1662                         break;
1663         }
1664
1665         for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
1666                 if (a > rect->ymax)
1667                         a = rect->ymax;
1668
1669                 /* left edge */
1670                 pos[0] = rect->xmin;
1671                 pos[1] = a;
1672
1673                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
1674
1675                 delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
1676                 delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
1677
1678                 /* right edge */
1679                 pos[0] = rect->xmax;
1680                 pos[1] = a;
1681
1682                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
1683
1684                 delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
1685                 delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
1686
1687                 if (a >= rect->ymax)
1688                         break;
1689         }
1690 }
1691
1692 /*********************** Image sampling *************************/
1693
1694 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
1695 {
1696         BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED,
1697                                       track->flag & TRACK_DISABLE_GREEN,
1698                                       track->flag & TRACK_DISABLE_BLUE, grayscale);
1699 }
1700
1701 ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf,
1702                                    MovieTrackingTrack *track, MovieTrackingMarker *marker,
1703                                    int use_mask, int num_samples_x, int num_samples_y,
1704                                    float pos[2])
1705 {
1706 #ifdef WITH_LIBMV
1707         ImBuf *pattern_ibuf;
1708         double src_pixel_x[5], src_pixel_y[5];
1709         double warped_position_x, warped_position_y;
1710         float *mask = NULL;
1711
1712         if (num_samples_x <= 0 || num_samples_y <= 0)
1713                 return NULL;
1714
1715         pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
1716
1717         if (!search_ibuf->rect_float) {
1718                 IMB_float_from_rect(search_ibuf);
1719         }
1720
1721         get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
1722
1723         if (use_mask) {
1724                 mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
1725         }
1726
1727         libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4,
1728                                 src_pixel_x, src_pixel_y, num_samples_x,
1729                                 num_samples_y, mask, pattern_ibuf->rect_float,
1730                                 &warped_position_x, &warped_position_y);
1731
1732         if (pos) {
1733                 pos[0] = warped_position_x;
1734                 pos[1] = warped_position_y;
1735         }
1736
1737         if (mask) {
1738                 MEM_freeN(mask);
1739         }
1740
1741         return pattern_ibuf;
1742 #else
1743         ImBuf *pattern_ibuf;
1744
1745         /* real sampling requires libmv, but areas are supposing pattern would be
1746          * sampled if search area does exists, so we'll need to create empty
1747          * pattern area here to prevent adding NULL-checks all over just to deal
1748          * with situation when libmv is disabled
1749          */
1750
1751         (void) frame_width;
1752         (void) frame_height;
1753         (void) search_ibuf;
1754         (void) marker;
1755         (void) track;
1756         (void) use_mask;
1757
1758         pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
1759
1760         pos[0] = num_samples_x / 2.0f;
1761         pos[1] = num_samples_y / 2.0f;
1762
1763         return pattern_ibuf;
1764 #endif
1765 }
1766
1767 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1768                                       int anchored, int disable_channels)
1769 {
1770         ImBuf *pattern_ibuf, *search_ibuf;
1771         float pat_min[2], pat_max[2];
1772         int num_samples_x, num_samples_y;
1773
1774         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1775
1776         num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x;
1777         num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y;
1778
1779         search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels);
1780
1781         if (search_ibuf) {
1782                 pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker,
1783                                                            FALSE, num_samples_x, num_samples_y, NULL);
1784
1785                 IMB_freeImBuf(search_ibuf);
1786         }
1787         else {
1788                 pattern_ibuf = NULL;
1789         }
1790
1791         return pattern_ibuf;
1792 }
1793
1794 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1795                                      int anchored, int disable_channels)
1796 {
1797         ImBuf *searchibuf;
1798         int x, y, w, h;
1799         float search_origin[2];
1800
1801         get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin);
1802
1803         x = search_origin[0];
1804         y = search_origin[1];
1805
1806         if (anchored) {
1807                 x += track->offset[0] * ibuf->x;
1808                 y += track->offset[1] * ibuf->y;
1809         }
1810
1811         w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x;
1812         h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
1813
1814         if (w <= 0 || h <= 0)
1815                 return NULL;
1816
1817         searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
1818
1819         IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
1820
1821         if (disable_channels) {
1822                 if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
1823                     (track->flag & TRACK_DISABLE_RED)       ||
1824                     (track->flag & TRACK_DISABLE_GREEN)     ||
1825                     (track->flag & TRACK_DISABLE_BLUE))
1826                 {
1827                         disable_imbuf_channels(searchibuf, track, TRUE);
1828                 }
1829         }
1830
1831         return searchibuf;
1832 }
1833
1834 /* zap channels from the imbuf that are disabled by the user. this can lead to
1835  * better tracks sometimes. however, instead of simply zeroing the channels
1836  * out, do a partial grayscale conversion so the display is better.
1837  */
1838 void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue,
1839                                    int grayscale)
1840 {
1841         int x, y;
1842         float scale;
1843
1844         if (!disable_red && !disable_green && !disable_blue && !grayscale)
1845                 return;
1846
1847         /* if only some components are selected, it's important to rescale the result
1848          * appropriately so that e.g. if only blue is selected, it's not zeroed out.
1849          */
1850         scale = (disable_red   ? 0.0f : 0.2126f) +
1851                 (disable_green ? 0.0f : 0.7152f) +
1852                 (disable_blue  ? 0.0f : 0.0722f);
1853
1854         for (y = 0; y < ibuf->y; y++) {
1855                 for (x = 0; x < ibuf->x; x++) {
1856                         int pixel = ibuf->x * y + x;
1857
1858                         if (ibuf->rect_float) {
1859                                 float *rrgbf = ibuf->rect_float + pixel * 4;
1860                                 float r = disable_red   ? 0.0f : rrgbf[0];
1861                                 float g = disable_green ? 0.0f : rrgbf[1];
1862                                 float b = disable_blue  ? 0.0f : rrgbf[2];
1863
1864                                 if (grayscale) {
1865                                         float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
1866
1867                                         rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
1868                                 }
1869                                 else {
1870                                         rrgbf[0] = r;
1871                                         rrgbf[1] = g;
1872                                         rrgbf[2] = b;
1873                                 }
1874                         }
1875                         else {
1876                                 char *rrgb = (char *)ibuf->rect + pixel * 4;
1877                                 char r = disable_red   ? 0 : rrgb[0];
1878                                 char g = disable_green ? 0 : rrgb[1];
1879                                 char b = disable_blue  ? 0 : rrgb[2];
1880
1881                                 if (grayscale) {
1882                                         float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
1883
1884                                         rrgb[0] = rrgb[1] = rrgb[2] = gray;
1885                                 }
1886                                 else {
1887                                         rrgb[0] = r;
1888                                         rrgb[1] = g;
1889                                         rrgb[2] = b;
1890                                 }
1891                         }
1892                 }
1893         }
1894
1895         if (ibuf->rect_float)
1896                 ibuf->userflags |= IB_RECT_INVALID;
1897 }
1898
1899 /*********************** Tracks map *************************/
1900
1901 typedef struct TracksMap {
1902         char object_name[MAX_NAME];
1903         int is_camera;
1904
1905         int num_tracks;
1906         int customdata_size;
1907
1908         char *customdata;
1909         MovieTrackingTrack *tracks;
1910
1911         GHash *hash;
1912
1913         int ptr;
1914 } TracksMap;
1915
1916 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
1917 {
1918         TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
1919
1920         BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
1921         map->is_camera = is_camera;
1922
1923         map->num_tracks = num_tracks;
1924         map->customdata_size = customdata_size;
1925
1926         map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
1927
1928         if (customdata_size)
1929                 map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
1930
1931         map->hash = BLI_ghash_ptr_new("TracksMap hash");
1932
1933         return map;
1934 }
1935
1936 static int tracks_map_get_size(TracksMap *map)
1937 {
1938         return map->num_tracks;
1939 }
1940
1941 static void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
1942 {
1943         *track = &map->tracks[index];
1944
1945         if (map->customdata)
1946                 *customdata = &map->customdata[index * map->customdata_size];
1947 }
1948
1949 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
1950 {
1951         MovieTrackingTrack new_track = *track;
1952
1953         new_track.markers = MEM_dupallocN(new_track.markers);
1954
1955         map->tracks[map->ptr] = new_track;
1956
1957         if (customdata)
1958                 memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
1959
1960         BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
1961
1962         map->ptr++;
1963 }
1964
1965 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
1966 {
1967         MovieTrackingTrack *track;
1968         MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
1969         MovieTrackingTrack *rot_track = tracking->stabilization.rot_track;
1970         ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
1971         ListBase *old_tracks;
1972         int a;
1973
1974         if (map->is_camera) {
1975                 old_tracks = &tracking->tracks;
1976         }
1977         else {
1978                 MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name);
1979
1980                 if (!object) {
1981                         /* object was deleted by user, create new one */
1982                         object = BKE_tracking_object_add(tracking, map->object_name);
1983                 }
1984
1985                 old_tracks = &object->tracks;
1986         }
1987
1988         /* duplicate currently operating tracks to temporary list.
1989          * this is needed to keep names in unique state and it's faster to change names
1990          * of currently operating tracks (if needed)
1991          */
1992         for (a = 0; a < map->num_tracks; a++) {
1993                 int replace_sel = 0, replace_rot = 0;
1994                 MovieTrackingTrack *new_track, *old;
1995
1996                 track = &map->tracks[a];
1997
1998                 /* find original of operating track in list of previously displayed tracks */
1999                 old = BLI_ghash_lookup(map->hash, track);
2000                 if (old) {
2001                         MovieTrackingTrack *cur = old_tracks->first;
2002
2003                         while (cur) {
2004                                 if (cur == old)
2005                                         break;
2006
2007                                 cur = cur->next;
2008                         }
2009
2010                         /* original track was found, re-use flags and remove this track */
2011                         if (cur) {
2012                                 if (cur == act_track)
2013                                         replace_sel = 1;
2014                                 if (cur == rot_track)
2015                                         replace_rot = 1;
2016
2017                                 track->flag = cur->flag;
2018                                 track->pat_flag = cur->pat_flag;
2019                                 track->search_flag = cur->search_flag;
2020
2021                                 BKE_tracking_track_free(cur);
2022                                 BLI_freelinkN(old_tracks, cur);
2023                         }
2024                 }
2025
2026                 new_track = tracking_track_duplicate(track);
2027
2028                 BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
2029                 BLI_ghash_insert(map->hash, track, new_track);
2030
2031                 if (replace_sel)  /* update current selection in clip */
2032                         tracking->act_track = new_track;
2033
2034                 if (replace_rot)  /* update track used for rotation stabilization */
2035                         tracking->stabilization.rot_track = new_track;
2036
2037                 BLI_addtail(&tracks, new_track);
2038         }
2039
2040         /* move all tracks, which aren't operating */
2041         track = old_tracks->first;
2042         while (track) {
2043                 MovieTrackingTrack *next = track->next;
2044
2045                 track->next = track->prev = NULL;
2046                 BLI_addtail(&new_tracks, track);
2047
2048                 track = next;
2049         }
2050
2051         /* now move all tracks which are currently operating and keep their names unique */
2052         track = tracks.first;
2053         while (track) {
2054                 MovieTrackingTrack *next = track->next;
2055
2056                 BLI_remlink(&tracks, track);
2057
2058                 track->next = track->prev = NULL;
2059                 BLI_addtail(&new_tracks, track);
2060
2061                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
2062
2063                 track = next;
2064         }
2065
2066         *old_tracks = new_tracks;
2067 }
2068
2069 static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
2070 {
2071         int i = 0;
2072
2073         BLI_ghash_free(map->hash, NULL, NULL);
2074
2075         for (i = 0; i < map->num_tracks; i++) {
2076                 if (map->customdata && customdata_free)
2077                         customdata_free(&map->customdata[i * map->customdata_size]);
2078
2079                 BKE_tracking_track_free(&map->tracks[i]);
2080         }
2081
2082         if (map->customdata)
2083                 MEM_freeN(map->customdata);
2084
2085         MEM_freeN(map->tracks);
2086         MEM_freeN(map);
2087 }
2088
2089 /*********************** 2D tracking *************************/
2090
2091 typedef struct TrackContext {
2092 #ifdef WITH_LIBMV
2093         /* the reference marker and cutout search area */
2094         MovieTrackingMarker marker;
2095
2096         /* keyframed patch. This is the search area */
2097         float *search_area;
2098         int search_area_height;
2099         int search_area_width;
2100         int framenr;
2101
2102         float *mask;
2103 #else
2104         int pad;
2105 #endif
2106 } TrackContext;
2107
2108 typedef struct MovieTrackingContext {
2109         MovieClipUser user;
2110         MovieClip *clip;
2111         int clip_flag;
2112
2113         int first_time, frames;
2114
2115         MovieTrackingSettings settings;
2116         TracksMap *tracks_map;
2117
2118         short backwards, sequence;
2119         int sync_frame;
2120 } MovieTrackingContext;
2121
2122 static void track_context_free(void *customdata)
2123 {
2124         TrackContext *track_context = (TrackContext *)customdata;
2125
2126 #ifdef WITH_LIBMV
2127         if (track_context->search_area)
2128                 MEM_freeN(track_context->search_area);
2129
2130         if (track_context->mask)
2131                 MEM_freeN(track_context->mask);
2132
2133 #else
2134         (void)track_context;
2135 #endif
2136 }
2137
2138 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
2139 {
2140         MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
2141         MovieTracking *tracking = &clip->tracking;
2142         MovieTrackingSettings *settings = &tracking->settings;
2143         ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
2144         MovieTrackingTrack *track;
2145         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
2146         int num_tracks = 0;
2147
2148         context->clip = clip;
2149         context->settings = *settings;
2150         context->backwards = backwards;
2151         context->sync_frame = user->framenr;
2152         context->first_time = TRUE;
2153         context->sequence = sequence;
2154
2155         /* count */
2156         track = tracksbase->first;
2157         while (track) {
2158                 if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
2159                         int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
2160                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
2161
2162                         if ((marker->flag & MARKER_DISABLED) == 0)
2163                                 num_tracks++;
2164                 }
2165
2166                 track = track->next;
2167         }
2168
2169         /* create tracking contextx for all tracks which would be tracked */
2170         if (num_tracks) {
2171                 int width, height;
2172
2173                 context->tracks_map = tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
2174                                                      num_tracks, sizeof(TrackContext));
2175
2176                 BKE_movieclip_get_size(clip, user, &width, &height);
2177
2178                 /* create tracking data */
2179                 track = tracksbase->first;
2180                 while (track) {
2181                         if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) {
2182                                 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
2183                                 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
2184
2185                                 if ((marker->flag & MARKER_DISABLED) == 0) {
2186                                         TrackContext track_context;
2187                                         memset(&track_context, 0, sizeof(TrackContext));
2188                                         tracks_map_insert(context->tracks_map, track, &track_context);
2189                                 }
2190                         }
2191
2192                         track = track->next;
2193                 }
2194         }
2195
2196         /* store needed clip flags passing to get_buffer functions
2197          * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
2198          *   only in case Proxy/Timecode flag is set, so store this flag to use
2199          *   timecodes properly but reset render size to SIZE_FULL so correct resolution
2200          *   would be used for images
2201          * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
2202          *   be stored in a different location
2203          * ignore all the rest possible flags for now
2204          */
2205         context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
2206
2207         context->user = *user;
2208         context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
2209         context->user.render_flag = 0;
2210
2211         if (!sequence)
2212                 BLI_begin_threaded_malloc();
2213
2214         return context;
2215 }
2216
2217 void BKE_tracking_context_free(MovieTrackingContext *context)
2218 {
2219         if (!context->sequence)
2220                 BLI_end_threaded_malloc();
2221
2222         tracks_map_free(context->tracks_map, track_context_free);
2223
2224         MEM_freeN(context);
2225 }
2226
2227 void BKE_tracking_context_sync(MovieTrackingContext *context)
2228 {
2229         MovieTracking *tracking = &context->clip->tracking;
2230         int newframe;
2231
2232         tracks_map_merge(context->tracks_map, tracking);
2233
2234         if (context->backwards)
2235                 newframe = context->user.framenr + 1;
2236         else
2237                 newframe = context->user.framenr - 1;
2238
2239         context->sync_frame = newframe;
2240
2241         BKE_tracking_dopesheet_tag_update(tracking);
2242 }
2243
2244 void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user)
2245 {
2246         user->framenr = context->sync_frame;
2247 }
2248
2249 #ifdef WITH_LIBMV
2250 /* **** utility functions for tracking **** */
2251
2252 /* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */
2253 static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels,
2254                                float weight_red, float weight_green, float weight_blue)
2255 {
2256         int i;
2257
2258         for (i = 0; i < num_pixels; i++) {
2259                 const float *pixel = rgba + 4 * i;
2260
2261                 gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2];
2262         }
2263 }
2264
2265 static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels,
2266                                      float weight_red, float weight_green, float weight_blue)
2267 {
2268         int i;
2269
2270         for (i = 0; i < num_pixels; i++) {
2271                 const unsigned char *pixel = rgba + i * 4;
2272
2273                 gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f;
2274         }
2275 }
2276
2277 static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
2278                                         int *width_r, int *height_r)
2279 {
2280         ImBuf *searchibuf;
2281         float *gray_pixels;
2282         int width, height;
2283
2284         searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE);
2285
2286         if (!searchibuf) {
2287                 *width_r = 0;
2288                 *height_r = 0;
2289                 return NULL;
2290         }
2291
2292         width = searchibuf->x;
2293         height = searchibuf->y;
2294
2295         gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf");
2296
2297         if (searchibuf->rect_float) {
2298                 float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height,
2299                                    0.2126f, 0.7152f, 0.0722f);
2300         }
2301         else {
2302                 uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height,
2303                                          0.2126f, 0.7152f, 0.0722f);
2304         }
2305
2306         IMB_freeImBuf(searchibuf);
2307
2308         *width_r = width;
2309         *height_r = height;
2310
2311         return gray_pixels;
2312 }
2313
2314 static ImBuf *tracking_context_get_frame_ibuf(MovieTrackingContext *context, int framenr)
2315 {
2316         ImBuf *ibuf;
2317         MovieClipUser user = context->user;
2318
2319         user.framenr = BKE_movieclip_remap_clip_to_scene_frame(context->clip, framenr);
2320
2321         ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag, MOVIECLIP_CACHE_SKIP);
2322
2323         return ibuf;
2324 }
2325
2326 static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
2327                                                                   MovieTrackingMarker *marker)
2328 {
2329         int a = marker - track->markers;
2330         MovieTrackingMarker *marker_keyed = marker;
2331
2332         while (a >= 0 && a < track->markersnr) {
2333                 int next = (context->backwards) ? a + 1 : a - 1;
2334                 int is_keyframed = FALSE;
2335                 MovieTrackingMarker *cur_marker = &track->markers[a];
2336                 MovieTrackingMarker *next_marker = NULL;
2337
2338                 if (next >= 0 && next < track->markersnr)
2339                         next_marker = &track->markers[next];
2340
2341                 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
2342                 if (next_marker && next_marker->flag & MARKER_DISABLED)
2343                         is_keyframed = TRUE;
2344
2345                 is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
2346
2347                 if (is_keyframed) {
2348                         marker_keyed = cur_marker;
2349
2350                         break;
2351                 }
2352
2353                 a = next;
2354         }
2355
2356         return marker_keyed;
2357 }
2358
2359 static ImBuf *tracking_context_get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
2360                                                   MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed_r)
2361 {
2362         MovieTrackingMarker *marker_keyed;
2363         int keyed_framenr;
2364
2365         marker_keyed = tracking_context_get_keyframed_marker(context, track, marker);
2366         keyed_framenr = marker_keyed->framenr;
2367
2368         *marker_keyed_r = marker_keyed;
2369
2370         return tracking_context_get_frame_ibuf(context, keyed_framenr);
2371 }
2372
2373 static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
2374                                                   MovieTrackingMarker *marker, int curfra,
2375                                                   MovieTrackingMarker **marker_keyed)
2376 {
2377         ImBuf *ibuf = NULL;
2378
2379         if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
2380                 ibuf = tracking_context_get_keyframed_ibuf(context, track, marker, marker_keyed);
2381         }
2382         else {
2383                 ibuf = tracking_context_get_frame_ibuf(context, curfra);
2384
2385                 /* use current marker as keyframed position */
2386                 *marker_keyed = marker;
2387         }
2388
2389         return ibuf;
2390 }
2391
2392 static int track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context,
2393                                           MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra,
2394                                           int frame_width, int frame_height)
2395 {
2396         MovieTrackingMarker *marker_keyed = NULL;
2397         ImBuf *reference_ibuf = NULL;
2398         int width, height;
2399
2400         /* calculate patch for keyframed position */
2401         reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed);
2402
2403         if (!reference_ibuf)
2404                 return FALSE;
2405
2406         track_context->marker = *marker_keyed;
2407
2408         if (track_context->search_area) {
2409                 MEM_freeN(track_context->search_area);
2410         }
2411
2412         track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, marker_keyed, &width, &height);
2413         track_context->search_area_height = height;
2414         track_context->search_area_width = width;
2415
2416         if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
2417                 if (track_context->mask)
2418                         MEM_freeN(track_context->mask);
2419
2420                 track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
2421         }
2422
2423         IMB_freeImBuf(reference_ibuf);
2424
2425         return TRUE;
2426 }
2427
2428 static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track,
2429                                        struct libmv_trackRegionOptions *options)
2430 {
2431         options->motion_model = track->motion_model;
2432
2433         options->use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0);
2434
2435         options->use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0);
2436
2437         options->num_iterations = 50;
2438         options->minimum_correlation = track->minimum_correlation;
2439         options->sigma = 0.9;
2440
2441         if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0)
2442                 options->image1_mask = track_context->mask;
2443 }
2444
2445 /* returns FALSE if marker crossed margin area from frame bounds */
2446 static int tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker,
2447                                         int frame_width, int frame_height)
2448 {
2449         float pat_min[2], pat_max[2], dim[2], margin[2];
2450
2451         /* margin from frame boundaries */
2452         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
2453         sub_v2_v2v2(dim, pat_max, pat_min);
2454         margin[0] = margin[1] = max_ff(dim[0], dim[1]) / 2.0f;
2455
2456         margin[0] = max_ff(margin[0], (float)track->margin / frame_width);
2457         margin[1] = max_ff(margin[1], (float)track->margin / frame_height);
2458
2459         /* do not track markers which are too close to boundary */
2460         if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] ||
2461             marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1])
2462         {
2463                 return FALSE;
2464         }
2465
2466         return TRUE;
2467 }
2468
2469 static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker)
2470 {
2471         float old_pat_min[2], old_pat_max[2];
2472         float new_pat_min[2], new_pat_max[2];
2473         float scale_x, scale_y;
2474
2475         BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max);
2476         BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max);
2477
2478         scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]);
2479         scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]);
2480
2481         new_marker->search_min[0] *= scale_x;
2482         new_marker->search_min[1] *= scale_y;
2483
2484         new_marker->search_max[0] *= scale_x;
2485         new_marker->search_max[1] *= scale_y;
2486 }
2487
2488 static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
2489                                        const MovieTrackingMarker *old_marker, int curfra, int tracked,
2490                                        int frame_width, int frame_height,
2491                                        double dst_pixel_x[5], double dst_pixel_y[5])
2492 {
2493         MovieTrackingMarker new_marker;
2494         int frame_delta = context->backwards ? -1 : 1;
2495         int nextfra = curfra + frame_delta;
2496
2497         new_marker = *old_marker;
2498
2499         if (tracked) {
2500                 set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y);
2501                 new_marker.flag |= MARKER_TRACKED;
2502                 new_marker.framenr = nextfra;
2503
2504                 tracking_scale_marker_search(old_marker, &new_marker);
2505
2506                 if (context->first_time) {
2507                         /* check if there's no keyframe/tracked markers before tracking marker.
2508                          * if so -- create disabled marker before currently tracking "segment"
2509                          */
2510
2511                         tracking_marker_insert_disabled(track, old_marker, !context->backwards, FALSE);
2512                 }
2513
2514                 /* insert currently tracked marker */
2515                 BKE_tracking_marker_insert(track, &new_marker);
2516
2517                 /* make currently tracked segment be finished with disabled marker */
2518                 tracking_marker_insert_disabled(track, &new_marker, context->backwards, FALSE);
2519         }
2520         else {
2521                 new_marker.framenr = nextfra;
2522                 new_marker.flag |= MARKER_DISABLED;
2523
2524                 BKE_tracking_marker_insert(track, &new_marker);
2525         }
2526 }
2527
2528 #endif
2529
2530 int BKE_tracking_context_step(MovieTrackingContext *context)
2531 {
2532         ImBuf *destination_ibuf;
2533         int frame_delta = context->backwards ? -1 : 1;
2534         int curfra =  BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr);
2535         /* int nextfra; */ /* UNUSED */
2536         int a, ok = FALSE, map_size;
2537
2538         int frame_width, frame_height;
2539
2540         map_size = tracks_map_get_size(context->tracks_map);
2541
2542         /* nothing to track, avoid unneeded frames reading to save time and memory */
2543         if (!map_size)
2544                 return FALSE;
2545
2546         context->user.framenr += frame_delta;
2547
2548         destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user,
2549                                                        context->clip_flag, MOVIECLIP_CACHE_SKIP);
2550         if (!destination_ibuf)
2551                 return FALSE;
2552
2553         /* nextfra = curfra + frame_delta; */ /* UNUSED */
2554
2555         frame_width = destination_ibuf->x;
2556         frame_height = destination_ibuf->y;
2557
2558         #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size > 1)
2559         for (a = 0; a < map_size; a++) {
2560                 TrackContext *track_context = NULL;
2561                 MovieTrackingTrack *track;
2562                 MovieTrackingMarker *marker;
2563
2564                 tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context);
2565
2566                 marker = BKE_tracking_marker_get_exact(track, curfra);
2567
2568                 if (marker && (marker->flag & MARKER_DISABLED) == 0) {
2569 #ifdef WITH_LIBMV
2570                         int width, height, tracked = FALSE, need_readjust;
2571                         double dst_pixel_x[5], dst_pixel_y[5];
2572
2573                         if (track->pattern_match == TRACK_MATCH_KEYFRAME)
2574                                 need_readjust = context->first_time;
2575                         else
2576                                 need_readjust = TRUE;
2577
2578                         /* do not track markers which are too close to boundary */
2579                         if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) {
2580                                 /* to convert to the x/y split array format for libmv. */
2581                                 double src_pixel_x[5], src_pixel_y[5];
2582
2583                                 /* settings for the tracker */
2584                                 struct libmv_trackRegionOptions options = {0};
2585                                 struct libmv_trackRegionResult result;
2586
2587                                 float *patch_new;
2588
2589                                 if (need_readjust) {
2590                                         if (track_context_update_reference(context, track_context, track, marker,
2591                                                                            curfra, frame_width, frame_height) == FALSE)
2592                                         {
2593                                                 /* happens when reference frame fails to be loaded */
2594                                                 continue;
2595                                         }
2596                                 }
2597
2598                                 /* for now track to the same search area dimension as marker has got for current frame
2599                                  * will make all tracked markers in currently tracked segment have the same search area
2600                                  * size, but it's quite close to what is actually needed
2601                                  */
2602                                 patch_new = track_get_search_floatbuf(destination_ibuf, track, marker, &width, &height);
2603
2604                                 /* configure the tracker */
2605                                 tracking_configure_tracker(track_context, track, &options);
2606
2607                                 /* convert the marker corners and center into pixel coordinates in the search/destination images. */
2608                                 get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y);
2609                                 get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
2610
2611                                 if (!patch_new || !track_context->search_area)
2612                                         continue;
2613
2614                                 /* run the tracker! */
2615                                 tracked = libmv_trackRegion(&options,
2616                                                             track_context->search_area,
2617                                                             track_context->search_area_width,
2618                                                             track_context->search_area_height,
2619                                                             patch_new, width, height,
2620                                                             src_pixel_x, src_pixel_y,
2621                                                             &result,
2622                                                             dst_pixel_x, dst_pixel_y);
2623                                 MEM_freeN(patch_new);
2624                         }
2625
2626                         #pragma omp critical
2627                         {
2628                                 tracking_insert_new_marker(context, track, marker, curfra, tracked,
2629                                                            frame_width, frame_height, dst_pixel_x, dst_pixel_y);
2630                         }
2631
2632                         ok = TRUE;
2633 #else
2634                         (void)frame_height;
2635                         (void)frame_width;
2636 #endif
2637                 }
2638         }
2639
2640         IMB_freeImBuf(destination_ibuf);
2641
2642         context->first_time = FALSE;
2643         context->frames++;
2644
2645         return ok;
2646 }
2647
2648 /*********************** Camera solving *************************/
2649
2650 typedef struct MovieReconstructContext {
2651 #ifdef WITH_LIBMV
2652         struct libmv_Tracks *tracks;
2653         int keyframe1, keyframe2;
2654         short refine_flags;
2655
2656         struct libmv_Reconstruction *reconstruction;
2657 #endif
2658         char object_name[MAX_NAME];
2659         int is_camera;
2660         short motion_flag;
2661
2662         float focal_length;
2663         float principal_point[2];
2664         float k1, k2, k3;
2665
2666         float reprojection_error;
2667
2668         TracksMap *tracks_map;
2669
2670         float success_threshold;
2671         int use_fallback_reconstruction;
2672
2673         int sfra, efra;
2674 } MovieReconstructContext;
2675
2676 typedef struct ReconstructProgressData {
2677         short *stop;
2678         short *do_update;
2679         float *progress;
2680         char *stats_message;
2681         int message_size;
2682 } ReconstructProgressData;
2683
2684 #ifdef WITH_LIBMV
2685 static struct libmv_Tracks *libmv_tracks_new(ListBase *tracksbase, int width, int height)
2686 {
2687         int tracknr = 0;
2688         MovieTrackingTrack *track;
2689         struct libmv_Tracks *tracks = libmv_tracksNew();
2690
2691         track = tracksbase->first;
2692         while (track) {
2693                 int a = 0;
2694
2695                 for (a = 0; a < track->markersnr; a++) {
2696                         MovieTrackingMarker *marker = &track->markers[a];
2697
2698                         if ((marker->flag & MARKER_DISABLED) == 0) {
2699                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
2700                                                    (marker->pos[0] + track->offset[0]) * width,
2701                                                    (marker->pos[1] + track->offset[1]) * height);
2702                         }
2703                 }
2704
2705                 track = track->next;
2706                 tracknr++;
2707         }
2708
2709         return tracks;
2710 }
2711
2712 static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *context, MovieTracking *tracking)
2713 {
2714         struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction;
2715         struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction);
2716
2717         float aspy = 1.0f / tracking->camera.pixel_aspect;
2718
2719         double focal_length, principal_x, principal_y, k1, k2, k3;
2720         int width, height;
2721
2722         libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y,
2723                                       &k1, &k2, &k3, &width, &height);
2724
2725         tracking->camera.focal = focal_length;
2726         tracking->camera.principal[0] = principal_x;
2727
2728         tracking->camera.principal[1] = principal_y / aspy;
2729         tracking->camera.k1 = k1;
2730         tracking->camera.k2 = k2;
2731 }
2732
2733 static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking)
2734 {
2735         struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction;
2736         MovieTrackingReconstruction *reconstruction = NULL;
2737         MovieReconstructedCamera *reconstructed;
2738         MovieTrackingTrack *track;
2739         ListBase *tracksbase =  NULL;
2740         int ok = TRUE, tracknr = 0, a, origin_set = FALSE;
2741         int sfra = context->sfra, efra = context->efra;
2742         float imat[4][4];
2743
2744         if (context->is_camera) {
2745                 tracksbase = &tracking->tracks;
2746                 reconstruction = &tracking->reconstruction;
2747         }
2748         else {
2749                 MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, context->object_name);
2750
2751                 tracksbase = &object->tracks;
2752                 reconstruction = &object->reconstruction;
2753         }
2754
2755         unit_m4(imat);
2756
2757         track = tracksbase->first;
2758         while (track) {
2759                 double pos[3];
2760
2761                 if (libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
2762                         track->bundle_pos[0] = pos[0];
2763                         track->bundle_pos[1] = pos[1];
2764                         track->bundle_pos[2] = pos[2];
2765
2766                         track->flag |= TRACK_HAS_BUNDLE;
2767                         track->error = libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
2768                 }
2769                 else {
2770                         track->flag &= ~TRACK_HAS_BUNDLE;
2771                         ok = FALSE;
2772
2773                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
2774                 }
2775
2776                 track = track->next;
2777                 tracknr++;
2778         }
2779
2780         if (reconstruction->cameras)
2781                 MEM_freeN(reconstruction->cameras);
2782
2783         reconstruction->camnr = 0;
2784         reconstruction->cameras = NULL;
2785         reconstructed = MEM_callocN((efra - sfra + 1) * sizeof(MovieReconstructedCamera),
2786                                     "temp reconstructed camera");
2787
2788         for (a = sfra; a <= efra; a++) {
2789                 double matd[4][4];
2790
2791                 if (libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
2792                         int i, j;
2793                         float mat[4][4];
2794                         float error = libmv_reporojectionErrorForImage(libmv_reconstruction, a);
2795
2796                         for (i = 0; i < 4; i++)
2797                                 for (j = 0; j < 4; j++)
2798                                         mat[i][j] = matd[i][j];
2799
2800                         if (!origin_set) {
2801                                 copy_m4_m4(imat, mat);
2802                                 invert_m4(imat);
2803                                 origin_set = TRUE;
2804                         }
2805
2806                         if (origin_set)
2807                                 mult_m4_m4m4(mat, imat, mat);
2808
2809                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
2810                         reconstructed[reconstruction->camnr].framenr = a;
2811                         reconstructed[reconstruction->camnr].error = error;
2812                         reconstruction->camnr++;
2813                 }
2814                 else {
2815                         ok = FALSE;
2816                         printf("No camera for frame %d\n", a);
2817                 }
2818         }
2819
2820         if (reconstruction->camnr) {
2821                 int size = reconstruction->camnr * sizeof(MovieReconstructedCamera);
2822                 reconstruction->cameras = MEM_callocN(size, "reconstructed camera");
2823                 memcpy(reconstruction->cameras, reconstructed, size);
2824         }
2825
2826         if (origin_set) {
2827                 track = tracksbase->first;
2828                 while (track) {
2829                         if (track->flag & TRACK_HAS_BUNDLE)
2830                                 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
2831
2832                         track = track->next;
2833                 }
2834         }
2835
2836         MEM_freeN(reconstructed);
2837
2838         return ok;
2839 }
2840
2841 static int reconstruct_retrieve_libmv(MovieReconstructContext *context, MovieTracking *tracking)
2842 {
2843         /* take the intrinscis back from libmv */
2844         reconstruct_retrieve_libmv_intrinscis(context, tracking);
2845
2846         return reconstruct_retrieve_libmv_tracks(context, tracking);
2847 }
2848
2849 static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, MovieTrackingObject *object)
2850 {
2851         int refine = tracking->settings.refine_camera_intrinsics;
2852         int flags = 0;
2853
2854         if ((object->flag & TRACKING_OBJECT_CAMERA) == 0)
2855                 return 0;
2856
2857         if (refine & REFINE_FOCAL_LENGTH)
2858                 flags |= LIBMV_REFINE_FOCAL_LENGTH;
2859
2860         if (refine & REFINE_PRINCIPAL_POINT)
2861                 flags |= LIBMV_REFINE_PRINCIPAL_POINT;
2862
2863         if (refine & REFINE_RADIAL_DISTORTION_K1)
2864                 flags |= REFINE_RADIAL_DISTORTION_K1;
2865
2866         if (refine & REFINE_RADIAL_DISTORTION_K2)
2867                 flags |= REFINE_RADIAL_DISTORTION_K2;
2868
2869         return flags;
2870 }
2871
2872 static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, MovieTrackingObject *object)
2873 {
2874         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
2875         int tot = 0;
2876         int frame1 = object->keyframe1, frame2 = object->keyframe2;
2877         MovieTrackingTrack *track;
2878
2879         track = tracksbase->first;
2880         while (track) {
2881                 if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame1)) {
2882                         if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame2)) {
2883                                 tot++;
2884                         }
2885                 }
2886
2887                 track = track->next;
2888         }
2889
2890         return tot;
2891 }
2892 #endif
2893
2894 int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
2895 {
2896 #ifdef WITH_LIBMV
2897         if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) {
2898                 /* TODO: check for number of tracks? */
2899                 return TRUE;
2900         }
2901         else if (reconstruct_count_tracks_on_both_keyframes(tracking, object) < 8) {
2902                 BLI_strncpy(error_msg, N_("At least 8 common tracks on both of keyframes are needed for reconstruction"),
2903                             error_size);
2904
2905                 return FALSE;
2906         }
2907
2908         return TRUE;
2909 #else
2910         BLI_strncpy(error_msg, N_("Blender is compiled without motion tracking library"), error_size);
2911
2912         (void) tracking;
2913         (void) object;
2914
2915         return 0;
2916 #endif
2917 }
2918
2919 MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking *tracking, MovieTrackingObject *object,
2920                                                                  int keyframe1, int keyframe2, int width, int height)
2921 {
2922         MovieReconstructContext *context = MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
2923         MovieTrackingCamera *camera = &tracking->camera;
2924         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
2925         float aspy = 1.0f / tracking->camera.pixel_aspect;
2926         int num_tracks = BLI_countlist(tracksbase);
2927         int sfra = INT_MAX, efra = INT_MIN;
2928         MovieTrackingTrack *track;
2929
2930         BLI_strncpy(context->object_name, object->name, sizeof(context->object_name));
2931         context->is_camera = object->flag & TRACKING_OBJECT_CAMERA;
2932         context->motion_flag = tracking->settings.motion_flag;
2933
2934         context->focal_length = camera->focal;
2935         context->principal_point[0] = camera->principal[0];
2936         context->principal_point[1] = camera->principal[1] * aspy;
2937
2938         context->k1 = camera->k1;
2939         context->k2 = camera->k2;
2940         context->k3 = camera->k3;
2941
2942         context->success_threshold = tracking->settings.reconstruction_success_threshold;
2943         context->use_fallback_reconstruction = tracking->settings.reconstruction_flag & TRACKING_USE_FALLBACK_RECONSTRUCTION;
2944
2945         context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
2946
2947         track = tracksbase->first;
2948         while (track) {
2949                 int first = 0, last = track->markersnr - 1;
2950                 MovieTrackingMarker *first_marker = &track->markers[0];
2951                 MovieTrackingMarker *last_marker = &track->markers[track->markersnr - 1];
2952
2953                 /* find first not-disabled marker */
2954                 while (first <= track->markersnr - 1 && first_marker->flag & MARKER_DISABLED) {
2955                         first++;
2956                         first_marker++;
2957                 }
2958
2959                 /* find last not-disabled marker */
2960                 while (last >= 0 && last_marker->flag & MARKER_DISABLED) {
2961                         last--;
2962                         last_marker--;
2963                 }
2964
2965                 if (first < track->markersnr - 1)
2966                         sfra = min_ii(sfra, first_marker->framenr);
2967
2968                 if (last >= 0)
2969                         efra = max_ii(efra, last_marker->framenr);
2970
2971                 tracks_map_insert(context->tracks_map, track, NULL);
2972
2973                 track = track->next;
2974         }
2975
2976         context->sfra = sfra;
2977         context->efra = efra;
2978
2979 #ifdef WITH_LIBMV
2980         context->tracks = libmv_tracks_new(tracksbase, width, height * aspy);
2981         context->keyframe1 = keyframe1;
2982         context->keyframe2 = keyframe2;
2983         context->refine_flags = reconstruct_refine_intrinsics_get_flags(tracking, object);
2984 #else
2985         (void) width;
2986         (void) height;
2987         (void) keyframe1;
2988         (void) keyframe2;
2989 #endif
2990
2991         return context;
2992 }
2993
2994 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
2995 {
2996 #ifdef WITH_LIBMV
2997         if (context->reconstruction)
2998                 libmv_destroyReconstruction(context->reconstruction);
2999
3000         libmv_tracksDestroy(context->tracks);
3001 #endif
3002
3003         tracks_map_free(context->tracks_map, NULL);
3004
3005         MEM_freeN(context);
3006 }
3007
3008 #ifdef WITH_LIBMV
3009 static void reconstruct_update_solve_cb(void *customdata, double progress, const char *message)
3010 {
3011         ReconstructProgressData *progressdata = customdata;
3012
3013         if (progressdata->progress) {
3014                 *progressdata->progress = progress;
3015                 *progressdata->do_update = TRUE;
3016         }
3017
3018         BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
3019 }
3020
3021 static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
3022                                               MovieReconstructContext *context)
3023 {
3024         camera_intrinsics_options->focal_length = context->focal_length;
3025
3026         camera_intrinsics_options->principal_point_x = context->principal_point[0];
3027         camera_intrinsics_options->principal_point_y = context->principal_point[1];
3028
3029         camera_intrinsics_options->k1 = context->k1;
3030         camera_intrinsics_options->k2 = context->k2;
3031         camera_intrinsics_options->k3 = context->k3;
3032
3033         camera_intrinsics_options->image_width = 0;
3034         camera_intrinsics_options->image_height = 0;
3035 }
3036
3037 static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,
3038                                              MovieReconstructContext *context)
3039 {
3040         reconstruction_options->keyframe1 = context->keyframe1;
3041         reconstruction_options->keyframe2 = context->keyframe2;
3042
3043         reconstruction_options->refine_intrinsics = context->refine_flags;
3044
3045         reconstruction_options->success_threshold = context->success_threshold;
3046         reconstruction_options->use_fallback_reconstruction = context->use_fallback_reconstruction;
3047 }
3048 #endif
3049
3050 void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update,
3051                                        float *progress, char *stats_message, int message_size)
3052 {
3053 #ifdef WITH_LIBMV
3054         float error;
3055
3056         ReconstructProgressData progressdata;
3057
3058         libmv_cameraIntrinsicsOptions camera_intrinsics_options;
3059         libmv_reconstructionOptions reconstruction_options;
3060
3061         progressdata.stop = stop;
3062         progressdata.do_update = do_update;
3063         progressdata.progress = progress;
3064         progressdata.stats_message = stats_message;
3065         progressdata.message_size = message_size;
3066
3067         camraIntrincicsOptionsFromContext(&camera_intrinsics_options, context);
3068         reconstructionOptionsFromContext(&reconstruction_options, context);
3069
3070         if (context->motion_flag & TRACKING_MOTION_MODAL) {
3071                 context->reconstruction = libmv_solveModal(context->tracks,
3072                                                            &camera_intrinsics_options,
3073                                                            reconstruct_update_solve_cb, &progressdata);
3074         }
3075         else {
3076                 context->reconstruction = libmv_solveReconstruction(context->tracks,
3077                                                                     &camera_intrinsics_options,
3078                                                                     &reconstruction_options,
3079                                                                     reconstruct_update_solve_cb, &progressdata);
3080         }
3081
3082         error = libmv_reprojectionError(context->reconstruction);
3083
3084         context->reprojection_error = error;
3085 #else
3086         (void) context;
3087         (void) stop;
3088         (void) do_update;
3089         (void) progress;
3090         (void) stats_message;
3091         (void) message_size;
3092 #endif
3093 }
3094
3095 int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking)
3096 {
3097         MovieTrackingReconstruction *reconstruction;
3098
3099         tracks_map_merge(context->tracks_map, tracking);
3100         BKE_tracking_dopesheet_tag_update(tracking);
3101
3102         if (context->is_camera) {
3103                 reconstruction = &tracking->reconstruction;
3104         }
3105         else {
3106                 MovieTrackingObject *object;
3107
3108                 object = BKE_tracking_object_get_named(tracking, context->object_name);
3109                 reconstruction = &object->reconstruction;
3110         }
3111
3112         reconstruction->error = context->reprojection_error;
3113         reconstruction->flag |= TRACKING_RECONSTRUCTED;
3114
3115 #ifdef WITH_LIBMV
3116         if (!reconstruct_retrieve_libmv(context, tracking))
3117                 return FALSE;
3118 #endif
3119
3120         return TRUE;
3121 }
3122
3123 /*********************** Feature detection *************************/
3124
3125 #ifdef WITH_LIBMV
3126 static int check_point_in_stroke(bGPDstroke *stroke, float x, float y)
3127 {
3128         int i, prev;
3129         int count = 0;
3130         bGPDspoint *points = stroke->points;
3131
3132         prev = stroke->totpoints - 1;
3133
3134         for (i = 0; i < stroke->totpoints; i++) {
3135                 if ((points[i].y < y && points[prev].y >= y) || (points[prev].y < y && points[i].y >= y)) {
3136                         float fac = (y - points[i].y) / (points[prev].y - points[i].y);
3137
3138                         if (points[i].x + fac * (points[prev].x - points[i].x) < x)
3139                                 count++;
3140                 }
3141
3142                 prev = i;
3143         }
3144
3145         return count % 2;
3146 }
3147
3148 static int check_point_in_layer(bGPDlayer *layer, float x, float y)
3149 {
3150         bGPDframe *frame = layer->frames.first;
3151
3152         while (frame) {
3153                 bGPDstroke *stroke = frame->strokes.first;
3154
3155                 while (stroke) {
3156                         if (check_point_in_stroke(stroke, x, y))
3157                                 return TRUE;
3158
3159                         stroke = stroke->next;
3160                 }
3161                 frame = frame->next;
3162         }
3163
3164         return FALSE;
3165 }
3166
3167 static void detect_retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
3168                                            struct libmv_Features *features, int framenr, int width, int height,
3169                                            bGPDlayer *layer, int place_outside_layer)
3170 {
3171         int a;
3172
3173         a = libmv_countFeatures(features);
3174         while (a--) {
3175                 MovieTrackingTrack *track;
3176                 double x, y, size, score;
3177                 int ok = TRUE;
3178                 float xu, yu;
3179
3180                 libmv_getFeature(features, a, &x, &y, &score, &size);
3181
3182                 xu = x / width;
3183                 yu = y / height;
3184
3185                 if (layer)
3186                         ok = check_point_in_layer(layer, xu, yu) != place_outside_layer;
3187
3188                 if (ok) {
3189                         track = BKE_tracking_track_add(tracking, tracksbase, xu, yu, framenr, width, height);
3190                         track->flag |= SELECT;
3191                         track->pat_flag |= SELECT;
3192                         track->search_flag |= SELECT;
3193                 }
3194         }
3195 }
3196
3197 static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf)
3198 {
3199         int x, y;
3200         unsigned char *pixels, *cp;
3201
3202         cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf");
3203         for (y = 0; y < ibuf->y; y++) {
3204                 for (x = 0; x < ibuf->x; x++) {
3205                         int pixel = ibuf->x * y + x;
3206
3207                         if (ibuf->rect_float) {
3208                                 const float *rrgbf = ibuf->rect_float + pixel * 4;
3209                                 const float gray_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2];
3210
3211                                 *cp = FTOCHAR(gray_f);
3212                         }
3213                         else {
3214                                 const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
3215
3216                                 *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2];
3217                         }
3218
3219                         cp++;
3220                 }
3221         }
3222
3223         return pixels;
3224 }
3225 #endif
3226
3227 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
3228                               int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
3229                               int place_outside_layer)
3230 {
3231 #ifdef WITH_LIBMV
3232         struct libmv_Features *features;
3233         unsigned char *pixels = detect_get_frame_ucharbuf(ibuf);
3234
3235         features = libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
3236                                             margin, min_trackness, min_distance);
3237
3238         MEM_freeN(pixels);
3239
3240         detect_retrieve_libmv_features(tracking, tracksbase, features, framenr,
3241                                        ibuf->x, ibuf->y, layer, place_outside_layer);
3242
3243         libmv_destroyFeatures(features);
3244 #else
3245         (void) tracking;
3246         (void) tracksbase;
3247         (void) ibuf;
3248         (void) framenr;
3249         (void) margin;
3250         (void) min_trackness;
3251         (void) min_distance;
3252         (void) layer;
3253         (void) place_outside_layer;
3254 #endif
3255 }
3256
3257 /*********************** 2D stabilization *************************/
3258
3259 static int stabilization_median_point_get(MovieTracking *tracking, int framenr, float median[2])
3260 {
3261         int ok = FALSE;
3262         float min[2], max[2];
3263         MovieTrackingTrack *track;
3264
3265         INIT_MINMAX2(min, max);
3266
3267         track = tracking->tracks.first;
3268         while (track) {
3269                 if (track->flag & TRACK_USE_2D_STAB) {
3270                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
3271
3272                         minmax_v2v2_v2(min, max, marker->pos);
3273
3274                         ok = TRUE;
3275                 }
3276
3277                 track = track->next;
3278         }
3279
3280         median[0] = (max[0] + min[0]) / 2.0f;
3281         median[1] = (max[1] + min[1]) / 2.0f;
3282
3283         return ok;
3284 }
3285
3286 static void stabilization_calculate_data(MovieTracking *tracking, int framenr, float width, float height,
3287                                          float firstmedian[2], float median[2], float loc[2],
3288                                          float *scale, float *angle)
3289 {
3290         MovieTrackingStabilization *stab = &tracking->stabilization;
3291
3292         *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f;
3293         *angle = 0.0f;
3294
3295         loc[0] = (firstmedian[0] - median[0]) * width * (*scale);
3296         loc[1] = (firstmedian[1] - median[1]) * height * (*scale);
3297
3298         mul_v2_fl(loc, stab->locinf);
3299
3300         if ((stab->flag & TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) {
3301                 MovieTrackingMarker *marker;
3302                 float a[2], b[2];
3303                 float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f;
3304                 float x = median[0] * width, y = median[1] * height;
3305
3306                 marker = BKE_tracking_marker_get(stab->rot_track, 1);
3307                 sub_v2_v2v2(a, marker->pos, firstmedian);
3308                 a[0] *= width;
3309                 a[1] *= height;
3310
3311                 marker = BKE_tracking_marker_get(stab->rot_track, framenr);
3312                 sub_v2_v2v2(b, marker->pos, median);
3313                 b[0] *= width;
3314                 b[1] *= height;
3315