ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / tracking_auto.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #include <stdlib.h>
25 #include "atomic_ops.h"
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_movieclip_types.h"
30 #include "DNA_object_types.h" /* SELECT */
31
32 #include "BLI_utildefines.h"
33 #include "BLI_listbase.h"
34 #include "BLI_task.h"
35 #include "BLI_threads.h"
36 #include "BLI_math.h"
37
38 #include "BKE_movieclip.h"
39 #include "BKE_tracking.h"
40
41 #include "libmv-capi.h"
42 #include "tracking_private.h"
43
44 typedef struct AutoTrackOptions {
45   int clip_index;            /** Index of the clip this track belogs to. */
46   int track_index;           /* Index of the track in AutoTrack tracks structure. */
47   MovieTrackingTrack *track; /* Pointer to an original track/ */
48   libmv_TrackRegionOptions track_region_options; /* Options for the region
49                                                      tracker. */
50   bool use_keyframe_match;                       /* Keyframe pattern matching. */
51
52   /* TODO(sergey): A bit awkward to keep it in here, only used to
53    * place a disabled marker once the tracking fails,
54    * Wither find a more clear way to do it or call it track context
55    * or state, not options.
56    */
57   bool is_failed;
58   int failed_frame;
59 } AutoTrackOptions;
60
61 typedef struct AutoTrackContext {
62   MovieClip *clips[MAX_ACCESSOR_CLIP];
63   int num_clips;
64
65   MovieClipUser user;
66   int frame_width, frame_height;
67
68   struct libmv_AutoTrack *autotrack;
69   TrackingImageAccessor *image_accessor;
70
71   int num_tracks;            /* Number of tracks being tracked. */
72   AutoTrackOptions *options; /* Per-tracking track options. */
73
74   /* Array of all tracks, indexed by track_index. */
75   MovieTrackingTrack **tracks;
76
77   bool backwards;
78   bool sequence;
79   int first_frame;
80   int sync_frame;
81   bool first_sync;
82   SpinLock spin_lock;
83
84   bool step_ok;
85 } AutoTrackContext;
86
87 static void normalized_to_libmv_frame(const float normalized[2],
88                                       const int frame_dimensions[2],
89                                       float result[2])
90 {
91   result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
92   result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
93 }
94
95 static void normalized_relative_to_libmv_frame(const float normalized[2],
96                                                const float origin[2],
97                                                const int frame_dimensions[2],
98                                                float result[2])
99 {
100   result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
101   result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
102 }
103
104 static void libmv_frame_to_normalized(const float frame_coord[2],
105                                       const int frame_dimensions[2],
106                                       float result[2])
107 {
108   result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
109   result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
110 }
111
112 static void libmv_frame_to_normalized_relative(const float frame_coord[2],
113                                                const float origin[2],
114                                                const int frame_dimensions[2],
115                                                float result[2])
116 {
117   result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
118   result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
119 }
120
121 static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
122                                        /*const*/ MovieTrackingMarker *marker,
123                                        int clip,
124                                        int track_index,
125                                        int frame_width,
126                                        int frame_height,
127                                        bool backwards,
128                                        libmv_Marker *libmv_marker)
129 {
130   const int frame_dimensions[2] = {frame_width, frame_height};
131   int i;
132   libmv_marker->clip = clip;
133   libmv_marker->frame = marker->framenr;
134   libmv_marker->track = track_index;
135
136   normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
137   for (i = 0; i < 4; ++i) {
138     normalized_relative_to_libmv_frame(
139         marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
140   }
141
142   normalized_relative_to_libmv_frame(
143       marker->search_min, marker->pos, frame_dimensions, libmv_marker->search_region_min);
144
145   normalized_relative_to_libmv_frame(
146       marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
147
148   /* TODO(sergey): All the markers does have 1.0 weight. */
149   libmv_marker->weight = 1.0f;
150
151   if (marker->flag & MARKER_TRACKED) {
152     libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
153   }
154   else {
155     libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
156   }
157   libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
158   libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
159   libmv_marker->model_id = 0;
160
161   /* TODO(sergey): We currently don't support reference marker from
162    * different clip.
163    */
164   libmv_marker->reference_clip = clip;
165
166   if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
167     MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
168         track, marker->framenr, backwards);
169     libmv_marker->reference_frame = keyframe_marker->framenr;
170   }
171   else {
172     libmv_marker->reference_frame = backwards ? marker->framenr - 1 : marker->framenr;
173   }
174
175   libmv_marker->disabled_channels =
176       ((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
177       ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
178       ((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
179 }
180
181 static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
182                                        int frame_width,
183                                        int frame_height,
184                                        MovieTrackingMarker *marker)
185 {
186   const int frame_dimensions[2] = {frame_width, frame_height};
187   int i;
188   marker->framenr = libmv_marker->frame;
189
190   libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
191   for (i = 0; i < 4; ++i) {
192     libmv_frame_to_normalized_relative(libmv_marker->patch[i],
193                                        libmv_marker->center,
194                                        frame_dimensions,
195                                        marker->pattern_corners[i]);
196   }
197
198   libmv_frame_to_normalized_relative(
199       libmv_marker->search_region_min, libmv_marker->center, frame_dimensions, marker->search_min);
200
201   libmv_frame_to_normalized_relative(
202       libmv_marker->search_region_max, libmv_marker->center, frame_dimensions, marker->search_max);
203
204   marker->flag = 0;
205   if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
206     marker->flag |= MARKER_TRACKED;
207   }
208   else {
209     marker->flag &= ~MARKER_TRACKED;
210   }
211 }
212
213 static bool check_track_trackable(const MovieClip *clip,
214                                   MovieTrackingTrack *track,
215                                   const MovieClipUser *user)
216 {
217   if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
218     int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
219     const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, frame);
220     return (marker->flag & MARKER_DISABLED) == 0;
221   }
222   return false;
223 }
224
225 /* Returns false if marker crossed margin area from frame bounds. */
226 static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
227                                          int margin,
228                                          int frame_width,
229                                          int frame_height)
230 {
231   float patch_min[2], patch_max[2];
232   float margin_left, margin_top, margin_right, margin_bottom;
233
234   INIT_MINMAX2(patch_min, patch_max);
235   minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
236   minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
237   minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
238   minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
239
240   margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
241   margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
242   margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
243   margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
244
245   if (libmv_marker->center[0] < margin_left ||
246       libmv_marker->center[0] > frame_width - margin_right ||
247       libmv_marker->center[1] < margin_bottom ||
248       libmv_marker->center[1] > frame_height - margin_top) {
249     return false;
250   }
251
252   return true;
253 }
254
255 /* Provide Libmv side of auto track all information about given tracks. */
256 static void fill_autotrack_tracks(const int frame_width,
257                                   const int frame_height,
258                                   const ListBase *tracksbase,
259                                   const bool backwards,
260                                   struct libmv_AutoTrack *autotrack)
261 {
262   /* Count number of markers to be put to a context. */
263   size_t num_trackable_markers = 0;
264   for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
265     for (int i = 0; i < track->markersnr; ++i) {
266       const MovieTrackingMarker *marker = track->markers + i;
267       if ((marker->flag & MARKER_DISABLED) == 0) {
268         num_trackable_markers++;
269       }
270     }
271   }
272   /* Early output if we don't have any markers. */
273   if (num_trackable_markers == 0) {
274     return;
275   }
276   /* Allocate memory for all the markers. */
277   libmv_Marker *libmv_markers = MEM_mallocN(sizeof(libmv_Marker) * num_trackable_markers,
278                                             "libmv markers array");
279   /* Fill in markers array. */
280   int track_index = 0, num_filled_libmv_markers = 0;
281   for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
282     for (int i = 0; i < track->markersnr; ++i) {
283       MovieTrackingMarker *marker = track->markers + i;
284       if ((marker->flag & MARKER_DISABLED) != 0) {
285         continue;
286       }
287       dna_marker_to_libmv_marker(track,
288                                  marker,
289                                  0,
290                                  track_index,
291                                  frame_width,
292                                  frame_height,
293                                  backwards,
294                                  &libmv_markers[num_filled_libmv_markers++]);
295     }
296     /* Put all markers to autotrack at once. */
297     track_index++;
298   }
299   /* Add all markers to autotrack. */
300   libmv_autoTrackSetMarkers(autotrack, libmv_markers, num_trackable_markers);
301   /* Free temporary memory. */
302   MEM_freeN(libmv_markers);
303 }
304
305 static void create_per_track_tracking_options(const MovieClip *clip,
306                                               const MovieClipUser *user,
307                                               const ListBase *tracksbase,
308                                               AutoTrackContext *context)
309 {
310   /* Count number of trackable tracks. */
311   for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
312     if (check_track_trackable(clip, track, user)) {
313       context->num_tracks++;
314     }
315   }
316   /* Allocate required memory. */
317   context->options = MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks,
318                                  "auto track options");
319   /* Fill in all the settings. */
320   int i = 0, track_index = 0;
321   for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
322     if (!check_track_trackable(clip, track, user)) {
323       ++track_index;
324       continue;
325     }
326     AutoTrackOptions *options = &context->options[i++];
327     /* TODO(sergey): Single clip only for now. */
328     options->clip_index = 0;
329     options->track_index = track_index;
330     options->track = track;
331     tracking_configure_tracker(track, NULL, &options->track_region_options);
332     options->use_keyframe_match = track->pattern_match == TRACK_MATCH_KEYFRAME;
333     context->tracks[track_index] = track;
334     ++track_index;
335   }
336 }
337
338 AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
339                                             MovieClipUser *user,
340                                             const bool backwards,
341                                             const bool sequence)
342 {
343   AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), "autotrack context");
344   MovieTracking *tracking = &clip->tracking;
345   ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
346   int frame_width, frame_height;
347   /* get size of frame to convert normalized coordinates to a picture ones. */
348   BKE_movieclip_get_size(clip, user, &frame_width, &frame_height);
349   /* TODO(sergey): Currently using only a single clip. */
350   context->clips[0] = clip;
351   context->num_clips = 1;
352   context->user = *user;
353   context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
354   context->user.render_flag = 0;
355   context->frame_width = frame_width;
356   context->frame_height = frame_height;
357   context->backwards = backwards;
358   context->sequence = sequence;
359   context->first_frame = user->framenr;
360   context->sync_frame = user->framenr;
361   context->first_sync = true;
362   BLI_spin_init(&context->spin_lock);
363   const int num_total_tracks = BLI_listbase_count(tracksbase);
364   context->tracks = MEM_callocN(sizeof(MovieTrackingTrack *) * num_total_tracks,
365                                 "auto track pointers");
366   /* Initialize image accessor. */
367   context->image_accessor = tracking_image_accessor_new(
368       context->clips, 1, context->tracks, num_total_tracks, user->framenr);
369   /* Initialize auto track context and provide all information about currently
370    * tracked markers.
371    */
372   context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor);
373   fill_autotrack_tracks(frame_width, frame_height, tracksbase, backwards, context->autotrack);
374   /* Create per-track tracking options. */
375   create_per_track_tracking_options(clip, user, tracksbase, context);
376   return context;
377 }
378
379 static void autotrack_context_step_cb(void *__restrict userdata,
380                                       const int track,
381                                       const ParallelRangeTLS *__restrict UNUSED(tls))
382 {
383   AutoTrackContext *context = userdata;
384   const int frame_delta = context->backwards ? -1 : 1;
385
386   AutoTrackOptions *options = &context->options[track];
387   if (options->is_failed) {
388     return;
389   }
390   libmv_Marker libmv_current_marker, libmv_reference_marker, libmv_tracked_marker;
391   libmv_TrackRegionResult libmv_result;
392   const int frame = BKE_movieclip_remap_scene_to_clip_frame(context->clips[options->clip_index],
393                                                             context->user.framenr);
394   BLI_spin_lock(&context->spin_lock);
395   const bool has_marker = libmv_autoTrackGetMarker(
396       context->autotrack, options->clip_index, frame, options->track_index, &libmv_current_marker);
397   BLI_spin_unlock(&context->spin_lock);
398   /* Check whether we've got marker to sync with. */
399   if (!has_marker) {
400     return;
401   }
402   /* Check whether marker is going outside of allowed frame margin. */
403   if (!tracking_check_marker_margin(&libmv_current_marker,
404                                     options->track->margin,
405                                     context->frame_width,
406                                     context->frame_height)) {
407     return;
408   }
409   libmv_tracked_marker = libmv_current_marker;
410   libmv_tracked_marker.frame = frame + frame_delta;
411   /* Update reference frame. */
412   if (options->use_keyframe_match) {
413     libmv_tracked_marker.reference_frame = libmv_current_marker.reference_frame;
414     libmv_autoTrackGetMarker(context->autotrack,
415                              options->clip_index,
416                              libmv_tracked_marker.reference_frame,
417                              options->track_index,
418                              &libmv_reference_marker);
419   }
420   else {
421     libmv_tracked_marker.reference_frame = frame;
422     libmv_reference_marker = libmv_current_marker;
423   }
424   /* Perform actual tracking. */
425   if (libmv_autoTrackMarker(context->autotrack,
426                             &options->track_region_options,
427                             &libmv_tracked_marker,
428                             &libmv_result)) {
429     BLI_spin_lock(&context->spin_lock);
430     libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
431     BLI_spin_unlock(&context->spin_lock);
432   }
433   else {
434     options->is_failed = true;
435     options->failed_frame = frame + frame_delta;
436   }
437
438   /* Note: Atomic is probably not actually needed here, I doubt we could get
439    *       any other result than a true bool anyway.
440    *       But for sake of consistency, and since it costs nothing...
441    */
442   atomic_fetch_and_or_uint8((uint8_t *)&context->step_ok, true);
443 }
444
445 bool BKE_autotrack_context_step(AutoTrackContext *context)
446 {
447   const int frame_delta = context->backwards ? -1 : 1;
448   context->step_ok = false;
449
450   ParallelRangeSettings settings;
451   BLI_parallel_range_settings_defaults(&settings);
452   settings.use_threading = (context->num_tracks > 1);
453   BLI_task_parallel_range(0, context->num_tracks, context, autotrack_context_step_cb, &settings);
454
455   /* Advance the frame. */
456   BLI_spin_lock(&context->spin_lock);
457   context->user.framenr += frame_delta;
458   BLI_spin_unlock(&context->spin_lock);
459   return context->step_ok;
460 }
461
462 void BKE_autotrack_context_sync(AutoTrackContext *context)
463 {
464   int newframe, frame_delta = context->backwards ? -1 : 1;
465   int frame;
466
467   BLI_spin_lock(&context->spin_lock);
468   newframe = context->user.framenr;
469   for (frame = context->sync_frame; frame != (context->backwards ? newframe - 1 : newframe + 1);
470        frame += frame_delta) {
471     MovieTrackingMarker marker;
472     libmv_Marker libmv_marker;
473     int clip = 0;
474     int track;
475     for (track = 0; track < context->num_tracks; ++track) {
476       AutoTrackOptions *options = &context->options[track];
477       int track_frame = BKE_movieclip_remap_scene_to_clip_frame(
478           context->clips[options->clip_index], frame);
479       if (options->is_failed) {
480         if (options->failed_frame == track_frame) {
481           MovieTrackingMarker *prev_marker = BKE_tracking_marker_get_exact(
482               options->track, context->backwards ? frame + 1 : frame - 1);
483           if (prev_marker) {
484             marker = *prev_marker;
485             marker.framenr = track_frame;
486             marker.flag |= MARKER_DISABLED;
487             BKE_tracking_marker_insert(options->track, &marker);
488             continue;
489           }
490         }
491         if ((context->backwards && options->failed_frame > track_frame) ||
492             (!context->backwards && options->failed_frame < track_frame)) {
493           continue;
494         }
495       }
496       if (libmv_autoTrackGetMarker(
497               context->autotrack, clip, track_frame, options->track_index, &libmv_marker)) {
498         libmv_marker_to_dna_marker(
499             &libmv_marker, context->frame_width, context->frame_height, &marker);
500         if (context->first_sync && frame == context->sync_frame) {
501           tracking_marker_insert_disabled(options->track, &marker, !context->backwards, false);
502         }
503         BKE_tracking_marker_insert(options->track, &marker);
504         tracking_marker_insert_disabled(options->track, &marker, context->backwards, false);
505       }
506     }
507   }
508   BLI_spin_unlock(&context->spin_lock);
509
510   for (int clip = 0; clip < context->num_clips; ++clip) {
511     MovieTracking *tracking = &context->clips[clip]->tracking;
512     BKE_tracking_dopesheet_tag_update(tracking);
513   }
514
515   context->sync_frame = newframe;
516   context->first_sync = false;
517 }
518
519 void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *user)
520 {
521   user->framenr = context->sync_frame;
522 }
523
524 void BKE_autotrack_context_finish(AutoTrackContext *context)
525 {
526   int clip_index;
527
528   for (clip_index = 0; clip_index < context->num_clips; ++clip_index) {
529     MovieClip *clip = context->clips[clip_index];
530     ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
531     MovieTrackingPlaneTrack *plane_track;
532
533     for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
534       if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
535         int track;
536         for (track = 0; track < context->num_tracks; ++track) {
537           if (BKE_tracking_plane_track_has_point_track(plane_track,
538                                                        context->options[track].track)) {
539             BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame);
540             break;
541           }
542         }
543       }
544     }
545   }
546 }
547
548 void BKE_autotrack_context_free(AutoTrackContext *context)
549 {
550   libmv_autoTrackDestroy(context->autotrack);
551   tracking_image_accessor_destroy(context->image_accessor);
552   MEM_freeN(context->options);
553   MEM_freeN(context->tracks);
554   BLI_spin_end(&context->spin_lock);
555   MEM_freeN(context);
556 }