[Bf-blender-cvs] [29401d38d11] master: Tracking: Refactor autotrack tracking implementation

Sergey Sharybin noreply at git.blender.org
Tue Dec 1 15:32:00 CET 2020


Commit: 29401d38d113342d6fe5b5545742ad355f777439
Author: Sergey Sharybin
Date:   Mon Nov 30 18:13:07 2020 +0100
Branches: master
https://developer.blender.org/rB29401d38d113342d6fe5b5545742ad355f777439

Tracking: Refactor autotrack tracking implementation

The idea is to avoid any synchronization needed in the worker threads
and make them to operate on a local data. From implementation detail
this is achieved by keeping track of "wavefront" of markers which are
to be tracked and the tracking result. Insertion of results to the
AutoTrack context happens from main thread, which avoids need in the
lock when accessing AutoTrack.

This change makes tracking of many (300+) about 10% faster on the
Xeon) CPU E5-2699 v4. More speedup will be gained by minimizing
threading overhead in the frame cache.

Another important aspect of this change is that it fixes non-thread
safe access which was often causing crashes. Quite surprising the
crash was never reported.

===================================================================

M	source/blender/blenkernel/intern/tracking_auto.c

===================================================================

diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index edd798b162a..05d1e427c14 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -41,39 +41,65 @@
 #include "libmv-capi.h"
 #include "tracking_private.h"
 
-typedef struct AutoTrackOptions {
-  int clip_index;            /** Index of the clip this track belongs to. */
-  int track_index;           /* Index of the track in AutoTrack tracks structure. */
-  MovieTrackingTrack *track; /* Pointer to an original track/ */
-  libmv_TrackRegionOptions track_region_options; /* Options for the region tracker. */
-
-  /* Define which frame is used for reference marker. */
-  eTrackFrameMatch frame_match;
-
-  /* TODO(sergey): A bit awkward to keep it in here, only used to
-   * place a disabled marker once the tracking fails,
-   * Either find a clearer way to do it or call it track context
-   * or state, not options.
-   */
-  bool is_failed;
-  int failed_frame;
-} AutoTrackOptions;
+typedef struct AutoTrackClip {
+  MovieClip *clip;
+
+  /* Dimensions of movie frame, in pixels.
+   *
+   * NOTE: All frames within a clip are expected to have match3ed dimensions. */
+  int width, height;
+} AutoTrackClip;
+
+typedef struct AutoTrackTrack {
+  /* Index of a clip from `AutoTrackContext::autotrack_clips` this track belongs to. */
+  int clip_index;
+
+  MovieTrackingTrack *track;
+
+  /* Options for the region tracker. */
+  libmv_TrackRegionOptions track_region_options;
+
+  /* Denotes whether this track will be tracked.
+   * Is usually initialized based on track's selection. Non-trackable tracks are still added to the
+   * context to provide AutoTrack all knowledge about what is going on in the scene. */
+  bool is_trackable;
+} AutoTrackTrack;
+
+typedef struct AutoTrackMarker {
+  libmv_Marker libmv_marker;
+} AutoTrackMarker;
+
+/* Result of tracking step for a single marker.
+ *
+ * On success both marker and result are fully initialized to the position on the new frame.
+ *
+ * On failure marker's frame number is initialized to frame number where it was attempted to be
+ * tracked to. The position and other fields of tracked marker are the same as the input. */
+typedef struct AutoTrackTrackingResult {
+  struct AutoTrackTrackingResult *next, *prev;
+
+  bool success;
+  libmv_Marker libmv_marker;
+  libmv_TrackRegionResult libmv_result;
+} AutoTrackTrackingResult;
 
 typedef struct AutoTrackContext {
+  /* --------------------------------------------------------------------
+   * Invariant part.
+   * Stays unchanged during the tracking process.
+   * If not the initialization process, all the fields here should be treated as `const`.
+   */
+
   /* Frame at which tracking process started.
    * NOTE: Measured in scene time frames, */
   int start_scene_frame;
 
-  /* Scene frame number from which tracker will perform the trackign step.
-   * The direction of the step is denoted by `is_backwards`. */
-  int current_scene_frame;
-
   /* True when tracking backwards (from higher frame number to lower frame number.) */
   bool is_backwards;
 
   /* Movie clips used during the trackign process. */
   int num_clips;
-  MovieClip *clips[MAX_ACCESSOR_CLIP];
+  AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP];
 
   /* Tracks for which the context has been created for.
    * This is a flat array of all tracks coming from all clips, regardless of whether track is
@@ -82,35 +108,41 @@ typedef struct AutoTrackContext {
    *
    * Indexed by AutoTrackOptions::track_index. */
   int num_all_tracks;
