Blender  V3.3
tracking_auto.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. All rights reserved. */
3 
8 #include "atomic_ops.h"
9 #include <stdlib.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_movieclip_types.h"
14 #include "DNA_object_types.h" /* SELECT */
15 
16 #include "BLI_listbase.h"
17 #include "BLI_math.h"
18 #include "BLI_task.h"
19 #include "BLI_threads.h"
20 #include "BLI_utildefines.h"
21 #include "PIL_time.h"
22 
23 #include "BKE_global.h"
24 #include "BKE_movieclip.h"
25 #include "BKE_tracking.h"
26 
27 #include "IMB_imbuf.h"
28 #include "IMB_imbuf_types.h"
29 
30 #include "libmv-capi.h"
31 #include "tracking_private.h"
32 
33 typedef struct AutoTrackClip {
35 
36  /* Dimensions of movie frame, in pixels.
37  *
38  * NOTE: All frames within a clip are expected to have match3ed dimensions. */
39  int width, height;
41 
42 typedef struct AutoTrackTrack {
43  /* Index of a clip from `AutoTrackContext::autotrack_clips` this track belongs to. */
45 
47 
48  /* Options for the region tracker. */
50 
51  /* Denotes whether this track will be tracked.
52  * Is usually initialized based on track's selection. Non-trackable tracks are still added to the
53  * context to provide AutoTrack all knowledge about what is going on in the scene. */
56 
57 typedef struct AutoTrackMarker {
60 
61 /* Result of tracking step for a single marker.
62  *
63  * On success both marker and result are fully initialized to the position on the new frame.
64  *
65  * On failure marker's frame number is initialized to frame number where it was attempted to be
66  * tracked to. The position and other fields of tracked marker are the same as the input. */
67 typedef struct AutoTrackTrackingResult {
69 
70  bool success;
74 
75 typedef struct AutoTrackContext {
76  /* --------------------------------------------------------------------
77  * Invariant part.
78  * Stays unchanged during the tracking process.
79  * If not the initialization process, all the fields here should be treated as `const`.
80  */
81 
82  /* Frame at which tracking process started.
83  * NOTE: Measured in scene time frames, */
85 
86  /* True when tracking backwards (from higher frame number to lower frame number.) */
88 
89  /* Movie clips used during the tracking process. */
90  int num_clips;
92 
93  /* Tracks for which the context has been created for.
94  * This is a flat array of all tracks coming from all clips, regardless of whether track is
95  * actually being tracked or not. This allows the AutoTrack to see a big picture of hat is going
96  * on in the scene, and request information it needs.
97  *
98  * Indexed by AutoTrackOptions::track_index. */
101 
102  /* Accessor for images of clip. Used by the autotrack context. */
104 
105  /* Image buffers acquired for markers which are using keyframe pattern matching.
106  * These image buffers are user-referenced and flagged as persistent so that they don't get
107  * removed from the movie cache during tracking. */
110 
111  /* --------------------------------------------------------------------
112  * Variant part.
113  * Denotes tracing state and tracking result.
114  */
115 
116  /* Auto-track context.
117  *
118  * NOTE: Is accessed from multiple threads at once. */
120 
121  /* Markers from the current frame which will be tracked to the next frame upon the tracking
122  * context step.
123  *
124  * NOTE: This array is re-used across tracking steps, which might make it appear that the array
125  * is over-allocated when some tracks has failed to track. */
128 
129  /* Tracking results which are to be synchronized from the AutoTrack context to the Blender's
130  * DNA to make the results visible for users. */
133 
136 
137 /* -------------------------------------------------------------------- */
141 static void normalized_to_libmv_frame(const float normalized[2],
142  const int frame_dimensions[2],
143  float result[2])
144 {
145  result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
146  result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
147 }
148 
150  const float origin[2],
151  const int frame_dimensions[2],
152  float result[2])
153 {
154  result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
155  result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
156 }
157 
158 static void libmv_frame_to_normalized(const float frame_coord[2],
159  const int frame_dimensions[2],
160  float result[2])
161 {
162  result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
163  result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
164 }
165 
166 static void libmv_frame_to_normalized_relative(const float frame_coord[2],
167  const float origin[2],
168  const int frame_dimensions[2],
169  float result[2])
170 {
171  result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
172  result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
173 }
174 
177 /* -------------------------------------------------------------------- */
181 static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
182  const MovieTrackingMarker *marker,
183  int clip,
184  int track_index,
185  int frame_width,
186  int frame_height,
187  bool backwards,
188  libmv_Marker *libmv_marker)
189 {
190  const int frame_dimensions[2] = {frame_width, frame_height};
191  libmv_marker->clip = clip;
192  libmv_marker->frame = marker->framenr;
193  libmv_marker->track = track_index;
194 
195  normalized_to_libmv_frame(marker->pos, frame_dimensions, libmv_marker->center);
196  for (int i = 0; i < 4; i++) {
198  marker->pattern_corners[i], marker->pos, frame_dimensions, libmv_marker->patch[i]);
199  }
200 
202  marker->search_min, marker->pos, frame_dimensions, libmv_marker->search_region_min);
203 
205  marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
206 
207  /* NOTE: All the markers does have 1.0 weight.
208  * Might support in the future, but will require more elaborated process which will involve
209  * F-Curve evaluation. */
210  libmv_marker->weight = 1.0f;
211 
212  if (marker->flag & MARKER_TRACKED) {
213  libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
214  }
215  else {
216  libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
217  }
218  libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
220  libmv_marker->model_id = 0;
221 
222  /* NOTE: We currently don't support reference marker from different clip. */
223  libmv_marker->reference_clip = clip;
224 
225  if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
226  const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
227  track, marker->framenr, backwards);
228  libmv_marker->reference_frame = keyframe_marker->framenr;
229  }
230  else {
231  libmv_marker->reference_frame = backwards ? marker->framenr - 1 : marker->framenr;
232  }
233 
234  libmv_marker->disabled_channels =
235  ((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
236  ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
238 }
239 
240 static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
241  int frame_width,
242  int frame_height,
243  MovieTrackingMarker *marker)
244 {
245  const int frame_dimensions[2] = {frame_width, frame_height};
246  marker->framenr = libmv_marker->frame;
247 
248  libmv_frame_to_normalized(libmv_marker->center, frame_dimensions, marker->pos);
249  for (int i = 0; i < 4; i++) {
250  libmv_frame_to_normalized_relative(libmv_marker->patch[i],
251  libmv_marker->center,
252  frame_dimensions,
253  marker->pattern_corners[i]);
254  }
255 
257  libmv_marker->search_region_min, libmv_marker->center, frame_dimensions, marker->search_min);
258 
260  libmv_marker->search_region_max, libmv_marker->center, frame_dimensions, marker->search_max);
261 
262  marker->flag = 0;
263  if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
264  marker->flag |= MARKER_TRACKED;
265  }
266  else {
267  marker->flag &= ~MARKER_TRACKED;
268  }
269 }
270 
273 /* -------------------------------------------------------------------- */
280 /* Returns false if marker crossed margin area from frame bounds. */
281 static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
282  int margin,
283  int frame_width,
284  int frame_height)
285 {
286  float patch_min[2], patch_max[2];
287  float margin_left, margin_top, margin_right, margin_bottom;
288 
289  INIT_MINMAX2(patch_min, patch_max);
290  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
291  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
292  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
293  minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
294 
295  margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
296  margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
297  margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
298  margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
299 
300  if (libmv_marker->center[0] < margin_left ||
301  libmv_marker->center[0] > frame_width - margin_right ||
302  libmv_marker->center[1] < margin_bottom ||
303  libmv_marker->center[1] > frame_height - margin_top) {
304  return false;
305  }
306 
307  return true;
308 }
309 
312 /* -------------------------------------------------------------------- */
317 {
318  if (marker->flag & MARKER_DISABLED) {
319  return false;
320  }
321  return true;
322 }
323 
325  const AutoTrackTrack *autotrack_track)
326 {
327  /*const*/ MovieTrackingTrack *track = autotrack_track->track;
328  if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
329  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
330  MovieClip *clip = autotrack_clip->clip;
331  const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
332  clip, context->start_scene_frame);
333 
334  const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
335  return autotrack_is_marker_usable(marker);
336  }
337  return false;
338 }
339 
341  MovieClip *clip,
342  MovieClipUser *user)
343 {
344  /* NOTE: Currently only tracking within a single clip. */
345 
346  context->num_clips = 1;
347 
348  context->autotrack_clips[0].clip = clip;
350  clip, user, &context->autotrack_clips[0].width, &context->autotrack_clips[0].height);
351 }
352 
353 /* Initialize flat list of tracks for quick index-based access for the specified clip.
354  * All the tracks from this clip are added at the end of the array of already-collected tracks.
355  *
356  * NOTE: Clips should be initialized first. */
358 {
359  BLI_assert(clip_index >= 0);
360  BLI_assert(clip_index < context->num_clips);
361 
362  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
363  MovieClip *clip = autotrack_clip->clip;
364  MovieTracking *tracking = &clip->tracking;
365  ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
366 
367  const int num_clip_tracks = BLI_listbase_count(tracks_base);
368  if (num_clip_tracks == 0) {
369  return;
370  }
371 
372  context->all_autotrack_tracks = MEM_reallocN(context->all_autotrack_tracks,
373  (context->num_all_tracks + num_clip_tracks) *
374  sizeof(AutoTrackTrack));
375 
376  LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_base) {
377  AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[context->num_all_tracks++];
378  autotrack_track->clip_index = clip_index;
379  autotrack_track->track = track;
380  autotrack_track->is_trackable = autotrack_is_track_trackable(context, autotrack_track);
381 
383  track, NULL, context->is_backwards, &autotrack_track->track_region_options);
384  }
385 }
386 
387 /* Initialize flat list of tracks for quick index-based access for all clips used for tracking.
388  *
389  * NOTE: Clips should be initialized first. */
391 {
392  BLI_assert(context->num_clips >= 1);
393 
394  for (int clip_index = 0; clip_index < context->num_clips; ++clip_index) {
396  }
397 }
398 
399 /* NOTE: Clips should be initialized first. */
401 {
402  BLI_assert(context->num_clips >= 1);
403 
404  /* Planarize arrays of clips and tracks, storing pointers to their base "objects".
405  * This allows image accessor to be independent, but adds some overhead here. Could be solved
406  * by either more strongly coupling accessor API with the AutoTrack, or by giving some functors
407  * to the accessor to access clip/track from their indices. */
408 
410  for (int i = 0; i < context->num_clips; ++i) {
411  clips[i] = context->autotrack_clips[i].clip;
412  }
413 
415  context->num_all_tracks, sizeof(MovieTrackingTrack *), "image accessor init tracks");
416  for (int i = 0; i < context->num_all_tracks; ++i) {
417  tracks[i] = context->all_autotrack_tracks[i].track;
418  }
419 
420  context->image_accessor = tracking_image_accessor_new(clips, 1, tracks, context->num_all_tracks);
421 
422  MEM_freeN(tracks);
423 }
424 
425 /* Count markers which are usable to be passed to the AutoTrack context. */
427 {
428  size_t num_usable_markers = 0;
429  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
430  const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
431  for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
432  const MovieTrackingMarker *marker = &track->markers[marker_index];
433  if (!autotrack_is_marker_usable(marker)) {
434  continue;
435  }
436  num_usable_markers++;
437  }
438  }
439  return num_usable_markers;
440 }
441 
443 {
444  int num_trackable_markers = 0;
445  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
446  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
447  if (!autotrack_track->is_trackable) {
448  continue;
449  }
450  num_trackable_markers++;
451  }
452  return num_trackable_markers;
453 }
454 
455 /* Provide Libmv side of auto track all information about given tracks.
456  * Information from all clips is passed to the auto tracker.
457  *
458  * NOTE: Clips and all tracks are to be initialized before calling this. */
460 {
461  context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor);
462 
463  /* Count number of markers to be put to a context. */
464  const size_t num_trackable_markers = autotrack_count_all_usable_markers(context);
465  if (num_trackable_markers == 0) {
466  return;
467  }
468 
469  /* Allocate memory for all the markers. */
470  libmv_Marker *libmv_markers = MEM_malloc_arrayN(
471  num_trackable_markers, sizeof(libmv_Marker), "libmv markers array");
472 
473  /* Fill in markers array. */
474  int num_filled_libmv_markers = 0;
475  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
476  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
477  /*const*/ MovieTrackingTrack *track = autotrack_track->track;
478  for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
479  /*const*/ MovieTrackingMarker *marker = &track->markers[marker_index];
480  if (!autotrack_is_marker_usable(marker)) {
481  continue;
482  }
483  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
485  marker,
486  autotrack_track->clip_index,
487  track_index,
488  autotrack_clip->width,
489  autotrack_clip->height,
490  context->is_backwards,
491  &libmv_markers[num_filled_libmv_markers++]);
492  }
493  }
494 
495  /* Add all markers to autotrack. */
496  libmv_autoTrackSetMarkers(context->autotrack, libmv_markers, num_trackable_markers);
497 
498  /* Free temporary memory. */
499  MEM_freeN(libmv_markers);
500 }
501 
503 {
504  /* Count number of trackable tracks. */
505  context->num_autotrack_markers = autotrack_count_trackable_markers(context);
506  if (context->num_autotrack_markers == 0) {
507  return;
508  }
509 
510  /* Allocate required memory. */
511  context->autotrack_markers = MEM_calloc_arrayN(
512  context->num_autotrack_markers, sizeof(AutoTrackMarker), "auto track options");
513 
514  /* Fill in all the markers. */
515  int autotrack_marker_index = 0;
516  for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
517  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
518  if (!autotrack_track->is_trackable) {
519  continue;
520  }
521 
522  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
523  MovieClip *clip = autotrack_clip->clip;
524  const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
525  clip, context->start_scene_frame);
526 
527  /*const*/ MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
528  const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
529 
530  AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
532  marker,
533  autotrack_track->clip_index,
534  track_index,
535  autotrack_clip->width,
536  autotrack_clip->height,
537  context->is_backwards,
538  &autotrack_marker->libmv_marker);
539  }
540 }
541 
543  MovieClipUser *user,
544  const bool is_backwards)
545 {
546  AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), "autotrack context");
547 
548  context->start_scene_frame = user->framenr;
549  context->is_backwards = is_backwards;
550  context->synchronized_scene_frame = context->start_scene_frame;
551 
557 
558  BLI_spin_init(&context->spin_lock);
559 
560  return context;
561 }
562 
565 /* -------------------------------------------------------------------- */
572 {
573  /* NOTE: This is potentially over-allocating, but it simplifies memory manipulation.
574  * In practice this is unlikely to be noticed in the profiler as the memory footprint of this
575  * data is way less of what the tracking process will use. */
576  context->referenced_image_buffers = MEM_calloc_arrayN(
577  context->num_autotrack_markers, sizeof(ImBuf *), __func__);
578 
579  context->num_referenced_image_buffers = 0;
580 
581  for (int i = 0; i < context->num_autotrack_markers; ++i) {
582  const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[i];
583  const int clip_index = autotrack_marker->libmv_marker.clip;
584  const int track_index = autotrack_marker->libmv_marker.track;
585 
586  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
587  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
588  const MovieTrackingTrack *track = autotrack_track->track;
589 
590  if (track->pattern_match != TRACK_MATCH_KEYFRAME) {
591  continue;
592  }
593 
594  const int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(
595  autotrack_clip->clip, autotrack_marker->libmv_marker.reference_frame);
596 
597  MovieClipUser user_at_keyframe;
598  BKE_movieclip_user_set_frame(&user_at_keyframe, scene_frame);
599  user_at_keyframe.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
600  user_at_keyframe.render_flag = 0;
601 
602  /* Keep reference to the image buffer so that we can manipulate its flags later on.
603  * Also request the movie cache to not remove the image buffer from the cache. */
604  ImBuf *ibuf = BKE_movieclip_get_ibuf(autotrack_clip->clip, &user_at_keyframe);
605  ibuf->userflags |= IB_PERSISTENT;
606 
607  context->referenced_image_buffers[context->num_referenced_image_buffers++] = ibuf;
608  }
609 }
610 
612 {
614 }
615 
618 /* -------------------------------------------------------------------- */
622 /* NOTE: This is a TLS in a sense that this struct is never accessed from multiple threads, and
623  * that threads are re-using the struct as much as possible. */
624 typedef struct AutoTrackTLS {
625  ListBase results; /* Elements of `AutoTrackTrackingResult`. */
627 
628 static void autotrack_context_step_cb(void *__restrict userdata,
629  const int marker_index,
630  const TaskParallelTLS *__restrict tls)
631 {
632  AutoTrackContext *context = userdata;
633  AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
634 
635  const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[marker_index];
636  const libmv_Marker *libmv_current_marker = &autotrack_marker->libmv_marker;
637 
638  const int frame_delta = context->is_backwards ? -1 : 1;
639  const int clip_index = libmv_current_marker->clip;
640  const int track_index = libmv_current_marker->track;
641 
642  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
643  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
644  const MovieTrackingTrack *track = autotrack_track->track;
645 
646  /* Check whether marker is going outside of allowed frame margin. */
648  libmv_current_marker, track->margin, autotrack_clip->width, autotrack_clip->height)) {
649  return;
650  }
651 
652  const int new_marker_frame = libmv_current_marker->frame + frame_delta;
653 
654  AutoTrackTrackingResult *autotrack_result = MEM_mallocN(sizeof(AutoTrackTrackingResult),
655  "autotrack result");
656  autotrack_result->libmv_marker = *libmv_current_marker;
657  autotrack_result->libmv_marker.frame = new_marker_frame;
658 
659  /* Update reference frame. */
660  libmv_Marker libmv_reference_marker;
661  if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
662  autotrack_result->libmv_marker.reference_frame = libmv_current_marker->reference_frame;
664  clip_index,
665  autotrack_result->libmv_marker.reference_frame,
666  track_index,
667  &libmv_reference_marker);
668  }
669  else {
670  BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
671  autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
672  libmv_reference_marker = *libmv_current_marker;
673  }
674 
675  /* Perform actual tracking. */
676  autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
677  &autotrack_track->track_region_options,
678  &autotrack_result->libmv_marker,
679  &autotrack_result->libmv_result);
680 
681  /* If tracking failed restore initial position.
682  * This is how Blender side is currently expecting failed track to be handled. Without this the
683  * marker is left in an arbitrary position which did not provide good correlation. */
684  if (!autotrack_result->success) {
685  autotrack_result->libmv_marker = *libmv_current_marker;
686  autotrack_result->libmv_marker.frame = new_marker_frame;
687  }
688 
689  BLI_addtail(&autotrack_tls->results, autotrack_result);
690 }
691 
692 static void autotrack_context_reduce(const void *__restrict UNUSED(userdata),
693  void *__restrict chunk_join,
694  void *__restrict chunk)
695 {
696  AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)chunk;
697  if (BLI_listbase_is_empty(&autotrack_tls->results)) {
698  /* Nothing to be joined from. */
699  return;
700  }
701 
702  AutoTrackTLS *autotrack_tls_join = (AutoTrackTLS *)chunk_join;
703  BLI_movelisttolist(&autotrack_tls_join->results, &autotrack_tls->results);
704 }
705 
707 {
708  if (context->num_autotrack_markers == 0) {
709  return false;
710  }
711 
712  AutoTrackTLS tls;
714 
715  TaskParallelSettings settings;
717  settings.use_threading = (context->num_autotrack_markers > 1);
718  settings.userdata_chunk = &tls;
719  settings.userdata_chunk_size = sizeof(AutoTrackTLS);
721 
723  0, context->num_autotrack_markers, context, autotrack_context_step_cb, &settings);
724 
725  /* Prepare next tracking step by updating the AutoTrack context with new markers and moving
726  * tracked markers as an input for the next iteration. */
727  context->num_autotrack_markers = 0;
728  LISTBASE_FOREACH (AutoTrackTrackingResult *, autotrack_result, &tls.results) {
729  if (!autotrack_result->success) {
730  continue;
731  }
732 
733  /* Insert tracking results to the AutoTrack context to make them usable for the next frame
734  * tracking iteration. */
735  libmv_autoTrackAddMarker(context->autotrack, &autotrack_result->libmv_marker);
736 
737  /* Update the list of markers which will be tracked on the next iteration. */
738  context->autotrack_markers[context->num_autotrack_markers++].libmv_marker =
739  autotrack_result->libmv_marker;
740  }
741 
742  BLI_spin_lock(&context->spin_lock);
743  BLI_movelisttolist(&context->results_to_sync, &tls.results);
744  BLI_spin_unlock(&context->spin_lock);
745 
746  return true;
747 }
748 
751 /* -------------------------------------------------------------------- */
760 {
761  const int frame_delta = context->is_backwards ? -1 : 1;
762 
763  BLI_spin_lock(&context->spin_lock);
764  ListBase results_to_sync = context->results_to_sync;
765  BLI_listbase_clear(&context->results_to_sync);
766  BLI_spin_unlock(&context->spin_lock);
767 
768  LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
769  const libmv_Marker *libmv_marker = &autotrack_result->libmv_marker;
770  const int clip_index = libmv_marker->clip;
771  const int track_index = libmv_marker->track;
772  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
773  const MovieClip *clip = autotrack_clip->clip;
774  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
775  MovieTrackingTrack *track = autotrack_track->track;
776 
777  const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
778  clip, context->start_scene_frame);
779  const int first_result_frame = start_clip_frame + frame_delta;
780 
781  /* Insert marker which corresponds to the tracking result. */
782  MovieTrackingMarker marker;
784  &autotrack_result->libmv_marker, autotrack_clip->width, autotrack_clip->height, &marker);
785  if (!autotrack_result->success) {
786  marker.flag |= MARKER_DISABLED;
787  }
788  BKE_tracking_marker_insert(track, &marker);
789 
790  /* Insert disabled marker at the end of tracked segment.
791  * When tracking forward the disabled marker is added at the next frame from the result,
792  * when tracking backwards the marker is added at the previous frame. */
793  tracking_marker_insert_disabled(track, &marker, context->is_backwards, false);
794 
795  if (marker.framenr == first_result_frame) {
797  track, marker.framenr - frame_delta);
798  BLI_assert(prev_marker != NULL);
799 
800  tracking_marker_insert_disabled(track, prev_marker, !context->is_backwards, false);
801  }
802 
803  /* Update synchronized frame to the latest tracked fame from the current results. */
804  const int marker_scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, marker.framenr);
805  if (context->is_backwards) {
806  context->synchronized_scene_frame = min_ii(context->synchronized_scene_frame,
807  marker_scene_frame);
808  }
809  else {
810  context->synchronized_scene_frame = max_ii(context->synchronized_scene_frame,
811  marker_scene_frame);
812  }
813 
814  MEM_freeN(autotrack_result);
815  }
816 
817  for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
818  MovieTracking *tracking = &context->autotrack_clips[clip_index].clip->tracking;
820  }
821 }
822 
823 /* TODO(sergey): Find a way to avoid this, somehow making all needed logic in
824  * #BKE_autotrack_context_sync(). */
826 {
827  user->framenr = context->synchronized_scene_frame;
828 }
829 
832 /* -------------------------------------------------------------------- */
837 {
838  for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
839  const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
840  MovieClip *clip = autotrack_clip->clip;
841  ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
842  const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
843  clip, context->start_scene_frame);
844 
845  LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
846  if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
847  continue;
848  }
849  for (int track_index = 0; track_index < context->num_all_tracks; track_index++) {
850  const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
851  if (!autotrack_track->is_trackable) {
852  continue;
853  }
854  MovieTrackingTrack *track = autotrack_track->track;
855  if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
856  BKE_tracking_track_plane_from_existing_motion(plane_track, start_clip_frame);
857  break;
858  }
859  }
860  }
861  }
862 }
863 
865 {
866  for (int i = 0; i < context->num_referenced_image_buffers; ++i) {
867  ImBuf *ibuf = context->referenced_image_buffers[i];
868 
869  /* Restore flag. It is not expected that anyone else is setting this flag on image buffers from
870  * movie clip, so can simply clear the flag. */
871  ibuf->userflags &= ~IB_PERSISTENT;
872  IMB_freeImBuf(ibuf);
873  }
874 
875  MEM_freeN(context->referenced_image_buffers);
876 }
877 
879 {
880  if (context->autotrack != NULL) {
881  libmv_autoTrackDestroy(context->autotrack);
882  }
883 
884  if (context->image_accessor != NULL) {
885  tracking_image_accessor_destroy(context->image_accessor);
886  }
887 
889 
890  MEM_SAFE_FREE(context->all_autotrack_tracks);
891  MEM_SAFE_FREE(context->autotrack_markers);
892 
893  BLI_freelistN(&context->results_to_sync);
894 
895  BLI_spin_end(&context->spin_lock);
896 
898 }
899 
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
Definition: movieclip.c:1614
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height)
Definition: movieclip.c:1520
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user)
Definition: movieclip.c:1329
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:346
struct MovieTrackingMarker * BKE_tracking_marker_insert(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker)
Definition: tracking.c:1302
#define TRACK_SELECTED(track)
Definition: BKE_tracking.h:823
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking)
Definition: tracking.c:3411
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1457
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:357
bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingTrack *track)
Definition: tracking.c:1741
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1424
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
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:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
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:890
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
#define INIT_MINMAX2(min, max)
#define UNUSED(x)
@ MCLIP_PROXY_RENDER_SIZE_FULL
Object is a sort of wrapper for general info.
@ PLANE_TRACK_AUTOKEY
@ MARKER_TRACKED
@ MARKER_DISABLED
@ TRACK_DISABLE_BLUE
@ TRACK_HIDDEN
@ TRACK_LOCKED
@ TRACK_DISABLE_RED
@ TRACK_DISABLE_GREEN
@ TRACK_MATCH_PREVIOS_FRAME
@ TRACK_MATCH_KEYFRAME
Contains defines and structs used throughout the imbuf module.
@ IB_PERSISTENT
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 IMB_freeImBuf(ImBuf *UNUSED(ibuf))
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:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
MovieClip * clip
Definition: tracking_auto.c:34
AutoTrackMarker * autotrack_markers
TrackingImageAccessor * image_accessor
AutoTrackTrack * all_autotrack_tracks
ImBuf ** referenced_image_buffers
ListBase results_to_sync
struct libmv_AutoTrack * autotrack
int num_referenced_image_buffers
AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP]
Definition: tracking_auto.c:91
libmv_Marker libmv_marker
Definition: tracking_auto.c:58
ListBase results
libmv_TrackRegionOptions track_region_options
Definition: tracking_auto.c:49
MovieTrackingTrack * track
Definition: tracking_auto.c:46
libmv_TrackRegionResult libmv_result
Definition: tracking_auto.c:72
struct AutoTrackTrackingResult * next
Definition: tracking_auto.c:68
struct AutoTrackTrackingResult * prev
Definition: tracking_auto.c:68
libmv_Marker libmv_marker
Definition: tracking_auto.c:71
int userflags
struct MovieTracking tracking
MovieTrackingMarker * markers
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:181
size_t userdata_chunk_size
Definition: BLI_task.h:169
int track
Definition: tracksN.h:49
float search_region_max[2]
Definition: tracksN.h:53
float center[2]
Definition: tracksN.h:50
float search_region_min[2]
Definition: tracksN.h:52
int frame
Definition: tracksN.h:48
int disabled_channels
Definition: tracksN.h:61
libmv_MarkerModelType model_type
Definition: tracksN.h:59
float patch[4][2]
Definition: tracksN.h:51
int reference_frame
Definition: tracksN.h:58
int reference_clip
Definition: tracksN.h:57
float weight
Definition: tracksN.h:54
libmv_MarkerSource source
Definition: tracksN.h:55
int clip
Definition: tracksN.h:47
int model_id
Definition: tracksN.h:60
libmv_MarkerStatus status
Definition: tracksN.h:56
ListBase tracks
Definition: tracking.c:60
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 release_keyframed_image_buffers(AutoTrackContext *context)
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
void BKE_autotrack_context_start(AutoTrackContext *context)
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 reference_keyframed_image_buffers(AutoTrackContext *context)
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:43
@ LIBMV_MARKER_CHANNEL_G
Definition: tracksN.h:42
@ LIBMV_MARKER_CHANNEL_R
Definition: tracksN.h:41
@ LIBMV_MARKER_SOURCE_TRACKED
Definition: tracksN.h:22
@ LIBMV_MARKER_SOURCE_MANUAL
Definition: tracksN.h:20
@ LIBMV_MARKER_STATUS_UNKNOWN
Definition: tracksN.h:28
@ LIBMV_MARKER_MODEL_TYPE_POINT
Definition: tracksN.h:34