Blender  V2.93
tracking_util.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 Blender Foundation.
17  * All rights reserved.
18  */
19 
27 #include <stddef.h>
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "DNA_movieclip_types.h"
32 
33 #include "BLI_ghash.h"
34 #include "BLI_listbase.h"
35 #include "BLI_math.h"
36 #include "BLI_string.h"
37 #include "BLI_string_utils.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40 
41 #include "BLT_translation.h"
42 
43 #include "BKE_movieclip.h"
44 #include "BKE_tracking.h"
45 
46 #include "IMB_imbuf.h"
47 #include "IMB_imbuf_types.h"
48 #include "IMB_moviecache.h"
49 
50 #include "tracking_private.h"
51 
52 #include "libmv-capi.h"
53 
54 /* Uncomment this to have caching-specific debug prints. */
55 // #define DEBUG_CACHE
56 
57 #ifdef DEBUG_CACHE
58 # define CACHE_PRINTF(...) printf(__VA_ARGS__)
59 #else
60 # define CACHE_PRINTF(...)
61 #endif
62 
63 /* -------------------------------------------------------------------- */
67 TracksMap *tracks_map_new(const char *object_name,
68  bool is_camera,
69  int num_tracks,
70  int customdata_size)
71 {
72  TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
73 
74  BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
75  map->is_camera = is_camera;
76 
77  map->num_tracks = num_tracks;
78  map->customdata_size = customdata_size;
79 
80  map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
81 
82  if (customdata_size) {
83  map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
84  }
85 
86  map->hash = BLI_ghash_ptr_new("TracksMap hash");
87 
88  BLI_spin_init(&map->spin_lock);
89 
90  return map;
91 }
92 
94 {
95  return map->num_tracks;
96 }
97 
99  int index,
100  MovieTrackingTrack **track,
101  void **customdata)
102 {
103  *track = &map->tracks[index];
104 
105  if (map->customdata) {
106  *customdata = &map->customdata[index * map->customdata_size];
107  }
108 }
109 
110 void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
111 {
112  MovieTrackingTrack new_track = *track;
113 
114  new_track.markers = MEM_dupallocN(new_track.markers);
115 
116  map->tracks[map->ptr] = new_track;
117 
118  if (customdata) {
119  memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
120  }
121 
122  BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
123 
124  map->ptr++;
125 }
126 
128 {
129  MovieTrackingTrack *track;
130  ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
131  ListBase *old_tracks;
132 
133  if (map->is_camera) {
134  old_tracks = &tracking->tracks;
135  }
136  else {
138 
139  if (!object) {
140  /* object was deleted by user, create new one */
141  object = BKE_tracking_object_add(tracking, map->object_name);
142  }
143 
144  old_tracks = &object->tracks;
145  }
146 
147  /* duplicate currently operating tracks to temporary list.
148  * this is needed to keep names in unique state and it's faster to change names
149  * of currently operating tracks (if needed)
150  */
151  for (int a = 0; a < map->num_tracks; a++) {
152  MovieTrackingTrack *old_track;
153  bool mapped_to_old = false;
154 
155  track = &map->tracks[a];
156 
157  /* find original of operating track in list of previously displayed tracks */
158  old_track = BLI_ghash_lookup(map->hash, track);
159  if (old_track) {
160  if (BLI_findindex(old_tracks, old_track) != -1) {
161  BLI_remlink(old_tracks, old_track);
162 
163  BLI_spin_lock(&map->spin_lock);
164 
165  /* Copy flags like selection back to the track map. */
166  track->flag = old_track->flag;
167  track->pat_flag = old_track->pat_flag;
168  track->search_flag = old_track->search_flag;
169 
170  /* Copy all the rest settings back from the map to the actual tracks. */
171  MEM_freeN(old_track->markers);
172  *old_track = *track;
173  old_track->markers = MEM_dupallocN(old_track->markers);
174 
175  BLI_spin_unlock(&map->spin_lock);
176 
177  BLI_addtail(&tracks, old_track);
178 
179  mapped_to_old = true;
180  }
181  }
182 
183  if (mapped_to_old == false) {
185 
186  /* Update old-new track mapping */
187  BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL);
188 
189  BLI_addtail(&tracks, new_track);
190  }
191  }
192 
193  /* move all tracks, which aren't operating */
194  track = old_tracks->first;
195  while (track) {
196  MovieTrackingTrack *next = track->next;
197  BLI_addtail(&new_tracks, track);
198  track = next;
199  }
200 
201  /* now move all tracks which are currently operating and keep their names unique */
202  track = tracks.first;
203  while (track) {
204  MovieTrackingTrack *next = track->next;
205 
206  BLI_remlink(&tracks, track);
207 
208  track->next = track->prev = NULL;
209  BLI_addtail(&new_tracks, track);
210 
211  BLI_uniquename(&new_tracks,
212  track,
214  '.',
215  offsetof(MovieTrackingTrack, name),
216  sizeof(track->name));
217 
218  track = next;
219  }
220 
221  *old_tracks = new_tracks;
222 }
223 
224 void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
225 {
226  BLI_ghash_free(map->hash, NULL, NULL);
227 
228  for (int i = 0; i < map->num_tracks; i++) {
229  if (map->customdata && customdata_free) {
230  customdata_free(&map->customdata[i * map->customdata_size]);
231  }
232 
234  }
235 
236  if (map->customdata) {
237  MEM_freeN(map->customdata);
238  }
239 
240  MEM_freeN(map->tracks);
241 
242  BLI_spin_end(&map->spin_lock);
243 
244  MEM_freeN(map);
245 }
246 
249 /* -------------------------------------------------------------------- */
253 /* Three coordinate frames: Frame, Search, and Marker
254  * Two units: Pixels, Unified
255  * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
256  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
257  * coordinates relative to the entire frame.
258  */
259 static void unified_to_pixel(int frame_width,
260  int frame_height,
261  const float unified_coords[2],
262  float pixel_coords[2])
263 {
264  pixel_coords[0] = unified_coords[0] * frame_width;
265  pixel_coords[1] = unified_coords[1] * frame_height;
266 }
267 
269  const float marker_unified_coords[2],
270  float frame_unified_coords[2])
271 {
272  frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
273  frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
274 }
275 
276 static void marker_unified_to_frame_pixel_coordinates(int frame_width,
277  int frame_height,
278  const MovieTrackingMarker *marker,
279  const float marker_unified_coords[2],
280  float frame_pixel_coords[2])
281 {
282  marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
283  unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
284 }
285 
287  int frame_height,
288  const MovieTrackingMarker *marker,
289  float frame_pixel[2])
290 {
291  /* Get the lower left coordinate of the search window and snap to pixel coordinates */
293  frame_width, frame_height, marker, marker->search_min, frame_pixel);
294  frame_pixel[0] = (int)frame_pixel[0];
295  frame_pixel[1] = (int)frame_pixel[1];
296 }
297 
298 static void pixel_to_unified(int frame_width,
299  int frame_height,
300  const float pixel_coords[2],
301  float unified_coords[2])
302 {
303  unified_coords[0] = pixel_coords[0] / frame_width;
304  unified_coords[1] = pixel_coords[1] / frame_height;
305 }
306 
307 static void marker_unified_to_search_pixel(int frame_width,
308  int frame_height,
309  const MovieTrackingMarker *marker,
310  const float marker_unified[2],
311  float search_pixel[2])
312 {
313  float frame_pixel[2];
314  float search_origin_frame_pixel[2];
315 
317  frame_width, frame_height, marker, marker_unified, frame_pixel);
319  frame_width, frame_height, marker, search_origin_frame_pixel);
320  sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
321 }
322 
323 static void search_pixel_to_marker_unified(int frame_width,
324  int frame_height,
325  const MovieTrackingMarker *marker,
326  const float search_pixel[2],
327  float marker_unified[2])
328 {
329  float frame_unified[2];
330  float search_origin_frame_pixel[2];
331 
333  frame_width, frame_height, marker, search_origin_frame_pixel);
334  add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
335  pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
336 
337  /* marker pos is in frame unified */
338  sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
339 }
340 
341 /* Each marker has 5 coordinates associated with it that get warped with
342  * tracking: the four corners ("pattern_corners"), and the center ("pos").
343  * This function puts those 5 points into the appropriate frame for tracking
344  * (the "search" coordinate frame).
345  */
347  int frame_height,
348  const MovieTrackingMarker *marker,
349  double search_pixel_x[5],
350  double search_pixel_y[5])
351 {
352  float unified_coords[2];
353  float pixel_coords[2];
354 
355  /* Convert the corners into search space coordinates. */
356  for (int i = 0; i < 4; i++) {
358  frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
359  search_pixel_x[i] = pixel_coords[0] - 0.5f;
360  search_pixel_y[i] = pixel_coords[1] - 0.5f;
361  }
362 
363  /* Convert the center position (aka "pos"); this is the origin */
364  unified_coords[0] = 0.0f;
365  unified_coords[1] = 0.0f;
366  marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
367 
368  search_pixel_x[4] = pixel_coords[0] - 0.5f;
369  search_pixel_y[4] = pixel_coords[1] - 0.5f;
370 }
371 
372 /* Inverse of above. */
374  int frame_height,
375  MovieTrackingMarker *marker,
376  const double search_pixel_x[5],
377  const double search_pixel_y[5])
378 {
379  float marker_unified[2];
380  float search_pixel[2];
381 
382  /* Convert the corners into search space coordinates. */
383  for (int i = 0; i < 4; i++) {
384  search_pixel[0] = search_pixel_x[i] + 0.5;
385  search_pixel[1] = search_pixel_y[i] + 0.5;
387  frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
388  }
389 
390  /* Convert the center position (aka "pos"); this is the origin */
391  search_pixel[0] = search_pixel_x[4] + 0.5;
392  search_pixel[1] = search_pixel_y[4] + 0.5;
393  search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
394 
395  /* If the tracker tracked nothing, then "marker_unified" would be zero.
396  * Otherwise, the entire patch shifted, and that delta should be applied to
397  * all the coordinates.
398  */
399  for (int i = 0; i < 4; i++) {
400  marker->pattern_corners[i][0] -= marker_unified[0];
401  marker->pattern_corners[i][1] -= marker_unified[1];
402  }
403 
404  marker->pos[0] += marker_unified[0];
405  marker->pos[1] += marker_unified[1];
406 }
407 
410 /* -------------------------------------------------------------------- */
414 /* Place a disabled marker before or after specified ref_marker.
415  *
416  * If before is truth, disabled marker is placed before reference
417  * one, and it's placed after it otherwise.
418  *
419  * If there's already a marker at the frame where disabled one
420  * is expected to be placed, nothing will happen if overwrite
421  * is false.
422  */
424  const MovieTrackingMarker *ref_marker,
425  bool before,
426  bool overwrite)
427 {
428  MovieTrackingMarker marker_new;
429 
430  marker_new = *ref_marker;
431  marker_new.flag &= ~MARKER_TRACKED;
432  marker_new.flag |= MARKER_DISABLED;
433 
434  if (before) {
435  marker_new.framenr--;
436  }
437  else {
438  marker_new.framenr++;
439  }
440 
441  if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr)) {
442  BKE_tracking_marker_insert(track, &marker_new);
443  }
444 }
445 
447  const MovieTrackingCamera *camera, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
448 {
449  switch (camera->distortion_model) {
451  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL;
452  camera_intrinsics_options->polynomial_k1 = camera->k1;
453  camera_intrinsics_options->polynomial_k2 = camera->k2;
454  camera_intrinsics_options->polynomial_k3 = camera->k3;
455  camera_intrinsics_options->polynomial_p1 = 0.0;
456  camera_intrinsics_options->polynomial_p2 = 0.0;
457  return;
458 
460  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_DIVISION;
461  camera_intrinsics_options->division_k1 = camera->division_k1;
462  camera_intrinsics_options->division_k2 = camera->division_k2;
463  return;
464 
466  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_NUKE;
467  camera_intrinsics_options->nuke_k1 = camera->nuke_k1;
468  camera_intrinsics_options->nuke_k2 = camera->nuke_k2;
469  return;
471  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_BROWN;
472  camera_intrinsics_options->brown_k1 = camera->brown_k1;
473  camera_intrinsics_options->brown_k2 = camera->brown_k2;
474  camera_intrinsics_options->brown_k3 = camera->brown_k3;
475  camera_intrinsics_options->brown_k4 = camera->brown_k4;
476  camera_intrinsics_options->brown_p1 = camera->brown_p1;
477  camera_intrinsics_options->brown_p2 = camera->brown_p2;
478  return;
479  }
480 
481  /* Unknown distortion model, which might be due to opening newer file in older Blender.
482  * Fallback to a known and supported model with 0 distortion. */
483  camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL;
484  camera_intrinsics_options->polynomial_k1 = 0.0;
485  camera_intrinsics_options->polynomial_k2 = 0.0;
486  camera_intrinsics_options->polynomial_k3 = 0.0;
487  camera_intrinsics_options->polynomial_p1 = 0.0;
488  camera_intrinsics_options->polynomial_p2 = 0.0;
489 }
490 
492  const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, MovieTrackingCamera *camera)
493 {
494  switch (camera_intrinsics_options->distortion_model) {
497  camera->k1 = camera_intrinsics_options->polynomial_k1;
498  camera->k2 = camera_intrinsics_options->polynomial_k2;
499  camera->k3 = camera_intrinsics_options->polynomial_k3;
500  return;
501 
504  camera->division_k1 = camera_intrinsics_options->division_k1;
505  camera->division_k2 = camera_intrinsics_options->division_k2;
506  return;
507 
510  camera->nuke_k1 = camera_intrinsics_options->nuke_k1;
511  camera->nuke_k2 = camera_intrinsics_options->nuke_k2;
512  return;
515  camera->brown_k1 = camera_intrinsics_options->brown_k1;
516  camera->brown_k2 = camera_intrinsics_options->brown_k2;
517  camera->brown_k3 = camera_intrinsics_options->brown_k3;
518  camera->brown_k4 = camera_intrinsics_options->brown_k4;
519  camera->brown_p1 = camera_intrinsics_options->brown_p1;
520  camera->brown_p2 = camera_intrinsics_options->brown_p2;
521  return;
522  }
523 
524  /* Libmv returned distortion model which is not known to Blender. This is a logical error in code
525  * and Blender side is to be updated to match Libmv. */
526  BLI_assert(!"Unknown distortion model");
527 }
528 
529 /* Fill in Libmv C-API camera intrinsics options from tracking structure. */
531  MovieTracking *tracking,
532  int calibration_width,
533  int calibration_height,
534  libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
535 {
536  MovieTrackingCamera *camera = &tracking->camera;
537  float aspy = 1.0f / tracking->camera.pixel_aspect;
538 
539  camera_intrinsics_options->num_threads = BLI_system_thread_count();
540 
541  camera_intrinsics_options->focal_length = camera->focal;
542 
543  camera_intrinsics_options->principal_point_x = camera->principal[0];
544  camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
545 
546  distortion_model_parameters_from_tracking(camera, camera_intrinsics_options);
547 
548  camera_intrinsics_options->image_width = calibration_width;
549  camera_intrinsics_options->image_height = (int)(calibration_height * aspy);
550 }
551 
553  MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
554 {
555  float aspy = 1.0f / tracking->camera.pixel_aspect;
556  MovieTrackingCamera *camera = &tracking->camera;
557 
558  camera->focal = camera_intrinsics_options->focal_length;
559 
560  camera->principal[0] = camera_intrinsics_options->principal_point_x;
561  camera->principal[1] = camera_intrinsics_options->principal_point_y / (double)aspy;
562 
563  distortion_model_parameters_from_options(camera_intrinsics_options, camera);
564 }
565 
566 /* Get previous keyframed marker. */
568  int current_frame,
569  bool backwards)
570 {
571  MovieTrackingMarker *marker_keyed = NULL;
572  MovieTrackingMarker *marker_keyed_fallback = NULL;
573  int a = BKE_tracking_marker_get(track, current_frame) - track->markers;
574 
575  while (a >= 0 && a < track->markersnr) {
576  int next = backwards ? a + 1 : a - 1;
577  bool is_keyframed = false;
578  MovieTrackingMarker *cur_marker = &track->markers[a];
579  MovieTrackingMarker *next_marker = NULL;
580 
581  if (next >= 0 && next < track->markersnr) {
582  next_marker = &track->markers[next];
583  }
584 
585  if ((cur_marker->flag & MARKER_DISABLED) == 0) {
586  /* If it'll happen so we didn't find a real keyframe marker,
587  * fallback to the first marker in current tracked segment
588  * as a keyframe.
589  */
590  if (next_marker == NULL) {
591  /* Could happen when trying to get reference marker for the fist
592  * one on the segment which isn't surrounded by disabled markers.
593  *
594  * There's no really good choice here, just use the reference
595  * marker which looks correct..
596  */
597  if (marker_keyed_fallback == NULL) {
598  marker_keyed_fallback = cur_marker;
599  }
600  }
601  else if (next_marker->flag & MARKER_DISABLED) {
602  if (marker_keyed_fallback == NULL) {
603  marker_keyed_fallback = cur_marker;
604  }
605  }
606 
607  is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
608  }
609 
610  if (is_keyframed) {
611  marker_keyed = cur_marker;
612 
613  break;
614  }
615 
616  a = next;
617  }
618 
619  if (marker_keyed == NULL) {
620  marker_keyed = marker_keyed_fallback;
621  }
622 
623  return marker_keyed;
624 }
625 
628 /* -------------------------------------------------------------------- */
633  int clip_index,
634  int frame)
635 {
636  MovieClip *clip;
637  MovieClipUser user;
638  ImBuf *ibuf;
639  int scene_frame;
640 
641  BLI_assert(clip_index < accessor->num_clips);
642 
643  clip = accessor->clips[clip_index];
644  scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
645  BKE_movieclip_user_set_frame(&user, scene_frame);
647  user.render_flag = 0;
648  ibuf = BKE_movieclip_get_ibuf(clip, &user);
649 
650  return ibuf;
651 }
652 
654 {
655  ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0);
656 
657  BLI_assert(ELEM(ibuf->channels, 3, 4));
658 
659  /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels
660  * float buffer, so we do it manually here.
661  *
662  * Will generalize it later.
663  */
664  const size_t size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
665  grayscale->channels = 1;
666  if ((grayscale->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) {
667  grayscale->mall |= IB_rectfloat;
668  grayscale->flags |= IB_rectfloat;
669 
670  for (int i = 0; i < grayscale->x * grayscale->y; i++) {
671  const float *pixel = ibuf->rect_float + ibuf->channels * i;
672 
673  grayscale->rect_float[i] = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
674  }
675  }
676 
677  return grayscale;
678 }
679 
680 static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
681 {
682  BLI_assert(ibuf->rect_float != NULL);
683  float_image->buffer = ibuf->rect_float;
684  float_image->width = ibuf->x;
685  float_image->height = ibuf->y;
686  float_image->channels = ibuf->channels;
687 }
688 
690 {
691  ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0);
692  size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float);
693  ibuf->channels = float_image->channels;
694  if ((ibuf->rect_float = MEM_callocN(size, "tracking grayscale image")) != NULL) {
695  ibuf->mall |= IB_rectfloat;
696  ibuf->flags |= IB_rectfloat;
697 
698  memcpy(ibuf->rect_float, float_image->buffer, size);
699  }
700  return ibuf;
701 }
702 
704  int clip_index,
705  int frame,
706  libmv_InputMode input_mode,
707  int downscale,
708  const libmv_Region *region,
710 {
711  /* First try to get fully processed image from the cache. */
712  CACHE_PRINTF("Calculate new buffer for frame %d\n", frame);
713  /* And now we do postprocessing of the original frame. */
714  ImBuf *orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);
715  if (orig_ibuf == NULL) {
716  return NULL;
717  }
718  ImBuf *final_ibuf;
719  /* Cut a region if requested. */
720  if (region != NULL) {
721  int width = region->max[0] - region->min[0], height = region->max[1] - region->min[1];
722 
723  /* If the requested region goes outside of the actual frame we still
724  * return the requested region size, but only fill it's partially with
725  * the data we can.
726  */
727  int clamped_origin_x = max_ii((int)region->min[0], 0),
728  clamped_origin_y = max_ii((int)region->min[1], 0);
729  int dst_offset_x = clamped_origin_x - (int)region->min[0],
730  dst_offset_y = clamped_origin_y - (int)region->min[1];
731  int clamped_width = width - dst_offset_x, clamped_height = height - dst_offset_y;
732  clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
733  clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);
734 
735  final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);
736 
737  if (orig_ibuf->rect_float != NULL) {
738  IMB_rectcpy(final_ibuf,
739  orig_ibuf,
740  dst_offset_x,
741  dst_offset_y,
742  clamped_origin_x,
743  clamped_origin_y,
744  clamped_width,
745  clamped_height);
746  }
747  else {
748  /* TODO(sergey): We don't do any color space or alpha conversion
749  * here. Probably Libmv is better to work in the linear space,
750  * but keep sRGB space here for compatibility for now.
751  */
752  for (int y = 0; y < clamped_height; y++) {
753  for (int x = 0; x < clamped_width; x++) {
754  int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y;
755  int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y;
756  int dst_index = (dst_y * width + dst_x) * 4,
757  src_index = (src_y * orig_ibuf->x + src_x) * 4;
758  rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
759  (unsigned char *)orig_ibuf->rect + src_index);
760  }
761  }
762  }
763  }
764  else {
765  /* Libmv only works with float images,
766  *
767  * This would likely make it so loads of float buffers are being stored
768  * in the cache which is nice on the one hand (faster re-use of the
769  * frames) but on the other hand it bumps the memory usage up.
770  */
772  IMB_float_from_rect(orig_ibuf);
774  final_ibuf = orig_ibuf;
775  }
776  /* Downscale if needed. */
777  if (downscale > 0) {
778  if (final_ibuf == orig_ibuf) {
779  final_ibuf = IMB_dupImBuf(orig_ibuf);
780  }
781  IMB_scaleImBuf(final_ibuf, orig_ibuf->x / (1 << downscale), orig_ibuf->y / (1 << downscale));
782  }
783  /* Apply possible transformation. */
784  if (transform != NULL) {
785  libmv_FloatImage input_image, output_image;
786  ibuf_to_float_image(final_ibuf, &input_image);
787  libmv_frameAccessorgetTransformRun(transform, &input_image, &output_image);
788  if (final_ibuf != orig_ibuf) {
789  IMB_freeImBuf(final_ibuf);
790  }
791  final_ibuf = float_image_to_ibuf(&output_image);
792  libmv_floatImageDestroy(&output_image);
793  }
794  /* Transform number of channels. */
795  if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
796  BLI_assert(ELEM(orig_ibuf->channels, 3, 4));
797  /* pass */
798  }
799  else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
800  BLI_assert(input_mode == LIBMV_IMAGE_MODE_MONO);
801  if (final_ibuf->channels != 1) {
802  ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
803  if (final_ibuf != orig_ibuf) {
804  /* We dereference original frame later. */
805  IMB_freeImBuf(final_ibuf);
806  }
807  final_ibuf = grayscale_ibuf;
808  }
809  }
810  /* It's possible processing still didn't happen at this point,
811  * but we really need a copy of the buffer to be transformed
812  * and to be put to the cache.
813  */
814  if (final_ibuf == orig_ibuf) {
815  final_ibuf = IMB_dupImBuf(orig_ibuf);
816  }
817  IMB_freeImBuf(orig_ibuf);
818  return final_ibuf;
819 }
820 
822  int clip_index,
823  int frame,
824  libmv_InputMode input_mode,
825  int downscale,
826  const libmv_Region *region,
828  float **destination,
829  int *width,
830  int *height,
831  int *channels)
832 {
834  ImBuf *ibuf;
835 
836  BLI_assert(clip_index >= 0 && clip_index < accessor->num_clips);
837 
838  ibuf = accessor_get_ibuf(accessor, clip_index, frame, input_mode, downscale, region, transform);
839 
840  if (ibuf) {
841  *destination = ibuf->rect_float;
842  *width = ibuf->x;
843  *height = ibuf->y;
844  *channels = ibuf->channels;
845  }
846  else {
847  *destination = NULL;
848  *width = 0;
849  *height = 0;
850  *channels = 0;
851  }
852 
853  return ibuf;
854 }
855 
857 {
858  ImBuf *ibuf = (ImBuf *)cache_key;
859  IMB_freeImBuf(ibuf);
860 }
861 
863  int clip_index,
864  int frame,
865  int track_index,
866  const libmv_Region *region,
867  float **r_destination,
868  int *r_width,
869  int *r_height)
870 {
871  /* Perform sanity checks first. */
873  BLI_assert(clip_index < accessor->num_clips);
874  BLI_assert(track_index < accessor->num_tracks);
875  MovieTrackingTrack *track = accessor->tracks[track_index];
876  /* Early output, track does not use mask. */
877  if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) {
878  return NULL;
879  }
880  MovieClip *clip = accessor->clips[clip_index];
881  /* Construct fake user so we can access movie clip. */
882  MovieClipUser user;
883  int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
884  BKE_movieclip_user_set_frame(&user, scene_frame);
886  user.render_flag = 0;
887  /* Get frame width and height so we can convert stroke coordinates
888  * and other things from normalized to pixel space.
889  */
890  int frame_width, frame_height;
891  BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
892  /* Actual mask sampling. */
893  MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame);
894  const float region_min[2] = {
895  region->min[0] - marker->pos[0] * frame_width,
896  region->min[1] - marker->pos[1] * frame_height,
897  };
898  const float region_max[2] = {
899  region->max[0] - marker->pos[0] * frame_width,
900  region->max[1] - marker->pos[1] * frame_height,
901  };
902  *r_destination = tracking_track_get_mask_for_region(
903  frame_width, frame_height, region_min, region_max, track);
904  *r_width = region->max[0] - region->min[0];
905  *r_height = region->max[1] - region->min[1];
906  return *r_destination;
907 }
908 
910 {
911  if (cache_key != NULL) {
912  float *mask = (float *)cache_key;
913  MEM_freeN(mask);
914  }
915 }
916 
918  int num_clips,
920  int num_tracks)
921 {
923  "tracking image accessor");
924 
925  BLI_assert(num_clips <= MAX_ACCESSOR_CLIP);
926 
927  memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *));
928  accessor->num_clips = num_clips;
929 
930  accessor->tracks = MEM_malloc_arrayN(
931  num_tracks, sizeof(MovieTrackingTrack *), "image accessor tracks");
932  memcpy(accessor->tracks, tracks, num_tracks * sizeof(MovieTrackingTrack *));
933  accessor->num_tracks = num_tracks;
934 
940 
941  BLI_spin_init(&accessor->cache_lock);
942 
943  return accessor;
944 }
945 
947 {
949  BLI_spin_end(&accessor->cache_lock);
950  MEM_freeN(accessor->tracks);
951  MEM_freeN(accessor);
952 }
953 
typedef float(TangentPoint)[2]
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
Definition: movieclip.c:1633
void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height)
Definition: movieclip.c:1540
struct ImBuf * BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user)
Definition: movieclip.c:1349
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
struct MovieTrackingTrack * BKE_tracking_track_duplicate(struct MovieTrackingTrack *track)
Definition: tracking.c:622
struct MovieTrackingMarker * BKE_tracking_marker_insert(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker)
Definition: tracking.c:1383
struct MovieTrackingObject * BKE_tracking_object_add(struct MovieTracking *tracking, const char *name)
Definition: tracking.c:2104
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1556
void BKE_tracking_track_free(struct MovieTrackingTrack *track)
Definition: tracking.c:661
bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:796
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition: tracking.c:2183
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition: tracking.c:1523
#define BLI_assert(a)
Definition: BLI_assert.h:58
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:768
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
Definition: math_color.c:414
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t len)
Definition: string_utils.c:381
void BLI_thread_unlock(int type)
Definition: threads.cc:389
void BLI_thread_lock(int type)
Definition: threads.cc:384
int BLI_system_thread_count(void)
Definition: threads.cc:309
@ LOCK_MOVIECLIP
Definition: BLI_threads.h:72
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define ELEM(...)
#define CTX_DATA_(context, msgid)
#define BLT_I18NCONTEXT_ID_MOVIECLIP
typedef double(DMatrix)[4][4]
@ MCLIP_PROXY_RENDER_SIZE_FULL
@ TRACK_ALGORITHM_FLAG_USE_MASK
@ TRACKING_DISTORTION_MODEL_DIVISION
@ TRACKING_DISTORTION_MODEL_POLYNOMIAL
@ TRACKING_DISTORTION_MODEL_NUKE
@ TRACKING_DISTORTION_MODEL_BROWN
@ MARKER_TRACKED
@ MARKER_DISABLED
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
void IMB_float_from_rect(struct ImBuf *ibuf)
Definition: divers.c:780
bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1667
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
struct ImBuf * IMB_dupImBuf(const struct ImBuf *ibuf1)
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
void IMB_rectcpy(struct ImBuf *dbuf, const struct ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void * user_data
void libmv_FrameAccessorDestroy(libmv_FrameAccessor *frame_accessor)
void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform, const libmv_FloatImage *input_image, libmv_FloatImage *output_image)
libmv_FrameAccessor * libmv_FrameAccessorNew(libmv_FrameAccessorUserData *user_data, libmv_GetImageCallback get_image_callback, libmv_ReleaseImageCallback release_image_callback, libmv_GetMaskForTrackCallback get_mask_for_track_callback, libmv_ReleaseMaskCallback release_mask_callback)
void libmv_floatImageDestroy(libmv_FloatImage *image)
Definition: image.cc:30
@ LIBMV_DISTORTION_MODEL_POLYNOMIAL
@ LIBMV_DISTORTION_MODEL_NUKE
@ LIBMV_DISTORTION_MODEL_BROWN
@ LIBMV_DISTORTION_MODEL_DIVISION
struct libmv_FrameTransform libmv_FrameTransform
void * libmv_CacheKey
struct libmv_FrameAccessorUserData libmv_FrameAccessorUserData
@ LIBMV_IMAGE_MODE_RGBA
@ LIBMV_IMAGE_MODE_MONO
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static ulong * next
static unsigned a[3]
Definition: RandGen.cpp:92
int channels
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:47
MovieTrackingMarker * markers
struct MovieTrackingTrack * next
struct MovieTrackingTrack * prev
MovieTrackingCamera camera
struct MovieTrackingTrack ** tracks
struct MovieClip * clips[MAX_ACCESSOR_CLIP]
struct libmv_FrameAccessor * libmv_accessor
char object_name[MAX_NAME]
struct GHash * hash
MovieTrackingTrack * tracks
SpinLock spin_lock
char * customdata
float min[2]
Definition: intern/region.h:28
float max[2]
Definition: intern/region.h:29
float * tracking_track_get_mask_for_region(int frame_width, int frame_height, const float region_min[2], const float region_max[2], MovieTrackingTrack *track)
Definition: tracking.c:1285
ListBase tracks
Definition: tracking.c:75
#define MAX_ACCESSOR_CLIP
static void accessor_release_image_callback(libmv_CacheKey cache_key)
static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
static ImBuf * float_image_to_ibuf(libmv_FloatImage *float_image)
static void unified_to_pixel(int frame_width, int frame_height, const float unified_coords[2], float pixel_coords[2])
static libmv_CacheKey accessor_get_mask_for_track_callback(libmv_FrameAccessorUserData *user_data, int clip_index, int frame, int track_index, const libmv_Region *region, float **r_destination, int *r_width, int *r_height)
void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, bool before, bool overwrite)
static void search_pixel_to_marker_unified(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float search_pixel[2], float marker_unified[2])
int tracks_map_get_size(TracksMap *map)
Definition: tracking_util.c:93
static ImBuf * accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame)
static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
static libmv_CacheKey accessor_get_image_callback(struct libmv_FrameAccessorUserData *user_data, int clip_index, int frame, libmv_InputMode input_mode, int downscale, const libmv_Region *region, const libmv_FrameTransform *transform, float **destination, int *width, int *height, int *channels)
static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_pixel_coords[2])
static void marker_unified_to_search_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float marker_unified[2], float search_pixel[2])
static ImBuf * make_grayscale_ibuf_copy(ImBuf *ibuf)
void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking, int calibration_width, int calibration_height, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
void tracking_get_marker_coords_for_tracking(int frame_width, int frame_height, const MovieTrackingMarker *marker, double search_pixel_x[5], double search_pixel_y[5])
void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
Definition: tracking_util.c:98
void tracks_map_free(TracksMap *map, void(*customdata_free)(void *customdata))
static void distortion_model_parameters_from_options(const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, MovieTrackingCamera *camera)
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)
static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], float frame_unified_coords[2])
#define CACHE_PRINTF(...)
Definition: tracking_util.c:60
void tracking_trackingCameraFromIntrinscisOptions(MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
static void distortion_model_parameters_from_tracking(const MovieTrackingCamera *camera, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
TracksMap * tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size)
Definition: tracking_util.c:67
static void accessor_release_mask_callback(libmv_CacheKey cache_key)
void tracking_set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker, const double search_pixel_x[5], const double search_pixel_y[5])
static ImBuf * accessor_get_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame, libmv_InputMode input_mode, int downscale, const libmv_Region *region, const libmv_FrameTransform *transform)
void tracking_get_search_origin_frame_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, float frame_pixel[2])
void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)