Blender V4.3
tracking_auto.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
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_vector.h"
18#include "BLI_task.h"
19#include "BLI_threads.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_movieclip.h"
23#include "BKE_tracking.h"
24
25#include "IMB_imbuf.hh"
26#include "IMB_imbuf_types.hh"
27
28#include "libmv-capi.h"
29#include "tracking_private.h"
30
33
34 /* Dimensions of movie frame, in pixels.
35 *
36 * NOTE: All frames within a clip are expected to have match3ed dimensions. */
38};
39
41 /* Index of a clip from `AutoTrackContext::autotrack_clips` this track belongs to. */
43
45
46 /* Options for the region tracker. */
48
49 /* Denotes whether this track will be tracked.
50 * Is usually initialized based on track's selection. Non-trackable tracks are still added to the
51 * context to provide AutoTrack all knowledge about what is going on in the scene. */
53};
54
58
59/* Result of tracking step for a single marker.
60 *
61 * On success both marker and result are fully initialized to the position on the new frame.
62 *
63 * On failure marker's frame number is initialized to frame number where it was attempted to be
64 * tracked to. The position and other fields of tracked marker are the same as the input. */
72
74 /* --------------------------------------------------------------------
75 * Invariant part.
76 * Stays unchanged during the tracking process.
77 * If not the initialization process, all the fields here should be treated as `const`.
78 */
79
80 /* Frame at which tracking process started.
81 * NOTE: Measured in scene time frames, */
83
84 /* True when tracking backwards (from higher frame number to lower frame number.) */
86
87 /* Movie clips used during the tracking process. */
90
91 /* Tracks for which the context has been created for.
92 * This is a flat array of all tracks coming from all clips, regardless of whether track is
93 * actually being tracked or not. This allows the AutoTrack to see a big picture of hat is going
94 * on in the scene, and request information it needs.
95 *
96 * Indexed by AutoTrackOptions::track_index. */
99
100 /* Accessor for images of clip. Used by the autotrack context. */
102
103 /* Image buffers acquired for markers which are using keyframe pattern matching.
104 * These image buffers are user-referenced and flagged as persistent so that they don't get
105 * removed from the movie cache during tracking. */
108
109 /* --------------------------------------------------------------------
110 * Variant part.
111 * Denotes tracing state and tracking result.
112 */
113
114 /* Auto-track context.
115 *
116 * NOTE: Is accessed from multiple threads at once. */
118
119 /* Markers from the current frame which will be tracked to the next frame upon the tracking
120 * context step.
121 *
122 * NOTE: This array is re-used across tracking steps, which might make it appear that the array
123 * is over-allocated when some tracks has failed to track. */
126
127 /* Tracking results which are to be synchronized from the AutoTrack context to the Blender's
128 * DNA to make the results visible for users. */
131
133};
134
135/* -------------------------------------------------------------------- */
139static void normalized_to_libmv_frame(const float normalized[2],
140 const int frame_dimensions[2],
141 float result[2])
142{
143 result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
144 result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
145}
146
148 const float origin[2],
149 const int frame_dimensions[2],
150 float result[2])
151{
152 result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
153 result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
154}
155
156static void libmv_frame_to_normalized(const float frame_coord[2],
157 const int frame_dimensions[2],
158 float result[2])
159{
160 result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
161 result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
162}
163
164static void libmv_frame_to_normalized_relative(const float frame_coord[2],
165 const float origin[2],
166 const int frame_dimensions[2],
167 float result[2])
168{
169 result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
170 result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
171}
172
175/* -------------------------------------------------------------------- */
180 const MovieTrackingMarker &marker,
181 const int clip,
182 const int track_index,
183 const int frame_width,
184 const int frame_height,
185 const bool backwards)
186{
187 libmv_Marker libmv_marker{};
188
189 const int frame_dimensions[2] = {frame_width, frame_height};
190 libmv_marker.clip = clip;
191 libmv_marker.frame = marker.framenr;
192 libmv_marker.track = track_index;
193
194 normalized_to_libmv_frame(marker.pos, frame_dimensions, libmv_marker.center);
195 for (int i = 0; i < 4; i++) {
197 marker.pattern_corners[i], marker.pos, frame_dimensions, libmv_marker.patch[i]);
198 }
199
201 marker.search_min, marker.pos, frame_dimensions, libmv_marker.search_region_min);
202
204 marker.search_max, marker.pos, frame_dimensions, libmv_marker.search_region_max);
205
206 /* NOTE: All the markers does have 1.0 weight.
207 * Might support in the future, but will require more elaborated process which will involve
208 * F-Curve evaluation. */
209 libmv_marker.weight = 1.0f;
210
211 if (marker.flag & MARKER_TRACKED) {
212 libmv_marker.source = LIBMV_MARKER_SOURCE_TRACKED;
213 }
214 else {
215 libmv_marker.source = LIBMV_MARKER_SOURCE_MANUAL;
216 }
217 libmv_marker.status = LIBMV_MARKER_STATUS_UNKNOWN;
218 libmv_marker.model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
219 libmv_marker.model_id = 0;
220
221 /* NOTE: We currently don't support reference marker from different clip. */
222 libmv_marker.reference_clip = clip;
223
224 if (track.pattern_match == TRACK_MATCH_KEYFRAME) {
225 const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
226 &track, marker.framenr, backwards);
227 libmv_marker.reference_frame = keyframe_marker->framenr;
228 }
229 else {
230 libmv_marker.reference_frame = backwards ? marker.framenr - 1 : marker.framenr;
231 }
232
233 libmv_marker.disabled_channels =
237
238 return libmv_marker;
239}
240
242 const int frame_width,
243 const int frame_height)
244{
245 MovieTrackingMarker marker{};
246
247 const int frame_dimensions[2] = {frame_width, frame_height};
248 marker.framenr = libmv_marker.frame;
249
250 libmv_frame_to_normalized(libmv_marker.center, frame_dimensions, marker.pos);
251 for (int i = 0; i < 4; i++) {
253 libmv_marker.patch[i], libmv_marker.center, frame_dimensions, 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 return marker;
271}
272
275/* -------------------------------------------------------------------- */
281/* Returns false if marker crossed margin area from frame bounds. */
282static bool tracking_check_marker_margin(const libmv_Marker &libmv_marker,
283 const int margin,
284 const int frame_width,
285 const int frame_height)
286{
287 float patch_min[2], patch_max[2];
288 float margin_left, margin_top, margin_right, margin_bottom;
289
290 INIT_MINMAX2(patch_min, patch_max);
291 minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[0]);
292 minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[1]);
293 minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[2]);
294 minmax_v2v2_v2(patch_min, patch_max, libmv_marker.patch[3]);
295
296 margin_left = max_ff(libmv_marker.center[0] - patch_min[0], margin);
297 margin_top = max_ff(patch_max[1] - libmv_marker.center[1], margin);
298 margin_right = max_ff(patch_max[0] - libmv_marker.center[0], margin);
299 margin_bottom = max_ff(libmv_marker.center[1] - patch_min[1], margin);
300
301 if (libmv_marker.center[0] < margin_left ||
302 libmv_marker.center[0] > frame_width - margin_right ||
303 libmv_marker.center[1] < margin_bottom || libmv_marker.center[1] > frame_height - margin_top)
304 {
305 return false;
306 }
307
308 return true;
309}
310
313/* -------------------------------------------------------------------- */
318{
319 if (marker.flag & MARKER_DISABLED) {
320 return false;
321 }
322 return true;
323}
324
326 const AutoTrackTrack *autotrack_track)
327{
328 /*const*/ MovieTrackingTrack *track = autotrack_track->track;
329 if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
330 const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
331 MovieClip *clip = autotrack_clip->clip;
332 const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
333 clip, context->start_scene_frame);
334
335 const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
336 return autotrack_is_marker_usable(*marker);
337 }
338 return false;
339}
340
342 MovieClip *clip,
343 MovieClipUser *user)
344{
345 /* NOTE: Currently only tracking within a single clip. */
346
347 context->num_clips = 1;
348
349 context->autotrack_clips[0].clip = clip;
351 clip, user, &context->autotrack_clips[0].width, &context->autotrack_clips[0].height);
352}
353
354/* Initialize flat list of tracks for quick index-based access for the specified clip.
355 * All the tracks from this clip are added at the end of the array of already-collected tracks.
356 *
357 * NOTE: Clips should be initialized first. */
358static void autotrack_context_init_tracks_for_clip(AutoTrackContext *context, int clip_index)
359{
360 BLI_assert(clip_index >= 0);
361 BLI_assert(clip_index < context->num_clips);
362
363 const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
364 MovieClip *clip = autotrack_clip->clip;
365 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
366
367 const int num_clip_tracks = BLI_listbase_count(&tracking_object->tracks);
368 if (num_clip_tracks == 0) {
369 return;
370 }
371
372 context->all_autotrack_tracks = static_cast<AutoTrackTrack *>(
373 MEM_reallocN(context->all_autotrack_tracks,
374 (context->num_all_tracks + num_clip_tracks) * sizeof(AutoTrackTrack)));
375
376 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
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, nullptr, 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) {
395 autotrack_context_init_tracks_for_clip(context, 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
414 MovieTrackingTrack **tracks = MEM_cnew_array<MovieTrackingTrack *>(context->num_all_tracks,
415 "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_cnew_array<libmv_Marker>(num_trackable_markers,
471 "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];
484 libmv_markers[num_filled_libmv_markers++] = dna_marker_to_libmv_marker(
485 track,
486 marker,
487 autotrack_track->clip_index,
488 track_index,
489 autotrack_clip->width,
490 autotrack_clip->height,
491 context->is_backwards);
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_cnew_array<AutoTrackMarker>(context->num_autotrack_markers,
512 "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++];
531 autotrack_marker->libmv_marker = dna_marker_to_libmv_marker(track,
532 marker,
533 autotrack_track->clip_index,
534 track_index,
535 autotrack_clip->width,
536 autotrack_clip->height,
537 context->is_backwards);
538 }
539}
540
542 MovieClipUser *user,
543 const bool is_backwards)
544{
545 AutoTrackContext *context = MEM_cnew<AutoTrackContext>("autotrack context");
546
547 context->start_scene_frame = user->framenr;
548 context->is_backwards = is_backwards;
549 context->synchronized_scene_frame = context->start_scene_frame;
550
551 autotrack_context_init_clips(context, clip, user);
556
557 BLI_spin_init(&context->spin_lock);
558
559 return context;
560}
561
564/* -------------------------------------------------------------------- */
571{
572 /* NOTE: This is potentially over-allocating, but it simplifies memory manipulation.
573 * In practice this is unlikely to be noticed in the profiler as the memory footprint of this
574 * data is way less of what the tracking process will use. */
575 context->referenced_image_buffers = MEM_cnew_array<ImBuf *>(context->num_autotrack_markers,
576 __func__);
577
578 context->num_referenced_image_buffers = 0;
579
580 for (int i = 0; i < context->num_autotrack_markers; ++i) {
581 const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[i];
582 const int clip_index = autotrack_marker->libmv_marker.clip;
583 const int track_index = autotrack_marker->libmv_marker.track;
584
585 const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
586 const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
587 const MovieTrackingTrack *track = autotrack_track->track;
588
589 if (track->pattern_match != TRACK_MATCH_KEYFRAME) {
590 continue;
591 }
592
593 const int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(
594 autotrack_clip->clip, autotrack_marker->libmv_marker.reference_frame);
595
596 MovieClipUser user_at_keyframe;
597 BKE_movieclip_user_set_frame(&user_at_keyframe, scene_frame);
598 user_at_keyframe.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
599 user_at_keyframe.render_flag = 0;
600
601 /* Keep reference to the image buffer so that we can manipulate its flags later on.
602 * Also request the movie cache to not remove the image buffer from the cache. */
603 ImBuf *ibuf = BKE_movieclip_get_ibuf(autotrack_clip->clip, &user_at_keyframe);
604 ibuf->userflags |= IB_PERSISTENT;
605
606 context->referenced_image_buffers[context->num_referenced_image_buffers++] = ibuf;
607 }
608}
609
614
617/* -------------------------------------------------------------------- */
621/* NOTE: This is a TLS in a sense that this struct is never accessed from multiple threads, and
622 * that threads are re-using the struct as much as possible. */
624 ListBase results; /* Elements of `AutoTrackTrackingResult`. */
625};
626
627static void autotrack_context_step_cb(void *__restrict userdata,
628 const int marker_index,
629 const TaskParallelTLS *__restrict tls)
630{
631 AutoTrackContext *context = static_cast<AutoTrackContext *>(userdata);
632 AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
633
634 const AutoTrackMarker &autotrack_marker = context->autotrack_markers[marker_index];
635 const libmv_Marker &libmv_current_marker = autotrack_marker.libmv_marker;
636
637 const int frame_delta = context->is_backwards ? -1 : 1;
638 const int clip_index = libmv_current_marker.clip;
639 const int track_index = libmv_current_marker.track;
640
641 const AutoTrackClip &autotrack_clip = context->autotrack_clips[clip_index];
642 const AutoTrackTrack &autotrack_track = context->all_autotrack_tracks[track_index];
643 const MovieTrackingTrack &track = *autotrack_track.track;
644
645 /* Check whether marker is going outside of allowed frame margin. */
647 libmv_current_marker, track.margin, autotrack_clip.width, autotrack_clip.height))
648 {
649 return;
650 }
651
652 const int new_marker_frame = libmv_current_marker.frame + frame_delta;
653
654 AutoTrackTrackingResult *autotrack_result = MEM_cnew<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;
663 libmv_autoTrackGetMarker(context->autotrack,
664 clip_index,
665 autotrack_result->libmv_marker.reference_frame,
666 track_index,
667 &libmv_reference_marker);
668 }
669 else {
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
692static void autotrack_context_reduce(const void *__restrict /*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);
720 settings.func_reduce = autotrack_context_reduce;
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. */
783 autotrack_result->libmv_marker, autotrack_clip.width, autotrack_clip.height);
784 if (!autotrack_result->success) {
785 marker.flag |= MARKER_DISABLED;
786 }
787 BKE_tracking_marker_insert(track, &marker);
788
789 /* Insert disabled marker at the end of tracked segment.
790 * When tracking forward the disabled marker is added at the next frame from the result,
791 * when tracking backwards the marker is added at the previous frame. */
792 tracking_marker_insert_disabled(track, &marker, context->is_backwards, false);
793
794 if (marker.framenr == first_result_frame) {
796 track, marker.framenr - frame_delta);
797 BLI_assert(prev_marker != nullptr);
798
799 tracking_marker_insert_disabled(track, prev_marker, !context->is_backwards, false);
800 }
801
802 /* Update synchronized frame to the latest tracked fame from the current results. */
803 const int marker_scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, marker.framenr);
804 if (context->is_backwards) {
805 context->synchronized_scene_frame = min_ii(context->synchronized_scene_frame,
806 marker_scene_frame);
807 }
808 else {
809 context->synchronized_scene_frame = max_ii(context->synchronized_scene_frame,
810 marker_scene_frame);
811 }
812
813 MEM_freeN(autotrack_result);
814 }
815
816 for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
817 MovieTracking *tracking = &context->autotrack_clips[clip_index].clip->tracking;
819 }
820}
821
823{
824 /* TODO(sergey): Find a way to avoid this function,
825 * somehow making all needed logic in #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 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&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, &tracking_object->plane_tracks) {
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 != nullptr) {
881 libmv_autoTrackDestroy(context->autotrack);
882 }
883
884 if (context->image_accessor != nullptr) {
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
897 MEM_freeN(context);
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)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, const struct MovieClipUser *user)
#define TRACK_SELECTED(track)
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking)
Definition tracking.cc:3411
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1391
void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame)
bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingTrack *track)
Definition tracking.cc:1641
struct MovieTrackingMarker * BKE_tracking_marker_insert(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker)
Definition tracking.cc:1235
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
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.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc: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])
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:230
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
#define INIT_MINMAX2(min, max)
@ MCLIP_PROXY_RENDER_SIZE_FULL
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_PREVIOUS_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)
SIMD_FORCE_INLINE btVector3 normalized() const
Return a normalized version of this vector.
void IMB_freeImBuf(ImBuf *)
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_freeN(void *vmemh)
Definition mallocn.cc:105
MovieClip * clip
AutoTrackMarker * autotrack_markers
TrackingImageAccessor * image_accessor
AutoTrackTrack * all_autotrack_tracks
libmv_AutoTrack * autotrack
ImBuf ** referenced_image_buffers
AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP]
libmv_Marker libmv_marker
libmv_TrackRegionOptions track_region_options
MovieTrackingTrack * track
libmv_TrackRegionResult libmv_result
AutoTrackTrackingResult * prev
AutoTrackTrackingResult * next
MovieTrackingMarker * markers
float search_region_max[2]
Definition tracksN.h:54
float center[2]
Definition tracksN.h:51
float search_region_min[2]
Definition tracksN.h:53
float patch[4][2]
Definition tracksN.h:52
int reference_frame
Definition tracksN.h:59
libmv_MarkerSource source
Definition tracksN.h:56
bool BKE_autotrack_context_step(AutoTrackContext *context)
static void release_keyframed_image_buffers(AutoTrackContext *context)
void BKE_autotrack_context_start(AutoTrackContext *context)
static void autotrack_context_step_cb(void *__restrict userdata, const int marker_index, const TaskParallelTLS *__restrict tls)
static bool tracking_check_marker_margin(const libmv_Marker &libmv_marker, const int margin, const int frame_width, const int frame_height)
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])
static MovieTrackingMarker libmv_marker_to_dna_marker(const libmv_Marker &libmv_marker, const int frame_width, const int frame_height)
static void normalized_relative_to_libmv_frame(const float normalized[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_to_libmv_frame(const float normalized[2], const int frame_dimensions[2], float result[2])
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)
static bool autotrack_is_marker_usable(const MovieTrackingMarker &marker)
static libmv_Marker dna_marker_to_libmv_marker(MovieTrackingTrack &track, const MovieTrackingMarker &marker, const int clip, const int track_index, const int frame_width, const int frame_height, const bool backwards)
void BKE_autotrack_context_finish(AutoTrackContext *context)
static size_t autotrack_count_all_usable_markers(AutoTrackContext *context)
static void autotrack_context_reduce(const void *__restrict, void *__restrict chunk_join, void *__restrict chunk)
static void autotrack_context_init_autotrack(AutoTrackContext *context)
void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *user)
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])
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)
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)
MovieTrackingMarker * tracking_get_keyframed_marker(MovieTrackingTrack *track, int current_frame, bool backwards)
@ LIBMV_MARKER_CHANNEL_B
Definition tracksN.h:44
@ LIBMV_MARKER_CHANNEL_G
Definition tracksN.h:43
@ LIBMV_MARKER_CHANNEL_R
Definition tracksN.h:42
@ LIBMV_MARKER_SOURCE_TRACKED
Definition tracksN.h:23
@ LIBMV_MARKER_SOURCE_MANUAL
Definition tracksN.h:21
@ LIBMV_MARKER_STATUS_UNKNOWN
Definition tracksN.h:29
@ LIBMV_MARKER_MODEL_TYPE_POINT
Definition tracksN.h:35