Blender  V2.93
tracking_auto.c
Go to the documentation of this file.
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 
24 #include "atomic_ops.h"
25 #include <stdlib.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_listbase.h"
33 #include "BLI_math.h"
34 #include "BLI_task.h"
35 #include "BLI_threads.h"
36 #include "BLI_utildefines.h"
37 #include "PIL_time.h"
38 
39 #include "BKE_global.h"
40 #include "BKE_movieclip.h"
41 #include "BKE_tracking.h"
42 
43 #include "libmv-capi.h"
44 #include "tracking_private.h"
45 
46 typedef struct AutoTrackClip {
48 
49  /* Dimensions of movie frame, in pixels.
50  *
51  * NOTE: All frames within a clip are expected to have match3ed dimensions. */
52  int width, height;
54 
55 typedef struct AutoTrackTrack {
56  /* Index of a clip from `AutoTrackContext::autotrack_clips` this track belongs to. */
58 
60 
61  /* Options for the region tracker. */
63 
64  /* Denotes whether this track will be tracked.
65  * Is usually initialized based on track's selection. Non-trackable tracks are still added to the
66  * context to provide AutoTrack all knowledge about what is going on in the scene. */
69 
70 typedef struct AutoTrackMarker {
73 
74 /* Result of tracking step for a single marker.
75  *
76  * On success both marker and result are fully initialized to the position on the new frame.
77  *
78  * On failure marker's frame number is initialized to frame number where it was attempted to be
79  * tracked to. The position and other fields of tracked marker are the same as the input. */
80 typedef struct AutoTrackTrackingResult {
82 
83  bool success;
87 
88 typedef struct AutoTrackContext {
89  /* --------------------------------------------------------------------
90  * Invariant part.
91  * Stays unchanged during the tracking process.
92  * If not the initialization process, all the fields here should be treated as `const`.
93  */
94 
95  /* Frame at which tracking process started.
96  * NOTE: Measured in scene time frames, */
98 
99  /* True when tracking backwards (from higher frame number to lower frame number.) */
101 
102  /* Movie clips used during the tracking process. */
105 
106  /* Tracks for which the context has been created for.
107  * This is a flat array of all tracks coming from all clips, regardless of whether track is
108  * actually being tracked or not. This allows the AutoTrack to see a big picture of hat is going
109  * on in the scene, and request information it needs.
110  *
111  * Indexed by AutoTrackOptions::track_index. */
114 
115  /* Accessor for images of clip. Used by the autotrack context. */
117 
118  /* --------------------------------------------------------------------
119  * Variant part.
120  * Denotes tracing state and tracking result.
121  */
122 
123  /* Auto-track context.
124  *
125  * NOTE: Is accessed from multiple threads at once. */
127 
128  /* Markers from the current frame which will be tracked to the next frame upon the tracking
129  * context step.
130  *
131  * NOTE: This array is re-used across tracking steps, which might make it appear that the array
132  * is over-allocated when some tracks has failed to track. */
135 
136  /* Tracking results which are to be synchronized from the AutoTrack context to the Blender's
137  * DNA to make the results visible for users. */
140 
143 
144 /* -------------------------------------------------------------------- */
148 static void normalized_to_libmv_frame(const float normalized[2],
149  const int frame_dimensions[2],
150  float result[2])
151 {
152  result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
153  result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
154 }
155 
157  const float origin[2],
158  const int frame_dimensions[2],
159  float result[2])
160 {
161  result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
162  result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
163 }
164 
165 static void libmv_frame_to_normalized(const float frame_coord[2],
166  const int frame_dimensions[2],
167  float result[2])
168 {
169  result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
170  result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
171 }
172 
173 static void libmv_frame_to_normalized_relative(const float frame_coord[2],
174  const float origin[2],
175  const int frame_dimensions[2],
176  float result[2])
177 {
178  result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
179  result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
180 }
181 
184 /* -------------------------------------------------------------------- */
188 static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
189  const MovieTrackingMarker *marker,
190  int clip,
191  int track_index,
192  int frame_width,
193  int frame_height,
194  bool backwards,
195  libmv_Marker *libmv_marker)
196 {
197  const int frame_dimensions[2] = {frame_width, frame_height};
198  libmv_marker->clip = clip;
199  libmv_marker->frame = marker->framenr;
200  libmv_marker->track = track_index;
201 
202  normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
203  for (int i = 0; i < 4; i++) {
205  marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
206  }
207 
209  marker->search_min, marker->pos, frame_dimensions, libmv_marker->search_region_min);
210 
212  marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
213 
214  /* NOTE: All the markers does have 1.0 weight.
215  * Might support in the future, but will require more elaborated process which will involve
216  * F-Curve evaluation. */
217  libmv_marker->weight = 1.0f;
218 
219  if (marker->flag & MARKER_TRACKED) {
220  libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
221  }
222  else {
223  libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
224  }
225  libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
227  libmv_marker->model_id = 0;
228 
229  /* NOTE: We currently don't support reference marker from different clip. */
230  libmv_marker->reference_clip = clip;
231 
232  if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
233  const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
234  track, marker->framenr, backwards);
235  libmv_marker->reference_frame = keyframe_marker->framenr;
236  }
237  else {
238  libmv_marker->reference_frame = backwards ? marker->framenr - 1 : marker->framenr;
239  }
240 
241  libmv_marker->disabled_channels =
242  ((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
243  ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
245 }
246 
247 static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
248  int frame_width,
249  int frame_height,
250  MovieTrackingMarker *marker)
251 {
252  const int frame_dimensions[2] = {frame_width, frame_height};
253  marker->framenr = libmv_marker->frame;
254 
255  libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
256  for (int i = 0; i < 4; i++) {
257  libmv_frame_to_normalized_relative(libmv_marker->patch[i],
258  libmv_marker->center,
259  frame_dimensions,
260  marker->pattern_corners[i]);
261  }
262 
264  libmv_marker->search_region_min, libmv_marker->center, frame_dimensions, marker->search_min);
265 
267  libmv_marker->search_region_max, libmv_marker->center, frame_dimensions, marker->search_max);
268 
269  marker->flag = 0;
270  if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
271  marker->flag |= MARKER_TRACKED;
272  }
273  else {
274  marker->flag &= ~MARKER_TRACKED;
275  }
276 }
277 
280 /* -------------------------------------------------------------------- */
287 /* Returns false if marker crossed margin area from frame bounds. */
288 static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
289  int margin,
290  int frame_width,
291  int frame_height)
292 {
293  float patch_min[2], patch_max[2];
294  float margin_left, margin_top, margin_right, margin_bottom;
295 
296  INIT_MINMAX2(patch_min, patch_max);
297  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
298  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
299  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
300  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
301 
302  margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
303  margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
304  margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
305  margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
306 
307  if (libmv_marker->center[0] < margin_left ||
308  libmv_marker->center[0] > frame_width - margin_right ||
309  libmv_marker->center[1] < margin_bottom ||
310  libmv_marker->center[1] > frame_height - margin_top) {
311  return false;
312  }
313 
314  return true;
315 }
316 
319 /* -------------------------------------------------------------------- */
324 {
325  if ((marker->flag & MARKER_DISABLED)) {
326  return false;
327  }
328  return true;
329 }
330 
332  const AutoTrackTrack *autotrack_track)
333 {
334  /*const*/ MovieTrackingTrack *track = autotrack_track->track;
335  if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
336  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
337  MovieClip *clip = autotrack_clip->clip;
338  const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
339  clip, context->start_scene_frame);
340 
341  const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
342  return autotrack_is_marker_usable(marker);
343  }
344  return false;
345 }
346 
348  MovieClip *clip,
349  MovieClipUser *user)
350 {
351  /* NOTE: Currently only tracking within a single clip. */
352 
353  context->num_clips = 1;
354 
355  context->autotrack_clips[0].clip = clip;
357  clip, user, &context->autotrack_clips[0].width, &context->autotrack_clips[0].height);
358 }
359 
360 /* Initialize flat list of tracks for quick index-based access for the specified clip.
361  * All the tracks from this clip are added at the end of the array of already-collected tracks.
362  *
363  * NOTE: Clips should be initialized first. */
365 {
366  BLI_assert(clip_index >= 0);
367  BLI_assert(clip_index < context->num_clips);
368 
369  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
370  MovieClip *clip = autotrack_clip->clip;
371  MovieTracking *tracking = &clip->tracking;
372  ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
373 
374  const int num_clip_tracks = BLI_listbase_count(tracks_base);
375  if (num_clip_tracks == 0) {
376  return;
377  }
378 
379  context->all_autotrack_tracks = MEM_reallocN(context->all_autotrack_tracks,
380  (context->num_all_tracks + num_clip_tracks) *
381  sizeof(AutoTrackTrack));
382 
383  LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_base) {
384  AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[context->num_all_tracks++];
385  autotrack_track->clip_index = clip_index;
386  autotrack_track->track = track;
387  autotrack_track->is_trackable = autotrack_is_track_trackable(context, autotrack_track);
388 
390  track, NULL, context->is_backwards, &autotrack_track->track_region_options);
391  }
392 }
393 
394 /* Initialize flat list of tracks for quick index-based access for all clips used for tracking.
395  *
396  * NOTE: Clips should be initialized first. */
398 {
399  BLI_assert(context->num_clips >= 1);
400 
401  for (int clip_index = 0; clip_index < context->num_clips; ++clip_index) {
403  }
404 }
405 
406 /* NOTE: Clips should be initialized first. */
408 {
409  BLI_assert(context->num_clips >= 1);
410 
411  /* Planarize arrays of clips and tracks, storing pointers to their base "objects".
412  * This allows image accessor to be independent, but adds some overhead here. Could be solved
413  * by either more strongly coupling accessor API with the AutoTrack, or by giving some functors
414  * to the accessor to access clip/track from their indices. */
415 
417  for (int i = 0; i < context->num_clips; ++i) {
418  clips[i] = context->autotrack_clips[i].clip;
419  }
420 
422  context->num_all_tracks, sizeof(MovieTrackingTrack *), "image accessor init tracks");
423  for (int i = 0; i < context->num_all_tracks; ++i) {
424  tracks[i] = context->all_autotrack_tracks[i].track;
425  }
426 
427  context->image_accessor = tracking_image_accessor_new(clips, 1, tracks, context->num_all_tracks);
428 
429  MEM_freeN(tracks);
430 }
431 
432 /* Count markers which are usable to be passed to the AutoTrack context. */
434 {
435  size_t num_usable_markers = 0;
436  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
437  const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
438  for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
439  const MovieTrackingMarker *marker = &track->markers[marker_index];
440  if (!autotrack_is_marker_usable(marker)) {
441  continue;
442  }
443  num_usable_markers++;
444  }
445  }
446  return num_usable_markers;
447 }
448 
450 {
451  int num_trackable_markers = 0;
452  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
453  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
454  if (!autotrack_track->is_trackable) {
455  continue;
456  }
457  num_trackable_markers++;
458  }
459  return num_trackable_markers;
460 }
461 
462 /* Provide Libmv side of auto track all information about given tracks.
463  * Information from all clips is passed to the auto tracker.
464  *
465  * NOTE: Clips and all tracks are to be initialized before calling this. */
467 {
468  context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor);
469 
470  /* Count number of markers to be put to a context. */
471  const size_t num_trackable_markers = autotrack_count_all_usable_markers(context);
472  if (num_trackable_markers == 0) {
473  return;
474  }
475 
476  /* Allocate memory for all the markers. */
477  libmv_Marker *libmv_markers = MEM_malloc_arrayN(
478  sizeof(libmv_Marker), num_trackable_markers, "libmv markers array");
479 
480  /* Fill in markers array. */
481  int num_filled_libmv_markers = 0;
482  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
483  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
484  /*const*/ MovieTrackingTrack *track = autotrack_track->track;
485  for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
486  /*const*/ MovieTrackingMarker *marker = &track->markers[marker_index];
487  if (!autotrack_is_marker_usable(marker)) {
488  continue;
489  }
490  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
492  marker,
493  autotrack_track->clip_index,
494  track_index,
495  autotrack_clip->width,
496  autotrack_clip->height,
497  context->is_backwards,
498  &libmv_markers[num_filled_libmv_markers++]);
499  }
500  }
501 
502  /* Add all markers to autotrack. */
503  libmv_autoTrackSetMarkers(context->autotrack, libmv_markers, num_trackable_markers);
504 
505  /* Free temporary memory. */
506  MEM_freeN(libmv_markers);
507 }
508 
510 {
511  /* Count number of trackable tracks. */
512  context->num_autotrack_markers = autotrack_count_trackable_markers(context);
513  if (context->num_autotrack_markers == 0) {
514  return;
515  }
516 
517  /* Allocate required memory. */
518  context->autotrack_markers = MEM_calloc_arrayN(
519  sizeof(AutoTrackMarker), context->num_autotrack_markers, "auto track options");
520 
521  /* Fill in all the markers. */
522  int autotrack_marker_index = 0;
523  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
524  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
525  if (!autotrack_track->is_trackable) {
526  continue;
527  }
528 
529  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
530  MovieClip *clip = autotrack_clip->clip;
531  const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
532  clip, context->start_scene_frame);
533 
534  /*const*/ MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
535  const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
536 
537  AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
539  marker,
540  autotrack_track->clip_index,
541  track_index,
542  autotrack_clip->width,
543  autotrack_clip->height,
544  context->is_backwards,
545  &autotrack_marker->libmv_marker);
546  }
547 }
548 
550  MovieClipUser *user,
551  const bool is_backwards)
552 {
553  AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), "autotrack context");
554 
555  context->start_scene_frame = user->framenr;
556  context->is_backwards = is_backwards;
557  context->synchronized_scene_frame = context->start_scene_frame;
558 
564 
565  BLI_spin_init(&context->spin_lock);
566 
567  return context;
568 }
569 
572 /* -------------------------------------------------------------------- */
576 /* NOTE: This is a TLS in a sense that this struct is never accessed from multiple threads, and
577  * that threads are re-using the struct as much as possible. */
578 typedef struct AutoTrackTLS {
579  ListBase results; /* Elements of `AutoTrackTrackingResult`. */
581 
582 static void autotrack_context_step_cb(void *__restrict userdata,
583  const int marker_index,
584  const TaskParallelTLS *__restrict tls)
585 {
586  AutoTrackContext *context = userdata;
587  AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
588 
589  const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[marker_index];
590  const libmv_Marker *libmv_current_marker = &autotrack_marker->libmv_marker;
591 
592  const int frame_delta = context->is_backwards ? -1 : 1;
593  const int clip_index = libmv_current_marker->clip;
594  const int track_index = libmv_current_marker->track;
595 
596  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
597  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
598  const MovieTrackingTrack *track = autotrack_track->track;
599 
600  /* Check whether marker is going outside of allowed frame margin. */
602  libmv_current_marker, track->margin, autotrack_clip->width, autotrack_clip->height)) {
603  return;
604  }
605 
606  const int new_marker_frame = libmv_current_marker->frame + frame_delta;
607 
608  AutoTrackTrackingResult *autotrack_result = MEM_mallocN(sizeof(AutoTrackTrackingResult),
609  "autotrack result");
610  autotrack_result->libmv_marker = *libmv_current_marker;
611  autotrack_result->libmv_marker.frame = new_marker_frame;
612 
613  /* Update reference frame. */
614  libmv_Marker libmv_reference_marker;
615  if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
616  autotrack_result->libmv_marker.reference_frame = libmv_current_marker->reference_frame;
618  clip_index,
619  autotrack_result->libmv_marker.reference_frame,
620  track_index,
621  &libmv_reference_marker);
622  }
623  else {
624  BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
625  autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
626  libmv_reference_marker = *libmv_current_marker;
627  }
628 
629  /* Perform actual tracking. */
630  autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
631  &autotrack_track->track_region_options,
632  &autotrack_result->libmv_marker,
633  &autotrack_result->libmv_result);
634 
635  /* If tracking failed restore initial position.
636  * This is how Blender side is currently expecting failed track to be handled. Without this the
637  * marker is left in an arbitrary position which did not provide good correlation. */
638  if (!autotrack_result->success) {
639  autotrack_result->libmv_marker = *libmv_current_marker;
640  autotrack_result->libmv_marker.frame = new_marker_frame;
641  }
642 
643  BLI_addtail(&autotrack_tls->results, autotrack_result);
644 }
645 
646 static void autotrack_context_reduce(const void *__restrict UNUSED(userdata),
647  void *__restrict chunk_join,
648  void *__restrict chunk)
649 {
650  AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)chunk;
651  if (BLI_listbase_is_empty(&autotrack_tls->results)) {
652  /* Nothing to be joined from. */
653  return;
654  }
655 
656  AutoTrackTLS *autotrack_tls_join = (AutoTrackTLS *)chunk_join;
657  BLI_movelisttolist(&autotrack_tls_join->results, &autotrack_tls->results);
658 }
659 
661 {
662  if (context->num_autotrack_markers == 0) {
663  return false;
664  }
665 
666  AutoTrackTLS tls;
668 
669  TaskParallelSettings settings;
671  settings.use_threading = (context->num_autotrack_markers > 1);
672  settings.userdata_chunk = &tls;
673  settings.userdata_chunk_size = sizeof(AutoTrackTLS);
675 
677  0, context->num_autotrack_markers, context, autotrack_context_step_cb, &settings);
678 
679  /* Prepare next tracking step by updating the AutoTrack context with new markers and moving
680  * tracked markers as an input for the next iteration. */
681  context->num_autotrack_markers = 0;
682  LISTBASE_FOREACH (AutoTrackTrackingResult *, autotrack_result, &tls.results) {
683  if (!autotrack_result->success) {
684  continue;
685  }
686 
687  /* Insert tracking results to the AutoTrack context to make them usable for the next frame
688  * tracking iteration. */
689  libmv_autoTrackAddMarker(context->autotrack, &autotrack_result->libmv_marker);
690 
691  /* Update the list of markers which will be tracked on the next iteration. */
692  context->autotrack_markers[context->num_autotrack_markers++].libmv_marker =
693  autotrack_result->libmv_marker;
694  }
695 
696  BLI_spin_lock(&context->spin_lock);
697  BLI_movelisttolist(&context->results_to_sync, &tls.results);
698  BLI_spin_unlock(&context->spin_lock);
699 
700  return true;
701 }
702 
705 /* -------------------------------------------------------------------- */
714 {
715  const int frame_delta = context->is_backwards ? -1 : 1;
716 
717  BLI_spin_lock(&context->spin_lock);
718  ListBase results_to_sync = context->results_to_sync;
719  BLI_listbase_clear(&context->results_to_sync);
720  BLI_spin_unlock(&context->spin_lock);
721 
722  LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
723  const libmv_Marker *libmv_marker = &autotrack_result->libmv_marker;
724  const int clip_index = libmv_marker->clip;
725  const int track_index = libmv_marker->track;
726  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
727  const MovieClip *clip = autotrack_clip->clip;
728  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
729  MovieTrackingTrack *track = autotrack_track->track;
730 
731  const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
732  clip, context->start_scene_frame);
733  const int first_result_frame = start_clip_frame + frame_delta;
734 
735  /* Insert marker which corresponds to the tracking result. */
736  MovieTrackingMarker marker;
738  &autotrack_result->libmv_marker, autotrack_clip->width, autotrack_clip->height, &marker);
739  if (!autotrack_result->success) {
740  marker.flag |= MARKER_DISABLED;
741  }
742  BKE_tracking_marker_insert(track, &marker);
743 
744  /* Insert disabled marker at the end of tracked segment.
745  * When tracking forward the disabled marker is added at the next frame from the result,
746  * when tracking backwards the marker is added at the previous frame. */
747  tracking_marker_insert_disabled(track, &marker, context->is_backwards, false);
748 
749  if (marker.framenr == first_result_frame) {
751  track, marker.framenr - frame_delta);
752  BLI_assert(prev_marker != NULL);
753 
754  tracking_marker_insert_disabled(track, prev_marker, !context->is_backwards, false);
755  }
756 
757  /* Update synchronized frame to the latest tracked fame from the current results. */
758  const int marker_scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, marker.framenr);
759  if (context->is_backwards) {
760  context->synchronized_scene_frame = min_ii(context->synchronized_scene_frame,
761  marker_scene_frame);
762  }
763  else {
764  context->synchronized_scene_frame = max_ii(context->synchronized_scene_frame,
765  marker_scene_frame);
766  }
767 
768  MEM_freeN(autotrack_result);
769  }
770 
771  for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
772  MovieTracking *tracking = &context->autotrack_clips[clip_index].clip->tracking;
774  }
775 }
776 
777 /* TODO(sergey): Find a way to avoid this, somehow making all needed logic in
778  * BKE_autotrack_context_sync(). */
780 {
781  user->framenr = context->synchronized_scene_frame;
782 }
783 
786 /* -------------------------------------------------------------------- */
791 {
792  for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
793  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
794  MovieClip *clip = autotrack_clip->clip;
795  ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
796  const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
797  clip, context->start_scene_frame);
798 
799  LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
800  if ((plane_track->flag & PLANE_TRACK_AUTOKEY)) {
801  continue;
802  }
803  for (int track_index = 0; track_index < context->num_all_tracks; track_index++) {
804  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
805  if (!autotrack_track->is_trackable) {
806  continue;
807  }
808  MovieTrackingTrack *track = autotrack_track->track;
809  if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
810  BKE_tracking_track_plane_from_existing_motion(plane_track, start_clip_frame);
811  break;
812  }
813  }
814  }
815  }
816 }
817 
819 {
820  if (context->autotrack != NULL) {
821  libmv_autoTrackDestroy(context->autotrack);
822  }
823 
824  if (context->image_accessor != NULL) {
825  tracking_image_accessor_destroy(context->image_accessor);
826  }
827 
828  MEM_SAFE_FREE(context->all_autotrack_tracks);
829  MEM_SAFE_FREE(context->autotrack_markers);
830 
831  BLI_freelistN(&context->results_to_sync);
832 
833  BLI_spin_end(&context->spin_lock);
834 
836 }
837 
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height)
Definition: movieclip.c:1540
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct ListBase * BKE_tracking_get_active_tracks(struct MovieTracking *tracking)
Definition: tracking.c:365
struct MovieTrackingMarker * BKE_tracking_marker_insert(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker)
Definition: tracking.c:1383
#define TRACK_SELECTED(track)
Definition: BKE_tracking.h:489
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking)
Definition: tracking.c:3321
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1556
void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame)
struct ListBase * BKE_tracking_get_active_plane_tracks(struct MovieTracking *tracking)
Definition: tracking.c:377
bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingTrack *track)
Definition: tracking.c:1844
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1523
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:1043
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:111
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define INIT_MINMAX2(min, max)
#define UNUSED(x)
Object is a sort of wrapper for general info.
@ TRACK_DISABLE_BLUE
@ TRACK_HIDDEN
@ TRACK_LOCKED
@ TRACK_DISABLE_RED
@ TRACK_DISABLE_GREEN
@ PLANE_TRACK_AUTOKEY
@ MARKER_TRACKED
@ MARKER_DISABLED
@ TRACK_MATCH_PREVIOS_FRAME
@ TRACK_MATCH_KEYFRAME
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Platform independent time functions.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
SIMD_FORCE_INLINE btVector3 normalized() const
Return a normalized version of this vector.
void libmv_autoTrackSetMarkers(libmv_AutoTrack *libmv_autotrack, const libmv_Marker *libmv_marker, size_t num_markers)
libmv_AutoTrack * libmv_autoTrackNew(libmv_FrameAccessor *frame_accessor)
int libmv_autoTrackMarker(libmv_AutoTrack *libmv_autotrack, const libmv_TrackRegionOptions *libmv_options, libmv_Marker *libmv_tracked_marker, libmv_TrackRegionResult *libmv_result)
void libmv_autoTrackDestroy(libmv_AutoTrack *libmv_autotrack)
int libmv_autoTrackGetMarker(libmv_AutoTrack *libmv_autotrack, int clip, int frame, int track, libmv_Marker *libmv_marker)
void libmv_autoTrackAddMarker(libmv_AutoTrack *libmv_autotrack, const libmv_Marker *libmv_marker)
struct libmv_AutoTrack libmv_AutoTrack
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
struct SELECTID_Context context
Definition: select_engine.c:47
MovieClip * clip
Definition: tracking_auto.c:47
AutoTrackMarker * autotrack_markers
TrackingImageAccessor * image_accessor
AutoTrackTrack * all_autotrack_tracks
ListBase results_to_sync
struct libmv_AutoTrack * autotrack
AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP]
libmv_Marker libmv_marker
Definition: tracking_auto.c:71
ListBase results
libmv_TrackRegionOptions track_region_options
Definition: tracking_auto.c:62
MovieTrackingTrack * track
Definition: tracking_auto.c:59
libmv_TrackRegionResult libmv_result
Definition: tracking_auto.c:85
struct AutoTrackTrackingResult * next
Definition: tracking_auto.c:81
struct AutoTrackTrackingResult * prev
Definition: tracking_auto.c:81
libmv_Marker libmv_marker
Definition: tracking_auto.c:84
struct MovieTracking tracking
MovieTrackingMarker * markers
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:158
size_t userdata_chunk_size
Definition: BLI_task.h:150
int track
Definition: tracksN.h:65
float search_region_max[2]
Definition: tracksN.h:69
float center[2]
Definition: tracksN.h:66
float search_region_min[2]
Definition: tracksN.h:68
int frame
Definition: tracksN.h:64
int disabled_channels
Definition: tracksN.h:77
libmv_MarkerModelType model_type
Definition: tracksN.h:75
float patch[4][2]
Definition: tracksN.h:67
int reference_frame
Definition: tracksN.h:74
int reference_clip
Definition: tracksN.h:73
float weight
Definition: tracksN.h:70
libmv_MarkerSource source
Definition: tracksN.h:71
int clip
Definition: tracksN.h:63
int model_id
Definition: tracksN.h:76
libmv_MarkerStatus status
Definition: tracksN.h:72
ListBase tracks
Definition: tracking.c:75
bool BKE_autotrack_context_step(AutoTrackContext *context)
static void autotrack_context_reduce(const void *__restrict UNUSED(userdata), void *__restrict chunk_join, void *__restrict chunk)
static void dna_marker_to_libmv_marker(MovieTrackingTrack *track, const MovieTrackingMarker *marker, int clip, int track_index, int frame_width, int frame_height, bool backwards, libmv_Marker *libmv_marker)
struct AutoTrackTrack AutoTrackTrack
struct AutoTrackClip AutoTrackClip
static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker, int frame_width, int frame_height, MovieTrackingMarker *marker)
static void autotrack_context_step_cb(void *__restrict userdata, const int marker_index, const TaskParallelTLS *__restrict tls)
static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
static int autotrack_count_trackable_markers(AutoTrackContext *context)
void BKE_autotrack_context_sync(AutoTrackContext *context)
static void libmv_frame_to_normalized_relative(const float frame_coord[2], const float origin[2], const int frame_dimensions[2], float result[2])
AutoTrackContext * BKE_autotrack_context_new(MovieClip *clip, MovieClipUser *user, const bool is_backwards)
static void normalized_relative_to_libmv_frame(const float normalized[2], const float origin[2], const int frame_dimensions[2], float result[2])
static void normalized_to_libmv_frame(const float normalized[2], const int frame_dimensions[2], float result[2])
struct AutoTrackContext AutoTrackContext
static void autotrack_context_init_image_accessor(AutoTrackContext *context)
static void autotrack_context_init_markers(AutoTrackContext *context)
void BKE_autotrack_context_free(AutoTrackContext *context)
static bool autotrack_is_track_trackable(const AutoTrackContext *context, const AutoTrackTrack *autotrack_track)
static void autotrack_context_init_tracks_for_clip(AutoTrackContext *context, int clip_index)
struct AutoTrackMarker AutoTrackMarker
void BKE_autotrack_context_finish(AutoTrackContext *context)
static size_t autotrack_count_all_usable_markers(AutoTrackContext *context)
static void autotrack_context_init_autotrack(AutoTrackContext *context)
void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *user)
struct AutoTrackTrackingResult AutoTrackTrackingResult
static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker, int margin, int frame_width, int frame_height)
static void autotrack_context_init_clips(AutoTrackContext *context, MovieClip *clip, MovieClipUser *user)
static void libmv_frame_to_normalized(const float frame_coord[2], const int frame_dimensions[2], float result[2])
struct AutoTrackTLS AutoTrackTLS
static void autotrack_context_init_tracks(AutoTrackContext *context)
#define MAX_ACCESSOR_CLIP
void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, const bool is_backwards, libmv_TrackRegionOptions *options)
void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, bool before, bool overwrite)
MovieTrackingMarker * tracking_get_keyframed_marker(MovieTrackingTrack *track, int current_frame, bool backwards)
TrackingImageAccessor * tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, MovieTrackingTrack **tracks, int num_tracks)
void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
@ LIBMV_MARKER_CHANNEL_B
Definition: tracksN.h:59
@ LIBMV_MARKER_CHANNEL_G
Definition: tracksN.h:58
@ LIBMV_MARKER_CHANNEL_R
Definition: tracksN.h:57
@ LIBMV_MARKER_SOURCE_TRACKED
Definition: tracksN.h:38
@ LIBMV_MARKER_SOURCE_MANUAL
Definition: tracksN.h:36
@ LIBMV_MARKER_STATUS_UNKNOWN
Definition: tracksN.h:44
@ LIBMV_MARKER_MODEL_TYPE_POINT
Definition: tracksN.h:50