tracking_util.c 31 KB

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