2014-06-22 16:19:48 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2011 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-06 05:42:22 +01:00
|
|
|
/** \file \ingroup bke
|
2014-06-22 16:19:48 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2017-11-26 17:25:41 +01:00
|
|
|
#include "atomic_ops.h"
|
2014-06-22 16:19:48 +02:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_movieclip_types.h"
|
|
|
|
#include "DNA_object_types.h" /* SELECT */
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h"
|
2017-05-26 15:21:15 +02:00
|
|
|
#include "BLI_listbase.h"
|
2017-11-26 17:25:41 +01:00
|
|
|
#include "BLI_task.h"
|
2017-05-26 15:21:15 +02:00
|
|
|
#include "BLI_threads.h"
|
2014-06-22 16:19:48 +02:00
|
|
|
#include "BLI_math.h"
|
|
|
|
|
|
|
|
#include "BKE_movieclip.h"
|
|
|
|
#include "BKE_tracking.h"
|
|
|
|
|
|
|
|
#include "libmv-capi.h"
|
|
|
|
#include "tracking_private.h"
|
|
|
|
|
|
|
|
typedef struct AutoTrackOptions {
|
|
|
|
int clip_index; /** Index of the clip this track belogs 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. */
|
|
|
|
bool use_keyframe_match; /* Keyframe pattern matching. */
|
|
|
|
|
|
|
|
/* TODO(sergey): A bit awkward to keep it in here, only used to
|
2014-11-01 14:31:09 +01:00
|
|
|
* place a disabled marker once the tracking fails,
|
2014-06-22 16:19:48 +02:00
|
|
|
* Wither find a more clear way to do it or call it track context
|
|
|
|
* or state, not options.
|
|
|
|
*/
|
|
|
|
bool is_failed;
|
|
|
|
int failed_frame;
|
|
|
|
} AutoTrackOptions;
|
|
|
|
|
|
|
|
typedef struct AutoTrackContext {
|
|
|
|
MovieClip *clips[MAX_ACCESSOR_CLIP];
|
|
|
|
int num_clips;
|
|
|
|
|
|
|
|
MovieClipUser user;
|
|
|
|
int frame_width, frame_height;
|
|
|
|
|
|
|
|
struct libmv_AutoTrack *autotrack;
|
|
|
|
TrackingImageAccessor *image_accessor;
|
|
|
|
|
|
|
|
int num_tracks; /* Number of tracks being tracked. */
|
|
|
|
AutoTrackOptions *options; /* Per-tracking track options. */
|
|
|
|
|
2017-05-26 15:21:15 +02:00
|
|
|
/* Array of all tracks, indexed by track_index. */
|
|
|
|
MovieTrackingTrack **tracks;
|
|
|
|
|
2014-06-22 16:19:48 +02:00
|
|
|
bool backwards;
|
|
|
|
bool sequence;
|
|
|
|
int first_frame;
|
|
|
|
int sync_frame;
|
|
|
|
bool first_sync;
|
|
|
|
SpinLock spin_lock;
|
2017-11-26 17:25:41 +01:00
|
|
|
|
|
|
|
bool step_ok;
|
2014-06-22 16:19:48 +02:00
|
|
|
} AutoTrackContext;
|
|
|
|
|
|
|
|
static void normalized_to_libmv_frame(const float normalized[2],
|
|
|
|
const int frame_dimensions[2],
|
|
|
|
float result[2])
|
|
|
|
{
|
|
|
|
result[0] = normalized[0] * frame_dimensions[0] - 0.5f;
|
|
|
|
result[1] = normalized[1] * frame_dimensions[1] - 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void normalized_relative_to_libmv_frame(const float normalized[2],
|
|
|
|
const float origin[2],
|
|
|
|
const int frame_dimensions[2],
|
|
|
|
float result[2])
|
|
|
|
{
|
|
|
|
result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f;
|
|
|
|
result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void libmv_frame_to_normalized(const float frame_coord[2],
|
|
|
|
const int frame_dimensions[2],
|
|
|
|
float result[2])
|
|
|
|
{
|
|
|
|
result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0];
|
|
|
|
result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void libmv_frame_to_normalized_relative(const float frame_coord[2],
|
|
|
|
const float origin[2],
|
|
|
|
const int frame_dimensions[2],
|
|
|
|
float result[2])
|
|
|
|
{
|
|
|
|
result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0];
|
|
|
|
result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
|
|
|
|
/*const*/ MovieTrackingMarker *marker,
|
|
|
|
int clip,
|
|
|
|
int track_index,
|
|
|
|
int frame_width,
|
|
|
|
int frame_height,
|
|
|
|
bool backwards,
|
|
|
|
libmv_Marker *libmv_marker)
|
|
|
|
{
|
|
|
|
const int frame_dimensions[2] = {frame_width, frame_height};
|
|
|
|
int i;
|
|
|
|
libmv_marker->clip = clip;
|
|
|
|
libmv_marker->frame = marker->framenr;
|
|
|
|
libmv_marker->track = track_index;
|
|
|
|
|
|
|
|
normalized_to_libmv_frame(marker->pos,
|
|
|
|
frame_dimensions,
|
|
|
|
libmv_marker->center);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
|
|
normalized_relative_to_libmv_frame(marker->pattern_corners[i],
|
|
|
|
marker->pos,
|
|
|
|
frame_dimensions,
|
|
|
|
libmv_marker->patch[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
normalized_relative_to_libmv_frame(marker->search_min,
|
|
|
|
marker->pos,
|
|
|
|
frame_dimensions,
|
|
|
|
libmv_marker->search_region_min);
|
|
|
|
|
|
|
|
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. */
|
|
|
|
libmv_marker->weight = 1.0f;
|
|
|
|
|
|
|
|
if (marker->flag & MARKER_TRACKED) {
|
|
|
|
libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL;
|
|
|
|
}
|
|
|
|
libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN;
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
libmv_marker->reference_clip = clip;
|
|
|
|
|
|
|
|
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
|
|
|
|
MovieTrackingMarker *keyframe_marker =
|
|
|
|
tracking_get_keyframed_marker(track,
|
|
|
|
marker->framenr,
|
|
|
|
backwards);
|
|
|
|
libmv_marker->reference_frame = keyframe_marker->framenr;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
libmv_marker->reference_frame = backwards ?
|
|
|
|
marker->framenr - 1 :
|
|
|
|
marker->framenr;
|
|
|
|
}
|
2014-10-30 19:13:53 +01:00
|
|
|
|
|
|
|
libmv_marker->disabled_channels =
|
|
|
|
((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) |
|
|
|
|
((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
|
|
|
|
((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0);
|
2014-06-22 16:19:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
|
|
|
|
int frame_width,
|
|
|
|
int frame_height,
|
|
|
|
MovieTrackingMarker *marker)
|
|
|
|
{
|
|
|
|
const int frame_dimensions[2] = {frame_width, frame_height};
|
|
|
|
int i;
|
|
|
|
marker->framenr = libmv_marker->frame;
|
|
|
|
|
|
|
|
libmv_frame_to_normalized(libmv_marker->center,
|
|
|
|
frame_dimensions,
|
|
|
|
marker->pos);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
|
|
libmv_frame_to_normalized_relative(libmv_marker->patch[i],
|
|
|
|
libmv_marker->center,
|
|
|
|
frame_dimensions,
|
|
|
|
marker->pattern_corners[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
libmv_frame_to_normalized_relative(libmv_marker->search_region_min,
|
|
|
|
libmv_marker->center,
|
|
|
|
frame_dimensions,
|
|
|
|
marker->search_min);
|
|
|
|
|
|
|
|
libmv_frame_to_normalized_relative(libmv_marker->search_region_max,
|
|
|
|
libmv_marker->center,
|
|
|
|
frame_dimensions,
|
|
|
|
marker->search_max);
|
|
|
|
|
|
|
|
marker->flag = 0;
|
|
|
|
if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) {
|
|
|
|
marker->flag |= MARKER_TRACKED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
marker->flag &= ~MARKER_TRACKED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-15 12:23:35 +01:00
|
|
|
static bool check_track_trackable(const MovieClip *clip,
|
2014-06-22 16:19:48 +02:00
|
|
|
MovieTrackingTrack *track,
|
2017-12-15 12:23:35 +01:00
|
|
|
const MovieClipUser *user)
|
2014-06-22 16:19:48 +02:00
|
|
|
{
|
|
|
|
if (TRACK_SELECTED(track) &&
|
|
|
|
(track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0)
|
|
|
|
{
|
2017-12-15 12:23:35 +01:00
|
|
|
int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
|
|
|
|
const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, frame);
|
2014-06-22 16:19:48 +02:00
|
|
|
return (marker->flag & MARKER_DISABLED) == 0;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns false if marker crossed margin area from frame bounds. */
|
|
|
|
static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
|
|
|
|
int margin,
|
|
|
|
int frame_width,
|
|
|
|
int frame_height)
|
|
|
|
{
|
|
|
|
float patch_min[2], patch_max[2];
|
|
|
|
float margin_left, margin_top, margin_right, margin_bottom;
|
|
|
|
|
|
|
|
INIT_MINMAX2(patch_min, patch_max);
|
|
|
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]);
|
|
|
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]);
|
|
|
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]);
|
|
|
|
minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]);
|
|
|
|
|
|
|
|
margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin);
|
|
|
|
margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin);
|
|
|
|
margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin);
|
|
|
|
margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin);
|
|
|
|
|
|
|
|
if (libmv_marker->center[0] < margin_left ||
|
|
|
|
libmv_marker->center[0] > frame_width - margin_right ||
|
|
|
|
libmv_marker->center[1] < margin_bottom ||
|
|
|
|
libmv_marker->center[1] > frame_height - margin_top)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-12-15 12:35:41 +01:00
|
|
|
/* 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)
|
|
|
|
{
|
2017-12-15 12:51:53 +01:00
|
|
|
/* Count number of markers to be put to a context. */
|
2017-12-15 13:53:44 +01:00
|
|
|
size_t num_trackable_markers = 0;
|
2017-12-15 12:51:53 +01:00
|
|
|
for (MovieTrackingTrack *track = tracksbase->first;
|
|
|
|
track != NULL;
|
|
|
|
track = track->next)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < track->markersnr; ++i) {
|
|
|
|
const MovieTrackingMarker *marker = track->markers + i;
|
|
|
|
if ((marker->flag & MARKER_DISABLED) == 0) {
|
2017-12-15 13:53:44 +01:00
|
|
|
num_trackable_markers++;
|
2017-12-15 12:51:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Early output if we don't have any markers. */
|
2017-12-15 13:53:44 +01:00
|
|
|
if (num_trackable_markers == 0) {
|
2017-12-15 12:51:53 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Allocate memory for all the markers. */
|
|
|
|
libmv_Marker *libmv_markers = MEM_mallocN(
|
2017-12-15 13:53:44 +01:00
|
|
|
sizeof(libmv_Marker) * num_trackable_markers,
|
2017-12-15 12:51:53 +01:00
|
|
|
"libmv markers array");
|
|
|
|
/* Fill in markers array. */
|
|
|
|
int track_index = 0, num_filled_libmv_markers = 0;
|
2017-12-15 12:35:41 +01:00
|
|
|
for (MovieTrackingTrack *track = tracksbase->first;
|
|
|
|
track != NULL;
|
|
|
|
track = track->next)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < track->markersnr; ++i) {
|
|
|
|
MovieTrackingMarker *marker = track->markers + i;
|
|
|
|
if ((marker->flag & MARKER_DISABLED) != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-12-15 12:51:53 +01:00
|
|
|
dna_marker_to_libmv_marker(
|
|
|
|
track,
|
|
|
|
marker,
|
|
|
|
0,
|
|
|
|
track_index,
|
|
|
|
frame_width, frame_height,
|
|
|
|
backwards,
|
|
|
|
&libmv_markers[num_filled_libmv_markers++]);
|
2017-12-15 12:35:41 +01:00
|
|
|
}
|
2017-12-15 12:51:53 +01:00
|
|
|
/* Put all markers to autotrack at once. */
|
2017-12-15 12:35:41 +01:00
|
|
|
track_index++;
|
|
|
|
}
|
2017-12-15 12:51:53 +01:00
|
|
|
/* Add all markers to autotrack. */
|
|
|
|
libmv_autoTrackSetMarkers(autotrack,
|
|
|
|
libmv_markers,
|
2017-12-15 13:53:44 +01:00
|
|
|
num_trackable_markers);
|
2017-12-15 12:51:53 +01:00
|
|
|
/* Free temporary memory. */
|
|
|
|
MEM_freeN(libmv_markers);
|
2017-12-15 12:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void create_per_track_tracking_options(const MovieClip *clip,
|
|
|
|
const MovieClipUser *user,
|
|
|
|
const ListBase *tracksbase,
|
|
|
|
AutoTrackContext *context)
|
|
|
|
{
|
|
|
|
/* Count number of trackable tracks. */
|
|
|
|
for (MovieTrackingTrack *track = tracksbase->first;
|
|
|
|
track != NULL;
|
|
|
|
track = track->next)
|
|
|
|
{
|
|
|
|
if (check_track_trackable(clip, track, user)) {
|
|
|
|
context->num_tracks++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Allocate required memory. */
|
|
|
|
context->options =
|
|
|
|
MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks,
|
|
|
|
"auto track options");
|
|
|
|
/* Fill in all the settings. */
|
|
|
|
int i = 0, track_index = 0;
|
|
|
|
for (MovieTrackingTrack *track = tracksbase->first;
|
|
|
|
track != NULL;
|
|
|
|
track = track->next)
|
|
|
|
{
|
|
|
|
if (!check_track_trackable(clip, track, user)) {
|
|
|
|
++track_index;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
AutoTrackOptions *options = &context->options[i++];
|
|
|
|
/* TODO(sergey): Single clip only for now. */
|
|
|
|
options->clip_index = 0;
|
|
|
|
options->track_index = track_index;
|
|
|
|
options->track = track;
|
|
|
|
tracking_configure_tracker(track,
|
|
|
|
NULL,
|
|
|
|
&options->track_region_options);
|
|
|
|
options->use_keyframe_match =
|
|
|
|
track->pattern_match == TRACK_MATCH_KEYFRAME;
|
|
|
|
context->tracks[track_index] = track;
|
|
|
|
++track_index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-22 16:19:48 +02:00
|
|
|
AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
|
|
|
|
MovieClipUser *user,
|
|
|
|
const bool backwards,
|
|
|
|
const bool sequence)
|
|
|
|
{
|
|
|
|
AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext),
|
|
|
|
"autotrack context");
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
|
|
|
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
|
2017-12-15 12:35:41 +01:00
|
|
|
int frame_width, frame_height;
|
|
|
|
/* get size of frame to convert normalized coordinates to a picture ones. */
|
2014-06-22 16:19:48 +02:00
|
|
|
BKE_movieclip_get_size(clip, user, &frame_width, &frame_height);
|
|
|
|
/* TODO(sergey): Currently using only a single clip. */
|
|
|
|
context->clips[0] = clip;
|
|
|
|
context->num_clips = 1;
|
|
|
|
context->user = *user;
|
|
|
|
context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
|
|
|
|
context->user.render_flag = 0;
|
|
|
|
context->frame_width = frame_width;
|
|
|
|
context->frame_height = frame_height;
|
|
|
|
context->backwards = backwards;
|
|
|
|
context->sequence = sequence;
|
|
|
|
context->first_frame = user->framenr;
|
|
|
|
context->sync_frame = user->framenr;
|
|
|
|
context->first_sync = true;
|
|
|
|
BLI_spin_init(&context->spin_lock);
|
2017-12-15 12:35:41 +01:00
|
|
|
const int num_total_tracks = BLI_listbase_count(tracksbase);
|
2017-05-26 15:21:15 +02:00
|
|
|
context->tracks =
|
2017-12-15 12:35:41 +01:00
|
|
|
MEM_callocN(sizeof(MovieTrackingTrack *) * num_total_tracks,
|
|
|
|
"auto track pointers");
|
|
|
|
/* Initialize image accessor. */
|
2014-06-22 16:19:48 +02:00
|
|
|
context->image_accessor =
|
2017-05-26 15:21:15 +02:00
|
|
|
tracking_image_accessor_new(context->clips, 1,
|
|
|
|
context->tracks, num_total_tracks,
|
|
|
|
user->framenr);
|
2017-12-15 12:35:41 +01:00
|
|
|
/* Initialize auto track context and provide all information about currently
|
|
|
|
* tracked markers.
|
|
|
|
*/
|
2014-06-22 16:19:48 +02:00
|
|
|
context->autotrack =
|
2017-12-15 12:35:41 +01:00
|
|
|
libmv_autoTrackNew(context->image_accessor->libmv_accessor);
|
|
|
|
fill_autotrack_tracks(frame_width, frame_height,
|
|
|
|
tracksbase,
|
|
|
|
backwards,
|
|
|
|
context->autotrack);
|
2014-06-22 16:19:48 +02:00
|
|
|
/* Create per-track tracking options. */
|
2017-12-15 12:35:41 +01:00
|
|
|
create_per_track_tracking_options(clip, user, tracksbase, context);
|
2014-06-22 16:19:48 +02:00
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
2018-01-10 12:49:51 +01:00
|
|
|
static void autotrack_context_step_cb(
|
|
|
|
void *__restrict userdata,
|
2018-01-10 12:53:59 +01:00
|
|
|
const int track,
|
2018-01-10 12:49:51 +01:00
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
2014-06-22 16:19:48 +02:00
|
|
|
{
|
2017-11-26 17:25:41 +01:00
|
|
|
AutoTrackContext *context = userdata;
|
2017-08-14 10:23:29 +02:00
|
|
|
const int frame_delta = context->backwards ? -1 : 1;
|
2017-11-26 17:25:41 +01:00
|
|
|
|
|
|
|
AutoTrackOptions *options = &context->options[track];
|
|
|
|
if (options->is_failed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
libmv_Marker libmv_current_marker,
|
|
|
|
libmv_reference_marker,
|
|
|
|
libmv_tracked_marker;
|
|
|
|
libmv_TrackRegionResult libmv_result;
|
|
|
|
const int frame = BKE_movieclip_remap_scene_to_clip_frame(
|
|
|
|
context->clips[options->clip_index],
|
|
|
|
context->user.framenr);
|
|
|
|
BLI_spin_lock(&context->spin_lock);
|
|
|
|
const bool has_marker = libmv_autoTrackGetMarker(context->autotrack,
|
|
|
|
options->clip_index,
|
|
|
|
frame,
|
|
|
|
options->track_index,
|
|
|
|
&libmv_current_marker);
|
|
|
|
BLI_spin_unlock(&context->spin_lock);
|
|
|
|
/* Check whether we've got marker to sync with. */
|
|
|
|
if (!has_marker) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Check whether marker is going outside of allowed frame margin. */
|
|
|
|
if (!tracking_check_marker_margin(&libmv_current_marker,
|
|
|
|
options->track->margin,
|
|
|
|
context->frame_width,
|
|
|
|
context->frame_height))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
libmv_tracked_marker = libmv_current_marker;
|
|
|
|
libmv_tracked_marker.frame = frame + frame_delta;
|
|
|
|
/* Update reference frame. */
|
|
|
|
if (options->use_keyframe_match) {
|
|
|
|
libmv_tracked_marker.reference_frame =
|
|
|
|
libmv_current_marker.reference_frame;
|
|
|
|
libmv_autoTrackGetMarker(context->autotrack,
|
|
|
|
options->clip_index,
|
|
|
|
libmv_tracked_marker.reference_frame,
|
|
|
|
options->track_index,
|
|
|
|
&libmv_reference_marker);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
libmv_tracked_marker.reference_frame = frame;
|
|
|
|
libmv_reference_marker = libmv_current_marker;
|
|
|
|
}
|
|
|
|
/* Perform actual tracking. */
|
|
|
|
if (libmv_autoTrackMarker(context->autotrack,
|
|
|
|
&options->track_region_options,
|
|
|
|
&libmv_tracked_marker,
|
|
|
|
&libmv_result))
|
|
|
|
{
|
2014-12-15 10:31:19 +01:00
|
|
|
BLI_spin_lock(&context->spin_lock);
|
2017-11-26 17:25:41 +01:00
|
|
|
libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
|
2014-12-15 10:31:19 +01:00
|
|
|
BLI_spin_unlock(&context->spin_lock);
|
2014-06-22 16:19:48 +02:00
|
|
|
}
|
2017-11-26 17:25:41 +01:00
|
|
|
else {
|
|
|
|
options->is_failed = true;
|
|
|
|
options->failed_frame = frame + frame_delta;
|
|
|
|
}
|
|
|
|
|
2017-11-27 08:50:01 +01:00
|
|
|
/* Note: Atomic is probably not actually needed here, I doubt we could get
|
|
|
|
* any other result than a true bool anyway.
|
|
|
|
* But for sake of consistency, and since it costs nothing...
|
|
|
|
*/
|
2017-11-26 17:25:41 +01:00
|
|
|
atomic_fetch_and_or_uint8((uint8_t *)&context->step_ok, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BKE_autotrack_context_step(AutoTrackContext *context)
|
|
|
|
{
|
|
|
|
const int frame_delta = context->backwards ? -1 : 1;
|
|
|
|
context->step_ok = false;
|
|
|
|
|
2018-01-08 11:35:48 +01:00
|
|
|
ParallelRangeSettings settings;
|
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
settings.use_threading = (context->num_tracks > 1);
|
2017-11-27 08:50:01 +01:00
|
|
|
BLI_task_parallel_range(0, context->num_tracks,
|
|
|
|
context,
|
|
|
|
autotrack_context_step_cb,
|
2018-01-08 11:35:48 +01:00
|
|
|
&settings);
|
2017-11-26 17:25:41 +01:00
|
|
|
|
2017-08-14 10:23:29 +02:00
|
|
|
/* Advance the frame. */
|
2014-06-22 16:19:48 +02:00
|
|
|
BLI_spin_lock(&context->spin_lock);
|
|
|
|
context->user.framenr += frame_delta;
|
|
|
|
BLI_spin_unlock(&context->spin_lock);
|
2017-11-26 17:25:41 +01:00
|
|
|
return context->step_ok;
|
2014-06-22 16:19:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_autotrack_context_sync(AutoTrackContext *context)
|
|
|
|
{
|
2014-12-15 10:34:47 +01:00
|
|
|
int newframe, frame_delta = context->backwards ? -1 : 1;
|
2015-11-23 01:27:02 +01:00
|
|
|
int frame;
|
2014-06-22 16:19:48 +02:00
|
|
|
|
|
|
|
BLI_spin_lock(&context->spin_lock);
|
2014-12-15 10:34:47 +01:00
|
|
|
newframe = context->user.framenr;
|
2014-06-22 16:19:48 +02:00
|
|
|
for (frame = context->sync_frame;
|
|
|
|
frame != (context->backwards ? newframe - 1 : newframe + 1);
|
|
|
|
frame += frame_delta)
|
|
|
|
{
|
|
|
|
MovieTrackingMarker marker;
|
|
|
|
libmv_Marker libmv_marker;
|
|
|
|
int clip = 0;
|
|
|
|
int track;
|
|
|
|
for (track = 0; track < context->num_tracks; ++track) {
|
|
|
|
AutoTrackOptions *options = &context->options[track];
|
|
|
|
int track_frame = BKE_movieclip_remap_scene_to_clip_frame(
|
|
|
|
context->clips[options->clip_index], frame);
|
2016-07-21 16:53:45 +02:00
|
|
|
if (options->is_failed) {
|
|
|
|
if (options->failed_frame == track_frame) {
|
|
|
|
MovieTrackingMarker *prev_marker =
|
|
|
|
BKE_tracking_marker_get_exact(
|
|
|
|
options->track,
|
|
|
|
context->backwards
|
|
|
|
? frame + 1
|
|
|
|
: frame - 1);
|
|
|
|
if (prev_marker) {
|
|
|
|
marker = *prev_marker;
|
|
|
|
marker.framenr = track_frame;
|
|
|
|
marker.flag |= MARKER_DISABLED;
|
|
|
|
BKE_tracking_marker_insert(options->track, &marker);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((context->backwards && options->failed_frame > track_frame) ||
|
|
|
|
(!context->backwards && options->failed_frame < track_frame))
|
|
|
|
{
|
2014-12-15 10:39:59 +01:00
|
|
|
continue;
|
2014-06-22 16:19:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (libmv_autoTrackGetMarker(context->autotrack,
|
|
|
|
clip,
|
|
|
|
track_frame,
|
|
|
|
options->track_index,
|
|
|
|
&libmv_marker))
|
|
|
|
{
|
|
|
|
libmv_marker_to_dna_marker(&libmv_marker,
|
|
|
|
context->frame_width,
|
|
|
|
context->frame_height,
|
|
|
|
&marker);
|
|
|
|
if (context->first_sync && frame == context->sync_frame) {
|
|
|
|
tracking_marker_insert_disabled(options->track,
|
|
|
|
&marker,
|
|
|
|
!context->backwards,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
BKE_tracking_marker_insert(options->track, &marker);
|
|
|
|
tracking_marker_insert_disabled(options->track,
|
|
|
|
&marker,
|
|
|
|
context->backwards,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BLI_spin_unlock(&context->spin_lock);
|
|
|
|
|
2015-11-23 01:27:02 +01:00
|
|
|
for (int clip = 0; clip < context->num_clips; ++clip) {
|
2014-06-22 16:19:48 +02:00
|
|
|
MovieTracking *tracking = &context->clips[clip]->tracking;
|
|
|
|
BKE_tracking_dopesheet_tag_update(tracking);
|
|
|
|
}
|
|
|
|
|
|
|
|
context->sync_frame = newframe;
|
|
|
|
context->first_sync = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_autotrack_context_sync_user(AutoTrackContext *context,
|
|
|
|
MovieClipUser *user)
|
|
|
|
{
|
|
|
|
user->framenr = context->sync_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_autotrack_context_finish(AutoTrackContext *context)
|
|
|
|
{
|
|
|
|
int clip_index;
|
|
|
|
|
|
|
|
for (clip_index = 0; clip_index < context->num_clips; ++clip_index) {
|
|
|
|
MovieClip *clip = context->clips[clip_index];
|
|
|
|
ListBase *plane_tracks_base =
|
|
|
|
BKE_tracking_get_active_plane_tracks(&clip->tracking);
|
|
|
|
MovieTrackingPlaneTrack *plane_track;
|
|
|
|
|
|
|
|
for (plane_track = plane_tracks_base->first;
|
|
|
|
plane_track;
|
|
|
|
plane_track = plane_track->next)
|
|
|
|
{
|
|
|
|
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
|
|
|
|
int track;
|
|
|
|
for (track = 0; track < context->num_tracks; ++track) {
|
2017-11-27 08:50:01 +01:00
|
|
|
if (BKE_tracking_plane_track_has_point_track(
|
|
|
|
plane_track,
|
|
|
|
context->options[track].track))
|
2015-04-22 09:34:01 +02:00
|
|
|
{
|
2014-06-22 16:19:48 +02:00
|
|
|
BKE_tracking_track_plane_from_existing_motion(
|
|
|
|
plane_track,
|
|
|
|
context->first_frame);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_autotrack_context_free(AutoTrackContext *context)
|
|
|
|
{
|
|
|
|
libmv_autoTrackDestroy(context->autotrack);
|
|
|
|
tracking_image_accessor_destroy(context->image_accessor);
|
|
|
|
MEM_freeN(context->options);
|
2017-05-26 15:21:15 +02:00
|
|
|
MEM_freeN(context->tracks);
|
2014-06-22 16:19:48 +02:00
|
|
|
BLI_spin_end(&context->spin_lock);
|
|
|
|
MEM_freeN(context);
|
|
|
|
}
|