ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / tracking_util.c
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
20 /** \file
21  * \ingroup bke
22  *
23  * This file contains implementation of function which are used
24  * by multiple tracking files but which should not be public.
25  */
26
27 #include <stddef.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_movieclip_types.h"
32
33 #include "BLI_utildefines.h"
34 #include "BLI_math.h"
35 #include "BLI_listbase.h"
36 #include "BLI_ghash.h"
37 #include "BLI_string.h"
38 #include "BLI_string_utils.h"
39
40 #include "BLT_translation.h"
41
42 #include "BKE_movieclip.h"
43 #include "BKE_tracking.h"
44
45 #include "IMB_imbuf_types.h"
46 #include "IMB_imbuf.h"
47 #include "IMB_moviecache.h"
48
49 #include "tracking_private.h"
50
51 #include "libmv-capi.h"
52
53 /* Uncomment this to have caching-specific debug prints. */
54 // #define DEBUG_CACHE
55
56 #ifdef DEBUG_CACHE
57 #  define CACHE_PRINTF(...) printf(__VA_ARGS__)
58 #else
59 #  define CACHE_PRINTF(...)
60 #endif
61
62 /*********************** Tracks map *************************/
63
64 TracksMap *tracks_map_new(const char *object_name,
65                           bool is_camera,
66                           int num_tracks,
67                           int customdata_size)
68 {
69   TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
70
71   BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
72   map->is_camera = is_camera;
73
74   map->num_tracks = num_tracks;
75   map->customdata_size = customdata_size;
76
77   map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
78
79   if (customdata_size)
80     map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
81
82   map->hash = BLI_ghash_ptr_new("TracksMap hash");
83
84   BLI_spin_init(&map->spin_lock);
85
86   return map;
87 }
88
89 int tracks_map_get_size(TracksMap *map)
90 {
91   return map->num_tracks;
92 }
93
94 void tracks_map_get_indexed_element(TracksMap *map,
95                                     int index,
96                                     MovieTrackingTrack **track,
97                                     void **customdata)
98 {
99   *track = &map->tracks[index];
100
101   if (map->customdata)
102     *customdata = &map->customdata[index * map->customdata_size];
103 }
104
105 void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
106 {
107   MovieTrackingTrack new_track = *track;
108
109   new_track.markers = MEM_dupallocN(new_track.markers);
110
111   map->tracks[map->ptr] = new_track;
112
113   if (customdata)
114     memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
115
116   BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
117
118   map->ptr++;
119 }
120
121 void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
122 {
123   MovieTrackingTrack *track;
124   ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
125   ListBase *old_tracks;
126   int a;
127
128   if (map->is_camera) {
129     old_tracks = &tracking->tracks;
130   }
131   else {
132     MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name);
133
134     if (!object) {
135       /* object was deleted by user, create new one */
136       object = BKE_tracking_object_add(tracking, map->object_name);
137     }
138
139     old_tracks = &object->tracks;
140   }
141
142   /* duplicate currently operating tracks to temporary list.
143    * this is needed to keep names in unique state and it's faster to change names
144    * of currently operating tracks (if needed)
145    */
146   for (a = 0; a < map->num_tracks; a++) {
147     MovieTrackingTrack *old_track;
148     bool mapped_to_old = false;
149
150     track = &map->tracks[a];
151
152     /* find original of operating track in list of previously displayed tracks */
153     old_track = BLI_ghash_lookup(map->hash, track);
154     if (old_track) {
155       if (BLI_findindex(old_tracks, old_track) != -1) {
156         BLI_remlink(old_tracks, old_track);
157
158         BLI_spin_lock(&map->spin_lock);
159
160         /* Copy flags like selection back to the track map. */
161         track->flag = old_track->flag;
162         track->pat_flag = old_track->pat_flag;
163         track->search_flag = old_track->search_flag;
164
165         /* Copy all the rest settings back from the map to the actual tracks. */
166         MEM_freeN(old_track->markers);
167         *old_track = *track;
168         old_track->markers = MEM_dupallocN(old_track->markers);
169
170         BLI_spin_unlock(&map->spin_lock);
171
172         BLI_addtail(&tracks, old_track);
173
174         mapped_to_old = true;
175       }
176     }
177
178     if (mapped_to_old == false) {
179       MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track);
180
181       /* Update old-new track mapping */
182       BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL);
183
184       BLI_addtail(&tracks, new_track);
185     }
186   }
187
188   /* move all tracks, which aren't operating */
189   track = old_tracks->first;
190   while (track) {
191     MovieTrackingTrack *next = track->next;
192     BLI_addtail(&new_tracks, track);
193     track = next;
194   }
195
196   /* now move all tracks which are currently operating and keep their names unique */
197   track = tracks.first;
198   while (track) {
199     MovieTrackingTrack *next = track->next;
200
201     BLI_remlink(&tracks, track);
202
203     track->next = track->prev = NULL;
204     BLI_addtail(&new_tracks, track);
205
206     BLI_uniquename(&new_tracks,
207                    track,
208                    CTX_DATA_(BLT_I18NCONTEXT_ID_MOVIECLIP, "Track"),
209                    '.',
210                    offsetof(MovieTrackingTrack, name),
211                    sizeof(track->name));
212
213     track = next;
214   }
215
216   *old_tracks = new_tracks;
217 }
218
219 void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
220 {
221   int i = 0;
222
223   BLI_ghash_free(map->hash, NULL, NULL);
224
225   for (i = 0; i < map->num_tracks; i++) {
226     if (map->customdata && customdata_free)
227       customdata_free(&map->customdata[i * map->customdata_size]);
228
229     BKE_tracking_track_free(&map->tracks[i]);
230   }
231
232   if (map->customdata)
233     MEM_freeN(map->customdata);
234
235   MEM_freeN(map->tracks);
236
237   BLI_spin_end(&map->spin_lock);
238
239   MEM_freeN(map);
240 }
241
242 /*********************** Space transformation functions *************************/
243
244 /* Three coordinate frames: Frame, Search, and Marker
245  * Two units: Pixels, Unified
246  * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
247  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
248  * coordinates relative to the entire frame.
249  */
250 static void unified_to_pixel(int frame_width,
251                              int frame_height,
252                              const float unified_coords[2],
253                              float pixel_coords[2])
254 {
255   pixel_coords[0] = unified_coords[0] * frame_width;
256   pixel_coords[1] = unified_coords[1] * frame_height;
257 }
258
259 static void marker_to_frame_unified(const MovieTrackingMarker *marker,
260                                     const float marker_unified_coords[2],
261                                     float frame_unified_coords[2])
262 {
263   frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
264   frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
265 }
266
267 static void marker_unified_to_frame_pixel_coordinates(int frame_width,
268                                                       int frame_height,
269                                                       const MovieTrackingMarker *marker,
270                                                       const float marker_unified_coords[2],
271                                                       float frame_pixel_coords[2])
272 {
273   marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
274   unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
275 }
276
277 void tracking_get_search_origin_frame_pixel(int frame_width,
278                                             int frame_height,
279                                             const MovieTrackingMarker *marker,
280                                             float frame_pixel[2])
281 {
282   /* Get the lower left coordinate of the search window and snap to pixel coordinates */
283   marker_unified_to_frame_pixel_coordinates(
284       frame_width, frame_height, marker, marker->search_min, frame_pixel);
285   frame_pixel[0] = (int)frame_pixel[0];
286   frame_pixel[1] = (int)frame_pixel[1];
287 }
288
289 static void pixel_to_unified(int frame_width,
290                              int frame_height,
291                              const float pixel_coords[2],
292                              float unified_coords[2])
293 {
294   unified_coords[0] = pixel_coords[0] / frame_width;
295   unified_coords[1] = pixel_coords[1] / frame_height;
296 }
297
298 static void marker_unified_to_search_pixel(int frame_width,
299                                            int frame_height,
300                                            const MovieTrackingMarker *marker,
301                                            const float marker_unified[2],
302                                            float search_pixel[2])
303 {
304   float frame_pixel[2];
305   float search_origin_frame_pixel[2];
306
307   marker_unified_to_frame_pixel_coordinates(
308       frame_width, frame_height, marker, marker_unified, frame_pixel);
309   tracking_get_search_origin_frame_pixel(
310       frame_width, frame_height, marker, search_origin_frame_pixel);
311   sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
312 }
313
314 static void search_pixel_to_marker_unified(int frame_width,
315                                            int frame_height,
316                                            const MovieTrackingMarker *marker,
317                                            const float search_pixel[2],
318                                            float marker_unified[2])
319 {
320   float frame_unified[2];
321   float search_origin_frame_pixel[2];
322
323   tracking_get_search_origin_frame_pixel(
324       frame_width, frame_height, marker, search_origin_frame_pixel);
325   add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
326   pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
327
328   /* marker pos is in frame unified */
329   sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
330 }
331
332 /* Each marker has 5 coordinates associated with it that get warped with
333  * tracking: the four corners ("pattern_corners"), and the center ("pos").
334  * This function puts those 5 points into the appropriate frame for tracking
335  * (the "search" coordinate frame).
336  */
337 void tracking_get_marker_coords_for_tracking(int frame_width,
338                                              int frame_height,
339                                              const MovieTrackingMarker *marker,
340                                              double search_pixel_x[5],
341                                              double search_pixel_y[5])
342 {
343   int i;
344   float unified_coords[2];
345   float pixel_coords[2];
346
347   /* Convert the corners into search space coordinates. */
348   for (i = 0; i < 4; i++) {
349     marker_unified_to_search_pixel(
350         frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
351     search_pixel_x[i] = pixel_coords[0] - 0.5f;
352     search_pixel_y[i] = pixel_coords[1] - 0.5f;
353   }
354
355   /* Convert the center position (aka "pos"); this is the origin */
356   unified_coords[0] = 0.0f;
357   unified_coords[1] = 0.0f;
358   marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
359
360   search_pixel_x[4] = pixel_coords[0] - 0.5f;
361   search_pixel_y[4] = pixel_coords[1] - 0.5f;
362 }
363
364 /* Inverse of above. */
365 void tracking_set_marker_coords_from_tracking(int frame_width,
366                                               int frame_height,
367                                               MovieTrackingMarker *marker,
368                                               const double search_pixel_x[5],
369                                               const double search_pixel_y[5])
370 {
371   int i;
372   float marker_unified[2];
373   float search_pixel[2];
374
375   /* Convert the corners into search space coordinates. */
376   for (i = 0; i < 4; i++) {
377     search_pixel[0] = search_pixel_x[i] + 0.5;
378     search_pixel[1] = search_pixel_y[i] + 0.5;
379     search_pixel_to_marker_unified(
380         frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
381   }
382
383   /* Convert the center position (aka "pos"); this is the origin */
384   search_pixel[0] = search_pixel_x[4] + 0.5;
385   search_pixel[1] = search_pixel_y[4] + 0.5;
386   search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
387
388   /* If the tracker tracked nothing, then "marker_unified" would be zero.
389    * Otherwise, the entire patch shifted, and that delta should be applied to
390    * all the coordinates.
391    */
392   for (i = 0; i < 4; i++) {
393     marker->pattern_corners[i][0] -= marker_unified[0];
394     marker->pattern_corners[i][1] -= marker_unified[1];
395   }
396
397   marker->pos[0] += marker_unified[0];
398   marker->pos[1] += marker_unified[1];
399 }
400
401 /*********************** General purpose utility functions *************************/
402
403 /* Place a disabled marker before or after specified ref_marker.
404  *
405  * If before is truth, disabled marker is placed before reference
406  * one, and it's placed after it otherwise.
407  *
408  * If there's already a marker at the frame where disabled one
409  * is expected to be placed, nothing will happen if overwrite
410  * is false.
411  */
412 void tracking_marker_insert_disabled(MovieTrackingTrack *track,
413                                      const MovieTrackingMarker *ref_marker,
414                                      bool before,
415                                      bool overwrite)
416 {
417   MovieTrackingMarker marker_new;
418
419   marker_new = *ref_marker;
420   marker_new.flag &= ~MARKER_TRACKED;
421   marker_new.flag |= MARKER_DISABLED;
422
423   if (before)
424     marker_new.framenr--;
425   else
426     marker_new.framenr++;
427
428   if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr))
429     BKE_tracking_marker_insert(track, &marker_new);
430 }
431
432 /* Fill in Libmv C-API camera intrinsics options from tracking structure. */
433 void tracking_cameraIntrinscisOptionsFromTracking(
434     MovieTracking *tracking,
435     int calibration_width,
436     int calibration_height,
437     libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
438 {
439   MovieTrackingCamera *camera = &tracking->camera;
440   float aspy = 1.0f / tracking->camera.pixel_aspect;
441
442   camera_intrinsics_options->focal_length = camera->focal;
443
444   camera_intrinsics_options->principal_point_x = camera->principal[0];
445   camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
446
447   switch (camera->distortion_model) {
448     case TRACKING_DISTORTION_MODEL_POLYNOMIAL:
449       camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL;
450       camera_intrinsics_options->polynomial_k1 = camera->k1;
451       camera_intrinsics_options->polynomial_k2 = camera->k2;
452       camera_intrinsics_options->polynomial_k3 = camera->k3;
453       camera_intrinsics_options->polynomial_p1 = 0.0;
454       camera_intrinsics_options->polynomial_p2 = 0.0;
455       break;
456     case TRACKING_DISTORTION_MODEL_DIVISION:
457       camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_DIVISION;
458       camera_intrinsics_options->division_k1 = camera->division_k1;
459       camera_intrinsics_options->division_k2 = camera->division_k2;
460       break;
461     default:
462       BLI_assert(!"Unknown distortion model");
463       break;
464   }
465
466   camera_intrinsics_options->image_width = calibration_width;
467   camera_intrinsics_options->image_height = (int)(calibration_height * aspy);
468 }
469
470 void tracking_trackingCameraFromIntrinscisOptions(
471     MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
472 {
473   float aspy = 1.0f / tracking->camera.pixel_aspect;
474   MovieTrackingCamera *camera = &tracking->camera;
475
476   camera->focal = camera_intrinsics_options->focal_length;
477
478   camera->principal[0] = camera_intrinsics_options->principal_point_x;
479   camera->principal[1] = camera_intrinsics_options->principal_point_y / (double)aspy;
480
481   switch (camera_intrinsics_options->distortion_model) {
482     case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
483       camera->distortion_model = TRACKING_DISTORTION_MODEL_POLYNOMIAL;
484       camera->k1 = camera_intrinsics_options->polynomial_k1;
485       camera->k2 = camera_intrinsics_options->polynomial_k2;
486       camera->k3 = camera_intrinsics_options->polynomial_k3;
487       break;
488     case LIBMV_DISTORTION_MODEL_DIVISION:
489       camera->distortion_model = TRACKING_DISTORTION_MODEL_DIVISION;
490       camera->division_k1 = camera_intrinsics_options->division_k1;
491       camera->division_k2 = camera_intrinsics_options->division_k2;
492       break;
493     default:
494       BLI_assert(!"Unknown distortion model");
495       break;
496   }
497 }
498
499 /* Get previous keyframed marker. */
500 MovieTrackingMarker *tracking_get_keyframed_marker(MovieTrackingTrack *track,
501                                                    int current_frame,
502                                                    bool backwards)
503 {
504   MovieTrackingMarker *marker_keyed = NULL;
505   MovieTrackingMarker *marker_keyed_fallback = NULL;
506   int a = BKE_tracking_marker_get(track, current_frame) - track->markers;
507
508   while (a >= 0 && a < track->markersnr) {
509     int next = backwards ? a + 1 : a - 1;
510     bool is_keyframed = false;
511     MovieTrackingMarker *cur_marker = &track->markers[a];
512     MovieTrackingMarker *next_marker = NULL;
513
514     if (next >= 0 && next < track->markersnr)
515       next_marker = &track->markers[next];
516
517     if ((cur_marker->flag & MARKER_DISABLED) == 0) {
518       /* If it'll happen so we didn't find a real keyframe marker,
519        * fallback to the first marker in current tracked segment
520        * as a keyframe.
521        */
522       if (next_marker == NULL) {
523         /* Could happen when trying to get reference marker for the fist
524          * one on the segment which isn't surrounded by disabled markers.
525          *
526          * There's no really good choice here, just use the reference
527          * marker which looks correct..
528          */
529         if (marker_keyed_fallback == NULL) {
530           marker_keyed_fallback = cur_marker;
531         }
532       }
533       else if (next_marker->flag & MARKER_DISABLED) {
534         if (marker_keyed_fallback == NULL)
535           marker_keyed_fallback = cur_marker;
536       }
537
538       is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
539     }
540
541     if (is_keyframed) {
542       marker_keyed = cur_marker;
543
544       break;
545     }
546
547     a = next;
548   }
549
550   if (marker_keyed == NULL)
551     marker_keyed = marker_keyed_fallback;
552
553   return marker_keyed;
554 }
555
556 /*********************** Frame accessr *************************/
557
558 typedef struct AccessCacheKey {
559   int clip_index;
560   int frame;
561   int downscale;
562   libmv_InputMode input_mode;
563   bool has_region;
564   float region_min[2], region_max[2];
565   int64_t transform_key;
566 } AccessCacheKey;
567
568 static unsigned int accesscache_hashhash(const void *key_v)
569 {
570   const AccessCacheKey *key = (const AccessCacheKey *)key_v;
571   /* TODP(sergey): Need better hashing here for faster frame access. */
572   return key->clip_index << 16 | key->frame;
573 }
574
575 static bool accesscache_hashcmp(const void *a_v, const void *b_v)
576 {
577   const AccessCacheKey *a = (const AccessCacheKey *)a_v;
578   const AccessCacheKey *b = (const AccessCacheKey *)b_v;
579   if (a->clip_index != b->clip_index || a->frame != b->frame || a->downscale != b->downscale ||
580       a->input_mode != b->input_mode || a->has_region != b->has_region ||
581       a->transform_key != b->transform_key) {
582     return true;
583   }
584   /* If there is region applied, compare it. */
585   if (a->has_region) {
586     if (!equals_v2v2(a->region_min, b->region_min) || !equals_v2v2(a->region_max, b->region_max)) {
587       return true;
588     }
589   }
590   return false;
591 }
592
593 static void accesscache_construct_key(AccessCacheKey *key,
594                                       int clip_index,
595                                       int frame,
596                                       libmv_InputMode input_mode,
597                                       int downscale,
598                                       const libmv_Region *region,
599                                       int64_t transform_key)
600 {
601   key->clip_index = clip_index;
602   key->frame = frame;
603   key->input_mode = input_mode;
604   key->downscale = downscale;
605   key->has_region = (region != NULL);
606   if (key->has_region) {
607     copy_v2_v2(key->region_min, region->min);
608     copy_v2_v2(key->region_max, region->max);
609   }
610   key->transform_key = transform_key;
611 }
612
613 static void accesscache_put(TrackingImageAccessor *accessor,
614                             int clip_index,
615                             int frame,
616                             libmv_InputMode input_mode,
617                             int downscale,
618                             const libmv_Region *region,
619                             int64_t transform_key,
620                             ImBuf *ibuf)
621 {
622   AccessCacheKey key;
623   accesscache_construct_key(&key, clip_index, frame, input_mode, downscale, region, transform_key);
624   IMB_moviecache_put(accessor->cache, &key, ibuf);
625 }
626
627 static ImBuf *accesscache_get(TrackingImageAccessor *accessor,
628                               int clip_index,
629                               int frame,
630                               libmv_InputMode input_mode,
631                               int downscale,
632                               const libmv_Region *region,
633                               int64_t transform_key)
634 {
635   AccessCacheKey key;
636   accesscache_construct_key(&key, clip_index, frame, input_mode, downscale, region, transform_key);
637   return IMB_moviecache_get(accessor->cache, &key);
638 }
639
640 static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor,
641                                              int clip_index,
642                                              int frame)
643 {
644   MovieClip *clip;
645   MovieClipUser user;
646   ImBuf *ibuf;
647   int scene_frame;
648
649   BLI_assert(clip_index < accessor->num_clips);
650
651   clip = accessor->clips[clip_index];
652   scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
653   BKE_movieclip_user_set_frame(&user, scene_frame);
654   user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
655   user.render_flag = 0;
656   ibuf = BKE_movieclip_get_ibuf(clip, &user);
657
658   return ibuf;
659 }
660
661 static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf)
662 {
663   ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0);
664   size_t size;
665   int i;
666
667   BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
668
669   /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels
670    * float buffer, so we do it manually here.
671    *
672    * Will generalize it later.
673    */
674   size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
675   grayscale->channels = 1;
676   if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) {
677     grayscale->mall |= IB_rectfloat;
678     grayscale->flags |= IB_rectfloat;
679
680     for (i = 0; i < grayscale->x * grayscale->y; ++i) {
681       const float *pixel = ibuf->rect_float + ibuf->channels * i;
682
683       grayscale->rect_float[i] = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
684     }
685   }
686
687   return grayscale;
688 }
689
690 static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image)
691 {
692   BLI_assert(ibuf->rect_float != NULL);
693   float_image->buffer = ibuf->rect_float;
694   float_image->width = ibuf->x;
695   float_image->height = ibuf->y;
696   float_image->channels = ibuf->channels;
697 }
698
699 static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image)
700 {
701   ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0);
702   size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float);
703   ibuf->channels = float_image->channels;
704   if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) {
705     ibuf->mall |= IB_rectfloat;
706     ibuf->flags |= IB_rectfloat;
707
708     memcpy(ibuf->rect_float, float_image->buffer, size);
709   }
710   return ibuf;
711 }
712
713 static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
714                                 int clip_index,
715                                 int frame,
716                                 libmv_InputMode input_mode,
717                                 int downscale,
718                                 const libmv_Region *region,
719                                 const libmv_FrameTransform *transform)
720 {
721   ImBuf *ibuf, *orig_ibuf, *final_ibuf;
722   int64_t transform_key = 0;
723   if (transform != NULL) {
724     transform_key = libmv_frameAccessorgetTransformKey(transform);
725   }
726   /* First try to get fully processed image from the cache. */
727   BLI_spin_lock(&accessor->cache_lock);
728   ibuf = accesscache_get(
729       accessor, clip_index, frame, input_mode, downscale, region, transform_key);
730   BLI_spin_unlock(&accessor->cache_lock);
731   if (ibuf != NULL) {
732     CACHE_PRINTF("Used cached buffer for frame %d\n", frame);
733     /* This is a little heuristic here: if we re-used image once, this is
734      * a high probability of the image to be related to a keyframe matched
735      * reference image. Those images we don't want to be thrown away because
736      * if we toss them out we'll be re-calculating them at the next
737      * iteration.
738      */
739     ibuf->userflags |= IB_PERSISTENT;
740     return ibuf;
741   }
742   CACHE_PRINTF("Calculate new buffer for frame %d\n", frame);
743   /* And now we do postprocessing of the original frame. */
744   orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame);
745   if (orig_ibuf == NULL) {
746     return NULL;
747   }
748   /* Cut a region if requested. */
749   if (region != NULL) {
750     int width = region->max[0] - region->min[0], height = region->max[1] - region->min[1];
751
752     /* If the requested region goes outside of the actual frame we still
753      * return the requested region size, but only fill it's partially with
754      * the data we can.
755      */
756     int clamped_origin_x = max_ii((int)region->min[0], 0),
757         clamped_origin_y = max_ii((int)region->min[1], 0);
758     int dst_offset_x = clamped_origin_x - (int)region->min[0],
759         dst_offset_y = clamped_origin_y - (int)region->min[1];
760     int clamped_width = width - dst_offset_x, clamped_height = height - dst_offset_y;
761     clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x);
762     clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y);
763
764     final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat);
765
766     if (orig_ibuf->rect_float != NULL) {
767       IMB_rectcpy(final_ibuf,
768                   orig_ibuf,
769                   dst_offset_x,
770                   dst_offset_y,
771                   clamped_origin_x,
772                   clamped_origin_y,
773                   clamped_width,
774                   clamped_height);
775     }
776     else {
777       int y;
778       /* TODO(sergey): We don't do any color space or alpha conversion
779        * here. Probably Libmv is better to work in the linear space,
780        * but keep sRGB space here for compatibility for now.
781        */
782       for (y = 0; y < clamped_height; ++y) {
783         int x;
784         for (x = 0; x < clamped_width; ++x) {
785           int src_x = x + clamped_origin_x, src_y = y + clamped_origin_y;
786           int dst_x = x + dst_offset_x, dst_y = y + dst_offset_y;
787           int dst_index = (dst_y * width + dst_x) * 4,
788               src_index = (src_y * orig_ibuf->x + src_x) * 4;
789           rgba_uchar_to_float(final_ibuf->rect_float + dst_index,
790                               (unsigned char *)orig_ibuf->rect + src_index);
791         }
792       }
793     }
794   }
795   else {
796     /* Libmv only works with float images,
797      *
798      * This would likely make it so loads of float buffers are being stored
799      * in the cache which is nice on the one hand (faster re-use of the
800      * frames) but on the other hand it bumps the memory usage up.
801      */
802     BLI_thread_lock(LOCK_MOVIECLIP);
803     IMB_float_from_rect(orig_ibuf);
804     BLI_thread_unlock(LOCK_MOVIECLIP);
805     final_ibuf = orig_ibuf;
806   }
807   /* Downscale if needed. */
808   if (downscale > 0) {
809     if (final_ibuf == orig_ibuf) {
810       final_ibuf = IMB_dupImBuf(orig_ibuf);
811     }
812     IMB_scaleImBuf(final_ibuf, orig_ibuf->x / (1 << downscale), orig_ibuf->y / (1 << downscale));
813   }
814   /* Apply possible transformation. */
815   if (transform != NULL) {
816     libmv_FloatImage input_image, output_image;
817     ibuf_to_float_image(final_ibuf, &input_image);
818     libmv_frameAccessorgetTransformRun(transform, &input_image, &output_image);
819     if (final_ibuf != orig_ibuf) {
820       IMB_freeImBuf(final_ibuf);
821     }
822     final_ibuf = float_image_to_ibuf(&output_image);
823     libmv_floatImageDestroy(&output_image);
824   }
825   /* Transform number of channels. */
826   if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
827     BLI_assert(orig_ibuf->channels == 3 || orig_ibuf->channels == 4);
828     /* pass */
829   }
830   else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
831     BLI_assert(input_mode == LIBMV_IMAGE_MODE_MONO);
832     if (final_ibuf->channels != 1) {
833       ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
834       if (final_ibuf != orig_ibuf) {
835         /* We dereference original frame later. */
836         IMB_freeImBuf(final_ibuf);
837       }
838       final_ibuf = grayscale_ibuf;
839     }
840   }
841   /* It's possible processing still didn't happen at this point,
842    * but we really need a copy of the buffer to be transformed
843    * and to be put to the cache.
844    */
845   if (final_ibuf == orig_ibuf) {
846     final_ibuf = IMB_dupImBuf(orig_ibuf);
847   }
848   IMB_freeImBuf(orig_ibuf);
849   BLI_spin_lock(&accessor->cache_lock);
850   /* Put final buffer to cache. */
851   accesscache_put(
852       accessor, clip_index, frame, input_mode, downscale, region, transform_key, final_ibuf);
853   BLI_spin_unlock(&accessor->cache_lock);
854   return final_ibuf;
855 }
856
857 static libmv_CacheKey accessor_get_image_callback(struct libmv_FrameAccessorUserData *user_data,
858                                                   int clip_index,
859                                                   int frame,
860                                                   libmv_InputMode input_mode,
861                                                   int downscale,
862                                                   const libmv_Region *region,
863                                                   const libmv_FrameTransform *transform,
864                                                   float **destination,
865                                                   int *width,
866                                                   int *height,
867                                                   int *channels)
868 {
869   TrackingImageAccessor *accessor = (TrackingImageAccessor *)user_data;
870   ImBuf *ibuf;
871
872   BLI_assert(clip_index >= 0 && clip_index < accessor->num_clips);
873
874   ibuf = accessor_get_ibuf(accessor, clip_index, frame, input_mode, downscale, region, transform);
875
876   if (ibuf) {
877     *destination = ibuf->rect_float;
878     *width = ibuf->x;
879     *height = ibuf->y;
880     *channels = ibuf->channels;
881   }
882   else {
883     *destination = NULL;
884     *width = 0;
885     *height = 0;
886     *channels = 0;
887   }
888
889   return ibuf;
890 }
891
892 static void accessor_release_image_callback(libmv_CacheKey cache_key)
893 {
894   ImBuf *ibuf = (ImBuf *)cache_key;
895   IMB_freeImBuf(ibuf);
896 }
897
898 static libmv_CacheKey accessor_get_mask_for_track_callback(libmv_FrameAccessorUserData *user_data,
899                                                            int clip_index,
900                                                            int frame,
901                                                            int track_index,
902                                                            const libmv_Region *region,
903                                                            float **r_destination,
904                                                            int *r_width,
905                                                            int *r_height)
906 {
907   /* Perform sanity checks first. */
908   TrackingImageAccessor *accessor = (TrackingImageAccessor *)user_data;
909   BLI_assert(clip_index < accessor->num_clips);
910   BLI_assert(track_index < accessor->num_tracks);
911   MovieTrackingTrack *track = accessor->tracks[track_index];
912   /* Early output, track does not use mask. */
913   if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) {
914     return NULL;
915   }
916   MovieClip *clip = accessor->clips[clip_index];
917   /* Construct fake user so we can access movie clip. */
918   MovieClipUser user;
919   int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
920   BKE_movieclip_user_set_frame(&user, scene_frame);
921   user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
922   user.render_flag = 0;
923   /* Get frame width and height so we can convert stroke coordinates
924    * and other things from normalized to pixel space.
925    */
926   int frame_width, frame_height;
927   BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
928   /* Actual mask sampling. */
929   MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame);
930   const float region_min[2] = {region->min[0] - marker->pos[0] * frame_width,
931                                region->min[1] - marker->pos[1] * frame_height};
932   const float region_max[2] = {region->max[0] - marker->pos[0] * frame_width,
933                                region->max[1] - marker->pos[1] * frame_height};
934   *r_destination = tracking_track_get_mask_for_region(
935       frame_width, frame_height, region_min, region_max, track);
936   *r_width = region->max[0] - region->min[0];
937   *r_height = region->max[1] - region->min[1];
938   return *r_destination;
939 }
940
941 static void accessor_release_mask_callback(libmv_CacheKey cache_key)
942 {
943   if (cache_key != NULL) {
944     float *mask = (float *)cache_key;
945     MEM_freeN(mask);
946   }
947 }
948
949 TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
950                                                    int num_clips,
951                                                    MovieTrackingTrack **tracks,
952                                                    int num_tracks,
953                                                    int start_frame)
954 {
955   TrackingImageAccessor *accessor = MEM_callocN(sizeof(TrackingImageAccessor),
956                                                 "tracking image accessor");
957
958   BLI_assert(num_clips <= MAX_ACCESSOR_CLIP);
959
960   accessor->cache = IMB_moviecache_create(
961       "frame access cache", sizeof(AccessCacheKey), accesscache_hashhash, accesscache_hashcmp);
962
963   memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *));
964   accessor->num_clips = num_clips;
965   accessor->tracks = tracks;
966   accessor->num_tracks = num_tracks;
967   accessor->start_frame = start_frame;
968
969   accessor->libmv_accessor = libmv_FrameAccessorNew((libmv_FrameAccessorUserData *)accessor,
970                                                     accessor_get_image_callback,
971                                                     accessor_release_image_callback,
972                                                     accessor_get_mask_for_track_callback,
973                                                     accessor_release_mask_callback);
974
975   BLI_spin_init(&accessor->cache_lock);
976
977   return accessor;
978 }
979
980 void tracking_image_accessor_destroy(TrackingImageAccessor *accessor)
981 {
982   IMB_moviecache_free(accessor->cache);
983   libmv_FrameAccessorDestroy(accessor->libmv_accessor);
984   BLI_spin_end(&accessor->cache_lock);
985   MEM_freeN(accessor);
986 }