Blender V4.5
tracking_ops_track.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_listbase.h"
12#include "BLI_time.h"
13
14#include "BLT_translation.hh"
15
16#include "BKE_context.hh"
17#include "BKE_global.hh"
18#include "BKE_main.hh"
19#include "BKE_movieclip.h"
20#include "BKE_tracking.h"
21
22#include "WM_api.hh"
23#include "WM_types.hh"
24
25#include "ED_clip.hh"
26
27#include "RNA_access.hh"
28#include "RNA_define.hh"
29
30#include "DEG_depsgraph.hh"
31
32#include "clip_intern.hh" /* own include */
34
35/********************** Track operator *********************/
36
38 AutoTrackContext *context; /* Tracking context */
39 int sfra, efra, lastfra; /* Start, end and recently tracked frames */
40 int backwards; /* Backwards tracking flag */
41 MovieClip *clip; /* Clip which is tracking */
42 float delay; /* Delay in milliseconds to allow
43 * tracking at fixed FPS */
44
49};
50
52{
53 return G.is_break;
54}
55
56static int track_count_markers(SpaceClip *sc, MovieClip *clip, const int framenr)
57{
58 int tot = 0;
59 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
60 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
61 bool selected = (sc != nullptr) ? TRACK_VIEW_SELECTED(sc, track) : TRACK_SELECTED(track);
62 if (selected && (track->flag & TRACK_LOCKED) == 0) {
63 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
64 if (!marker || (marker->flag & MARKER_DISABLED) == 0) {
65 tot++;
66 }
67 }
68 }
69 return tot;
70}
71
73 MovieClip *clip,
74 const int framenr,
75 int *r_frames_limit)
76{
77 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
78 int frames_limit = 0;
79 if (sc != nullptr) {
81 }
82 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
83 bool selected = (sc != nullptr) ? TRACK_VIEW_SELECTED(sc, track) : TRACK_SELECTED(track);
84 if (selected) {
85 if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
86 BKE_tracking_marker_ensure(track, framenr);
87 if (track->frames_limit) {
88 if (frames_limit == 0) {
89 frames_limit = track->frames_limit;
90 }
91 else {
92 frames_limit = min_ii(frames_limit, int(track->frames_limit));
93 }
94 }
95 }
96 }
97 }
98 *r_frames_limit = frames_limit;
99}
100
101static bool track_markers_check_direction(int backwards, int curfra, int efra)
102{
103 if (backwards) {
104 if (curfra < efra) {
105 return false;
106 }
107 }
108 else {
109 if (curfra > efra) {
110 return false;
111 }
112 }
113
114 return true;
115}
116
117static bool track_markers_initjob(bContext *C, TrackMarkersJob *tmj, bool backwards, bool sequence)
118{
121 Scene *scene = CTX_data_scene(C);
122 MovieTrackingSettings *settings = &clip->tracking.settings;
123 int frames_limit;
124 int framenr = ED_space_clip_get_clip_frame_number(sc);
125
126 track_init_markers(sc, clip, framenr, &frames_limit);
127
128 tmj->sfra = framenr;
129 tmj->clip = clip;
130 tmj->backwards = backwards;
131
132 if (sequence) {
133 if (backwards) {
134 tmj->efra = scene->r.sfra;
135 }
136 else {
137 tmj->efra = scene->r.efra;
138 }
140 }
141 else {
142 if (backwards) {
143 tmj->efra = tmj->sfra - 1;
144 }
145 else {
146 tmj->efra = tmj->sfra + 1;
147 }
148 }
149
150 /* Limit frames to be tracked by user setting. */
151 if (frames_limit) {
152 if (backwards) {
153 tmj->efra = std::max(tmj->efra, tmj->sfra - frames_limit);
154 }
155 else {
156 tmj->efra = std::min(tmj->efra, tmj->sfra + frames_limit);
157 }
158 }
159
160 if (settings->speed != TRACKING_SPEED_FASTEST) {
161 tmj->delay = 1.0f / scene->r.frs_sec * 1000.0f;
162
163 if (settings->speed == TRACKING_SPEED_HALF) {
164 tmj->delay *= 2;
165 }
166 else if (settings->speed == TRACKING_SPEED_QUARTER) {
167 tmj->delay *= 4;
168 }
169 else if (settings->speed == TRACKING_SPEED_DOUBLE) {
170 tmj->delay /= 2;
171 }
172 }
173
174 tmj->context = BKE_autotrack_context_new(clip, &sc->user, backwards);
175
176 clip->tracking_context = tmj->context;
177
178 tmj->lastfra = tmj->sfra;
179
180 /* XXX: silly to store this, but this data is needed to update scene and
181 * movie-clip numbers when tracking is finished. This introduces
182 * better feedback for artists.
183 * Maybe there's another way to solve this problem,
184 * but can't think better way at the moment.
185 * Anyway, this way isn't more unstable as animation rendering
186 * animation which uses the same approach (except storing screen).
187 */
188 tmj->scene = scene;
189 tmj->main = CTX_data_main(C);
190 tmj->screen = CTX_wm_screen(C);
191
192 tmj->wm = CTX_wm_manager(C);
193
194 if (!track_markers_check_direction(backwards, tmj->sfra, tmj->efra)) {
195 return false;
196 }
197
198 WM_set_locked_interface(tmj->wm, true);
199
200 return true;
201}
202
203static void track_markers_startjob(void *tmv, wmJobWorkerStatus *worker_status)
204{
205 TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
206 int framenr = tmj->sfra;
207
209
210 while (framenr != tmj->efra) {
211 if (tmj->delay > 0) {
212 /* Tracking should happen with fixed fps. Calculate time
213 * using current timer value before tracking frame and after.
214 *
215 * Small (and maybe unneeded optimization): do not calculate
216 * exec_time for "Fastest" tracking
217 */
218
219 double start_time = BLI_time_now_seconds(), exec_time;
220
222 break;
223 }
224
225 exec_time = BLI_time_now_seconds() - start_time;
226 if (tmj->delay > float(exec_time)) {
227 BLI_time_sleep_ms(tmj->delay - float(exec_time));
228 }
229 }
230 else if (!BKE_autotrack_context_step(tmj->context)) {
231 break;
232 }
233
234 worker_status->do_update = true;
235 worker_status->progress = float(framenr - tmj->sfra) / (tmj->efra - tmj->sfra);
236
237 if (tmj->backwards) {
238 framenr--;
239 }
240 else {
241 framenr++;
242 }
243
244 tmj->lastfra = framenr;
245
246 if (worker_status->stop || track_markers_testbreak()) {
247 break;
248 }
249 }
250}
251
252static void track_markers_updatejob(void *tmv)
253{
254 TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
256}
257
258static void track_markers_endjob(void *tmv)
259{
260 TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
261 wmWindowManager *wm = static_cast<wmWindowManager *>(tmj->main->wm.first);
262
263 tmj->clip->tracking_context = nullptr;
265 if (wm != nullptr) {
266 /* XXX */
267 // ED_update_for_newframe(tmj->main, tmj->scene);
268 }
269
272
275}
276
277static void track_markers_freejob(void *tmv)
278{
279 TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
280 tmj->clip->tracking_context = nullptr;
281 WM_set_locked_interface(tmj->wm, false);
283 MEM_freeN(tmj);
284}
285
287{
288 TrackMarkersJob *tmj;
291 wmJob *wm_job;
292 bool backwards = RNA_boolean_get(op->ptr, "backwards");
293 bool sequence = RNA_boolean_get(op->ptr, "sequence");
294 int framenr = ED_space_clip_get_clip_frame_number(sc);
295
297 /* Only one tracking is allowed at a time. */
298 return OPERATOR_CANCELLED;
299 }
300
301 if (clip->tracking_context) {
302 return OPERATOR_CANCELLED;
303 }
304
305 if (track_count_markers(sc, clip, framenr) == 0) {
306 return OPERATOR_CANCELLED;
307 }
308
309 tmj = MEM_callocN<TrackMarkersJob>("TrackMarkersJob data");
310 if (!track_markers_initjob(C, tmj, backwards, sequence)) {
312 return OPERATOR_CANCELLED;
313 }
314
315 /* Setup job. */
316 if (use_job && sequence) {
317 wm_job = WM_jobs_get(CTX_wm_manager(C),
320 "Track Markers",
324
325 /* If there's delay set in tracking job, tracking should happen
326 * with fixed FPS. To deal with editor refresh we have to synchronize
327 * tracks from job and tracks in clip. Do this in timer callback
328 * to prevent threading conflicts. */
329 if (tmj->delay > 0) {
330 WM_jobs_timer(wm_job, tmj->delay / 1000.0f, NC_MOVIECLIP | NA_EVALUATED, 0);
331 }
332 else {
333 WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0);
334 }
335
338
339 G.is_break = false;
340
342 WM_cursor_wait(false);
343
344 /* Add modal handler for ESC. */
346
348 }
349
350 wmJobWorkerStatus worker_status = {};
351 track_markers_startjob(tmj, &worker_status);
354 return OPERATOR_FINISHED;
355}
356
358{
359 return track_markers(C, op, false);
360}
361
363 wmOperator *op,
364 const wmEvent * /*event*/)
365{
366 return track_markers(C, op, true);
367}
368
370{
371 /* No running tracking, remove handler and pass through. */
374 }
375
376 /* Running tracking. */
377 switch (event->type) {
378 case EVT_ESCKEY:
380 default: {
381 break;
382 }
383 }
384
386}
387
388static std::string track_markers_get_description(bContext * /*C*/,
389 wmOperatorType * /*ot*/,
391{
392 const bool backwards = RNA_boolean_get(ptr, "backwards");
393 const bool sequence = RNA_boolean_get(ptr, "sequence");
394
395 if (backwards && sequence) {
396 return TIP_("Track the selected markers backward for the entire clip");
397 }
398 if (backwards && !sequence) {
399 return TIP_("Track the selected markers backward by one frame");
400 }
401 if (!backwards && sequence) {
402 return TIP_("Track the selected markers forward for the entire clip");
403 }
404 if (!backwards && !sequence) {
405 return TIP_("Track the selected markers forward by one frame");
406 }
407
408 /* Use default description. */
409 return "";
410}
411
413{
414 /* identifiers */
415 ot->name = "Track Markers";
416 ot->description = "Track selected markers";
417 ot->idname = "CLIP_OT_track_markers";
418
419 /* API callbacks. */
420 ot->exec = track_markers_exec;
421 ot->invoke = track_markers_invoke;
422 ot->modal = track_markers_modal;
424 ot->get_description = track_markers_get_description;
425
426 /* flags */
427 ot->flag = OPTYPE_UNDO;
428
429 /* properties */
430 RNA_def_boolean(ot->srna, "backwards", false, "Backwards", "Do backwards tracking");
431 RNA_def_boolean(ot->srna,
432 "sequence",
433 false,
434 "Track Sequence",
435 "Track marker during image sequence rather than "
436 "single image");
437}
438
439/********************** Refine track position operator *********************/
440
442{
445 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
446 const bool backwards = RNA_boolean_get(op->ptr, "backwards");
447 const int framenr = ED_space_clip_get_clip_frame_number(sc);
448
449 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
450 if (TRACK_VIEW_SELECTED(sc, track)) {
451 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
452 BKE_tracking_refine_marker(clip, track, marker, backwards);
453 }
454 }
455
458
459 return OPERATOR_FINISHED;
460}
461
463{
464 /* identifiers */
465 ot->name = "Refine Markers";
466 ot->description =
467 "Refine selected markers positions "
468 "by running the tracker from track's reference "
469 "to current frame";
470 ot->idname = "CLIP_OT_refine_markers";
471
472 /* API callbacks. */
473 ot->exec = refine_marker_exec;
475
476 /* flags */
478
479 /* properties */
480 RNA_def_boolean(ot->srna, "backwards", false, "Backwards", "Do backwards tracking");
481}
bScreen * CTX_wm_screen(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
SpaceClip * CTX_wm_space_clip(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct AutoTrackContext * BKE_autotrack_context_new(struct MovieClip *clip, struct MovieClipUser *user, bool is_backwards)
void BKE_autotrack_context_finish(struct AutoTrackContext *context)
struct MovieTrackingMarker * BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1401
bool BKE_autotrack_context_step(struct AutoTrackContext *context)
#define TRACK_SELECTED(track)
void BKE_autotrack_context_free(struct AutoTrackContext *context)
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1357
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards)
#define TRACK_VIEW_SELECTED(sc, track)
void BKE_autotrack_context_start(struct AutoTrackContext *context)
void BKE_autotrack_context_sync(struct AutoTrackContext *context)
#define LISTBASE_FOREACH(type, var, list)
MINLINE int min_ii(int a, int b)
Platform independent time functions.
void BLI_time_sleep_ms(int ms)
Definition time.cc:85
double BLI_time_now_seconds(void)
Definition time.cc:65
#define TIP_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ MARKER_DISABLED
@ TRACK_HIDDEN
@ TRACK_LOCKED
@ TRACKING_SPEED_DOUBLE
@ TRACKING_SPEED_HALF
@ TRACKING_SPEED_FASTEST
@ TRACKING_SPEED_QUARTER
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
MovieClip * ED_space_clip_get_clip(const SpaceClip *sc)
int ED_space_clip_get_clip_frame_number(const SpaceClip *sc)
bool ED_space_clip_tracking_poll(bContext *C)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
@ WM_JOB_TYPE_ANY
Definition WM_api.hh:1725
@ WM_JOB_TYPE_CLIP_TRACK_MARKERS
Definition WM_api.hh:1739
@ WM_JOB_PROGRESS
Definition WM_api.hh:1716
#define NA_EVALUATED
Definition WM_types.hh:582
#define NC_MOVIECLIP
Definition WM_types.hh:394
#define NC_SCENE
Definition WM_types.hh:375
#define ND_FRAME
Definition WM_types.hh:431
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void * first
ListBase wm
Definition BKE_main.hh:276
void * tracking_context
struct MovieTracking tracking
MovieTrackingSettings settings
struct RenderData r
struct MovieClipUser user
wmWindowManager * wm
AutoTrackContext * context
wmEventType type
Definition WM_types.hh:754
struct PointerRNA * ptr
void clip_tracking_clear_invisible_track_selection(SpaceClip *sc, MovieClip *clip)
static wmOperatorStatus track_markers_exec(bContext *C, wmOperator *op)
static wmOperatorStatus refine_marker_exec(bContext *C, wmOperator *op)
static void track_markers_endjob(void *tmv)
static bool track_markers_check_direction(int backwards, int curfra, int efra)
static wmOperatorStatus track_markers(bContext *C, wmOperator *op, bool use_job)
void CLIP_OT_track_markers(wmOperatorType *ot)
static void track_markers_startjob(void *tmv, wmJobWorkerStatus *worker_status)
static std::string track_markers_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
static void track_markers_updatejob(void *tmv)
static wmOperatorStatus track_markers_modal(bContext *C, wmOperator *, const wmEvent *event)
static bool track_markers_initjob(bContext *C, TrackMarkersJob *tmj, bool backwards, bool sequence)
static bool track_markers_testbreak()
void CLIP_OT_refine_markers(wmOperatorType *ot)
static wmOperatorStatus track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void track_markers_freejob(void *tmv)
static int track_count_markers(SpaceClip *sc, MovieClip *clip, const int framenr)
static void track_init_markers(SpaceClip *sc, MovieClip *clip, const int framenr, int *r_frames_limit)
void WM_cursor_wait(bool val)
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
@ EVT_ESCKEY
PointerRNA * ptr
Definition wm_files.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:353
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:456
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:190
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:365
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:224
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:337