-  MovieTrackingTrack **all_tracks;
-
-  /* Dimensions of movie frame, in pixels.
-   *
-   * NOTE: All clips and frames within a clip are expected to have match3ed dimensions.
-   *
-   * TODO(sergey): Make it more flexible to fully support multiple-clip tracking. Could either be
-   * stored as a `pair<MovieClip, Dimensions>` or even be replaced with actual frame size access
-   * to support variadic frame dimensions. */
-  int frame_width, frame_height;
+  AutoTrackTrack *all_autotrack_tracks;
 
   /* Accessor for images of clip. Used by the autotrack context. */
   TrackingImageAccessor *image_accessor;
 
+  /* --------------------------------------------------------------------
+   * Variant part.
+   * Denotes tracing state and tracking result.
+   */
+
   /* Auto-track context.
    *
    * NOTE: Is accessed from multiple threads at once. */
   struct libmv_AutoTrack *autotrack;
 
-  int num_track_options;
-  AutoTrackOptions *track_options; /* Per-tracking track options. */
+  /* Markers from the current frame which will be tracked to the next frame upon the tracking
+   * context step.
+   *
+   * NOTE: This array is re-used across tracking steps, which might make it appear that the array
+   * is over-allocated when some tracks has failed to track. */
+  int num_autotrack_markers;
+  AutoTrackMarker *autotrack_markers;
 
-  int sync_frame;
-  bool first_sync;
-  SpinLock spin_lock;
+  /* Tracking results which are to be synchronized from the AutoTrack context to the Blender's
+   * DNA to make the results visible for users. */
+  ListBase results_to_sync;
+  int synchronized_scene_frame;
 
-  bool step_ok;
+  SpinLock spin_lock;
 } AutoTrackContext;
 
+/* -------------------------------------------------------------------- */
+/** \name Marker coordinate system conversion.
+ * \{ */
+
 static void normalized_to_libmv_frame(const float normalized[2],
                                       const int frame_dimensions[2],
                                       float result[2])
@@ -145,8 +177,14 @@ static void libmv_frame_to_normalized_relative(const float frame_coord[2],
   result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
 }
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Coversion of markers between Blender's DNA and Libmv.
+ * \{ */
+
 static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
-                                       /*const*/ MovieTrackingMarker *marker,
+                                       const MovieTrackingMarker *marker,
                                        int clip,
                                        int track_index,
                                        int frame_width,
@@ -171,7 +209,9 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
   normalized_relative_to_libmv_frame(
       marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
 
-  /* TODO(sergey): All the markers does have 1.0 weight. */
+  /* NOTE: All the markers does have 1.0 weight.
+   * Might support in the future, but will require more elaborated process which will involve
+   * F-Curve evaluation. */
   libmv_marker->weight = 1.0f;
 
   if (marker->flag & MARKER_TRACKED) {
@@ -184,13 +224,11 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
   libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
   libmv_marker->model_id = 0;
 
-  /* TODO(sergey): We currently don't support reference marker from
-   * different clip.
-   */
+  /* NOTE: We currently don't support reference marker from different clip. */
   libmv_marker->reference_clip = clip;
 
   if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
-    MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
+    const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
         track, marker->framenr, backwards);
     libmv_marker->reference_frame = keyframe_marker->framenr;
   }
@@ -235,20 +273,17 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
   }
 }
 
-static bool check_track_trackable(const MovieClip *clip,
-                                  MovieTrackingTrack *track,
-                                  const MovieClipUser *user)
-{
-  if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
-    int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
-    const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, frame);
-    return (marker->flag & MARKER_DISABLED) == 0;
-  }
-  return false;
-}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General helpers.
+ *
+ * TODO(sergey): Should be moved to tracking_util.c
+ *
+ * \{ */
 
 /* Returns false if marker crossed margin area from frame bounds. */
-static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
+static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
                                          int margin,
                                          int frame_width,
                                          int frame_height)
@@ -277,91 +312,234 @@ static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
   return true;
 }
 
-/* Provide Libmv side of auto track all information about given tracks. */
-static void fill_autotrack_tracks(const int frame_width,
-                                  const int frame_height,
-                                  const ListBase *tracksbase,
-                                  const bool backwards,
-                                  struct libmv_AutoTrack *autotrack)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Autotrack context initialization.
+ * \{ */
+
+static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
 {
-  /* Count number of markers to be put to a context. */
-  size_t num_trackable_markers = 0;
-  LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
-    for (int i = 0; i < track->markersnr; i++) {
-      const MovieTrackingMarker *marker = track->markers + i;
-      if ((marker->flag & MARKER_DISABLED) == 0) {
-        num_trackable_markers++;
+  if ((marker->flag & MARKER_DISABLED)) {
+    return false;
+  }
+  return true;
+}
+
+static bool autotrack_is_track_trackable(const AutoTrackContext *context,
+                                         const AutoTrackTrack *autotrack_track)
+{
+  /*const*/ MovieTrackingTrack *track = autotrack_track->track;
+  if (TRACK_SEL

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list