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