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 
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #ifndef WIN32
29 #  include <unistd.h>
30 #else
31 #  include <io.h>
32 #endif
33 
34 #include <time.h>
35 
36 #include "MEM_guardedalloc.h"
37 
38 /* Allow using deprecated functionality for .blend file I/O. */
39 #define DNA_DEPRECATED_ALLOW
40 
41 #include "DNA_defaults.h"
42 
43 #include "DNA_constraint_types.h"
44 #include "DNA_gpencil_types.h"
45 #include "DNA_movieclip_types.h"
46 #include "DNA_node_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_view3d_types.h"
52 
53 #include "BLI_utildefines.h"
54 
55 #include "BLI_blenlib.h"
56 #include "BLI_ghash.h"
57 #include "BLI_math.h"
58 #include "BLI_threads.h"
59 
60 #include "BLT_translation.h"
61 
62 #include "BKE_anim_data.h"
63 #include "BKE_colortools.h"
64 #include "BKE_global.h"
65 #include "BKE_idtype.h"
66 #include "BKE_image.h" /* openanim */
67 #include "BKE_lib_id.h"
68 #include "BKE_lib_query.h"
69 #include "BKE_main.h"
70 #include "BKE_movieclip.h"
71 #include "BKE_node.h"
72 #include "BKE_tracking.h"
73 
74 #include "IMB_imbuf.h"
75 #include "IMB_imbuf_types.h"
76 #include "IMB_moviecache.h"
77 
78 #include "DEG_depsgraph.h"
79 #include "DEG_depsgraph_query.h"
80 
81 #include "GPU_texture.h"
82 
83 #include "BLO_read_write.h"
84 
85 #ifdef WITH_OPENEXR
86 #  include "intern/openexr/openexr_multi.h"
87 #endif
88 
89 static void free_buffers(MovieClip *clip);
90 
movie_clip_init_data(ID * id)91 static void movie_clip_init_data(ID *id)
92 {
93   MovieClip *movie_clip = (MovieClip *)id;
94   BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(movie_clip, id));
95 
96   MEMCPY_STRUCT_AFTER(movie_clip, DNA_struct_default_get(MovieClip), id);
97 
98   BKE_tracking_settings_init(&movie_clip->tracking);
99   BKE_color_managed_colorspace_settings_init(&movie_clip->colorspace_settings);
100 }
101 
movie_clip_copy_data(Main * UNUSED (bmain),ID * id_dst,const ID * id_src,const int flag)102 static void movie_clip_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
103 {
104   MovieClip *movie_clip_dst = (MovieClip *)id_dst;
105   const MovieClip *movie_clip_src = (const MovieClip *)id_src;
106 
107   /* We never handle usercount here for own data. */
108   const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
109 
110   movie_clip_dst->anim = NULL;
111   movie_clip_dst->cache = NULL;
112 
113   BKE_tracking_copy(&movie_clip_dst->tracking, &movie_clip_src->tracking, flag_subdata);
114   movie_clip_dst->tracking_context = NULL;
115 
116   BKE_color_managed_colorspace_settings_copy(&movie_clip_dst->colorspace_settings,
117                                              &movie_clip_src->colorspace_settings);
118 }
119 
movie_clip_free_data(ID * id)120 static void movie_clip_free_data(ID *id)
121 {
122   MovieClip *movie_clip = (MovieClip *)id;
123 
124   /* Also frees animdata. */
125   free_buffers(movie_clip);
126 
127   BKE_tracking_free(&movie_clip->tracking);
128 }
129 
movie_clip_foreach_id(ID * id,LibraryForeachIDData * data)130 static void movie_clip_foreach_id(ID *id, LibraryForeachIDData *data)
131 {
132   MovieClip *movie_clip = (MovieClip *)id;
133   MovieTracking *tracking = &movie_clip->tracking;
134 
135   BKE_LIB_FOREACHID_PROCESS(data, movie_clip->gpd, IDWALK_CB_USER);
136 
137   LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking->tracks) {
138     BKE_LIB_FOREACHID_PROCESS(data, track->gpd, IDWALK_CB_USER);
139   }
140   LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
141     LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) {
142       BKE_LIB_FOREACHID_PROCESS(data, track->gpd, IDWALK_CB_USER);
143     }
144   }
145 
146   LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking->plane_tracks) {
147     BKE_LIB_FOREACHID_PROCESS(data, plane_track->image, IDWALK_CB_USER);
148   }
149 }
150 
movie_clip_foreach_cache(ID * id,IDTypeForeachCacheFunctionCallback function_callback,void * user_data)151 static void movie_clip_foreach_cache(ID *id,
152                                      IDTypeForeachCacheFunctionCallback function_callback,
153                                      void *user_data)
154 {
155   MovieClip *movie_clip = (MovieClip *)id;
156   IDCacheKey key = {
157       .id_session_uuid = id->session_uuid,
158       .offset_in_ID = offsetof(MovieClip, cache),
159       .cache_v = movie_clip->cache,
160   };
161   function_callback(id, &key, (void **)&movie_clip->cache, 0, user_data);
162 
163   key.offset_in_ID = offsetof(MovieClip, tracking.camera.intrinsics);
164   key.cache_v = movie_clip->tracking.camera.intrinsics;
165   function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data);
166 }
167 
write_movieTracks(BlendWriter * writer,ListBase * tracks)168 static void write_movieTracks(BlendWriter *writer, ListBase *tracks)
169 {
170   MovieTrackingTrack *track;
171 
172   track = tracks->first;
173   while (track) {
174     BLO_write_struct(writer, MovieTrackingTrack, track);
175 
176     if (track->markers) {
177       BLO_write_struct_array(writer, MovieTrackingMarker, track->markersnr, track->markers);
178     }
179 
180     track = track->next;
181   }
182 }
183 
write_moviePlaneTracks(BlendWriter * writer,ListBase * plane_tracks_base)184 static void write_moviePlaneTracks(BlendWriter *writer, ListBase *plane_tracks_base)
185 {
186   MovieTrackingPlaneTrack *plane_track;
187 
188   for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
189     BLO_write_struct(writer, MovieTrackingPlaneTrack, plane_track);
190 
191     BLO_write_pointer_array(writer, plane_track->point_tracksnr, plane_track->point_tracks);
192     BLO_write_struct_array(
193         writer, MovieTrackingPlaneMarker, plane_track->markersnr, plane_track->markers);
194   }
195 }
196 
write_movieReconstruction(BlendWriter * writer,MovieTrackingReconstruction * reconstruction)197 static void write_movieReconstruction(BlendWriter *writer,
198                                       MovieTrackingReconstruction *reconstruction)
199 {
200   if (reconstruction->camnr) {
201     BLO_write_struct_array(
202         writer, MovieReconstructedCamera, reconstruction->camnr, reconstruction->cameras);
203   }
204 }
205 
movieclip_blend_write(BlendWriter * writer,ID * id,const void * id_address)206 static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
207 {
208   MovieClip *clip = (MovieClip *)id;
209   if (clip->id.us > 0 || BLO_write_is_undo(writer)) {
210     /* Clean up, important in undo case to reduce false detection of changed datablocks. */
211     clip->anim = NULL;
212     clip->tracking_context = NULL;
213     clip->tracking.stats = NULL;
214 
215     MovieTracking *tracking = &clip->tracking;
216     MovieTrackingObject *object;
217 
218     BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
219     BKE_id_blend_write(writer, &clip->id);
220 
221     if (clip->adt) {
222       BKE_animdata_blend_write(writer, clip->adt);
223     }
224 
225     write_movieTracks(writer, &tracking->tracks);
226     write_moviePlaneTracks(writer, &tracking->plane_tracks);
227     write_movieReconstruction(writer, &tracking->reconstruction);
228 
229     object = tracking->objects.first;
230     while (object) {
231       BLO_write_struct(writer, MovieTrackingObject, object);
232 
233       write_movieTracks(writer, &object->tracks);
234       write_moviePlaneTracks(writer, &object->plane_tracks);
235       write_movieReconstruction(writer, &object->reconstruction);
236 
237       object = object->next;
238     }
239   }
240 }
241 
direct_link_movieReconstruction(BlendDataReader * reader,MovieTrackingReconstruction * reconstruction)242 static void direct_link_movieReconstruction(BlendDataReader *reader,
243                                             MovieTrackingReconstruction *reconstruction)
244 {
245   BLO_read_data_address(reader, &reconstruction->cameras);
246 }
247 
direct_link_movieTracks(BlendDataReader * reader,ListBase * tracksbase)248 static void direct_link_movieTracks(BlendDataReader *reader, ListBase *tracksbase)
249 {
250   BLO_read_list(reader, tracksbase);
251 
252   LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
253     BLO_read_data_address(reader, &track->markers);
254   }
255 }
256 
direct_link_moviePlaneTracks(BlendDataReader * reader,ListBase * plane_tracks_base)257 static void direct_link_moviePlaneTracks(BlendDataReader *reader, ListBase *plane_tracks_base)
258 {
259   BLO_read_list(reader, plane_tracks_base);
260 
261   LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
262     BLO_read_pointer_array(reader, (void **)&plane_track->point_tracks);
263     for (int i = 0; i < plane_track->point_tracksnr; i++) {
264       BLO_read_data_address(reader, &plane_track->point_tracks[i]);
265     }
266 
267     BLO_read_data_address(reader, &plane_track->markers);
268   }
269 }
270 
movieclip_blend_read_data(BlendDataReader * reader,ID * id)271 static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
272 {
273   MovieClip *clip = (MovieClip *)id;
274   MovieTracking *tracking = &clip->tracking;
275 
276   BLO_read_data_address(reader, &clip->adt);
277   BKE_animdata_blend_read_data(reader, clip->adt);
278 
279   direct_link_movieTracks(reader, &tracking->tracks);
280   direct_link_moviePlaneTracks(reader, &tracking->plane_tracks);
281   direct_link_movieReconstruction(reader, &tracking->reconstruction);
282 
283   BLO_read_data_address(reader, &clip->tracking.act_track);
284   BLO_read_data_address(reader, &clip->tracking.act_plane_track);
285 
286   clip->anim = NULL;
287   clip->tracking_context = NULL;
288   clip->tracking.stats = NULL;
289 
290   /* TODO we could store those in undo cache storage as well, and preserve them instead of
291    * re-creating them... */
292   BLI_listbase_clear(&clip->runtime.gputextures);
293 
294   /* Needed for proper versioning, will be NULL for all newer files anyway. */
295   BLO_read_data_address(reader, &clip->tracking.stabilization.rot_track);
296 
297   clip->tracking.dopesheet.ok = 0;
298   BLI_listbase_clear(&clip->tracking.dopesheet.channels);
299   BLI_listbase_clear(&clip->tracking.dopesheet.coverage_segments);
300 
301   BLO_read_list(reader, &tracking->objects);
302 
303   LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
304     direct_link_movieTracks(reader, &object->tracks);
305     direct_link_moviePlaneTracks(reader, &object->plane_tracks);
306     direct_link_movieReconstruction(reader, &object->reconstruction);
307   }
308 }
309 
lib_link_movieTracks(BlendLibReader * reader,MovieClip * clip,ListBase * tracksbase)310 static void lib_link_movieTracks(BlendLibReader *reader, MovieClip *clip, ListBase *tracksbase)
311 {
312   LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
313     BLO_read_id_address(reader, clip->id.lib, &track->gpd);
314   }
315 }
316 
lib_link_moviePlaneTracks(BlendLibReader * reader,MovieClip * clip,ListBase * tracksbase)317 static void lib_link_moviePlaneTracks(BlendLibReader *reader,
318                                       MovieClip *clip,
319                                       ListBase *tracksbase)
320 {
321   LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, tracksbase) {
322     BLO_read_id_address(reader, clip->id.lib, &plane_track->image);
323   }
324 }
325 
movieclip_blend_read_lib(BlendLibReader * reader,ID * id)326 static void movieclip_blend_read_lib(BlendLibReader *reader, ID *id)
327 {
328   MovieClip *clip = (MovieClip *)id;
329   MovieTracking *tracking = &clip->tracking;
330 
331   BLO_read_id_address(reader, clip->id.lib, &clip->gpd);
332 
333   lib_link_movieTracks(reader, clip, &tracking->tracks);
334   lib_link_moviePlaneTracks(reader, clip, &tracking->plane_tracks);
335 
336   LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
337     lib_link_movieTracks(reader, clip, &object->tracks);
338     lib_link_moviePlaneTracks(reader, clip, &object->plane_tracks);
339   }
340 }
341 
342 IDTypeInfo IDType_ID_MC = {
343     .id_code = ID_MC,
344     .id_filter = FILTER_ID_MC,
345     .main_listbase_index = INDEX_ID_MC,
346     .struct_size = sizeof(MovieClip),
347     .name = "MovieClip",
348     .name_plural = "movieclips",
349     .translation_context = BLT_I18NCONTEXT_ID_MOVIECLIP,
350     .flags = 0,
351 
352     .init_data = movie_clip_init_data,
353     .copy_data = movie_clip_copy_data,
354     .free_data = movie_clip_free_data,
355     .make_local = NULL,
356     .foreach_id = movie_clip_foreach_id,
357     .foreach_cache = movie_clip_foreach_cache,
358 
359     .blend_write = movieclip_blend_write,
360     .blend_read_data = movieclip_blend_read_data,
361     .blend_read_lib = movieclip_blend_read_lib,
362     .blend_read_expand = NULL,
363 };
364 
365 /*********************** movieclip buffer loaders *************************/
366 
sequence_guess_offset(const char * full_name,int head_len,unsigned short numlen)367 static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
368 {
369   char num[FILE_MAX] = {0};
370 
371   BLI_strncpy(num, full_name + head_len, numlen + 1);
372 
373   return atoi(num);
374 }
375 
rendersize_to_proxy(const MovieClipUser * user,int flag)376 static int rendersize_to_proxy(const MovieClipUser *user, int flag)
377 {
378   if ((flag & MCLIP_USE_PROXY) == 0) {
379     return IMB_PROXY_NONE;
380   }
381 
382   switch (user->render_size) {
383     case MCLIP_PROXY_RENDER_SIZE_25:
384       return IMB_PROXY_25;
385 
386     case MCLIP_PROXY_RENDER_SIZE_50:
387       return IMB_PROXY_50;
388 
389     case MCLIP_PROXY_RENDER_SIZE_75:
390       return IMB_PROXY_75;
391 
392     case MCLIP_PROXY_RENDER_SIZE_100:
393       return IMB_PROXY_100;
394 
395     case MCLIP_PROXY_RENDER_SIZE_FULL:
396       return IMB_PROXY_NONE;
397   }
398 
399   return IMB_PROXY_NONE;
400 }
401 
rendersize_to_number(int render_size)402 static int rendersize_to_number(int render_size)
403 {
404   switch (render_size) {
405     case MCLIP_PROXY_RENDER_SIZE_25:
406       return 25;
407 
408     case MCLIP_PROXY_RENDER_SIZE_50:
409       return 50;
410 
411     case MCLIP_PROXY_RENDER_SIZE_75:
412       return 75;
413 
414     case MCLIP_PROXY_RENDER_SIZE_100:
415       return 100;
416 
417     case MCLIP_PROXY_RENDER_SIZE_FULL:
418       return 100;
419   }
420 
421   return 100;
422 }
423 
get_timecode(MovieClip * clip,int flag)424 static int get_timecode(MovieClip *clip, int flag)
425 {
426   if ((flag & MCLIP_USE_PROXY) == 0) {
427     return IMB_TC_NONE;
428   }
429 
430   return clip->proxy.tc;
431 }
432 
get_sequence_fname(const MovieClip * clip,const int framenr,char * name)433 static void get_sequence_fname(const MovieClip *clip, const int framenr, char *name)
434 {
435   unsigned short numlen;
436   char head[FILE_MAX], tail[FILE_MAX];
437   int offset;
438 
439   BLI_strncpy(name, clip->filepath, sizeof(clip->filepath));
440   BLI_path_sequence_decode(name, head, tail, &numlen);
441 
442   /* Movie-clips always points to first image from sequence, auto-guess offset for now.
443    * Could be something smarter in the future. */
444   offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
445 
446   if (numlen) {
447     BLI_path_sequence_encode(
448         name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
449   }
450   else {
451     BLI_strncpy(name, clip->filepath, sizeof(clip->filepath));
452   }
453 
454   BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
455 }
456 
457 /* supposed to work with sequences only */
get_proxy_fname(const MovieClip * clip,int proxy_render_size,bool undistorted,int framenr,char * name)458 static void get_proxy_fname(
459     const MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *name)
460 {
461   int size = rendersize_to_number(proxy_render_size);
462   char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
463   int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset;
464 
465   BLI_split_dirfile(clip->filepath, clipdir, clipfile, FILE_MAX, FILE_MAX);
466 
467   if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
468     BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
469   }
470   else {
471     BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
472   }
473 
474   if (undistorted) {
475     BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
476   }
477   else {
478     BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
479   }
480 
481   BLI_path_abs(name, BKE_main_blendfile_path_from_global());
482   BLI_path_frame(name, 1, 0);
483 
484   strcat(name, ".jpg");
485 }
486 
487 #ifdef WITH_OPENEXR
488 
489 typedef struct MultilayerConvertContext {
490   float *combined_pass;
491   int num_combined_channels;
492 } MultilayerConvertContext;
493 
movieclip_convert_multilayer_add_view(void * UNUSED (ctx_v),const char * UNUSED (view_name))494 static void *movieclip_convert_multilayer_add_view(void *UNUSED(ctx_v),
495                                                    const char *UNUSED(view_name))
496 {
497   return NULL;
498 }
499 
movieclip_convert_multilayer_add_layer(void * ctx_v,const char * UNUSED (layer_name))500 static void *movieclip_convert_multilayer_add_layer(void *ctx_v, const char *UNUSED(layer_name))
501 {
502   /* Return dummy non-NULL value, we don't use layer handle but need to return
503    * something, so render API invokes the add_pass() callbacks. */
504   return ctx_v;
505 }
506 
movieclip_convert_multilayer_add_pass(void * UNUSED (layer),void * ctx_v,const char * pass_name,float * rect,int num_channels,const char * chan_id,const char * UNUSED (view_name))507 static void movieclip_convert_multilayer_add_pass(void *UNUSED(layer),
508                                                   void *ctx_v,
509                                                   const char *pass_name,
510                                                   float *rect,
511                                                   int num_channels,
512                                                   const char *chan_id,
513                                                   const char *UNUSED(view_name))
514 {
515   /* NOTE: This function must free pass pixels data if it is not used, this
516    * is how IMB_exr_multilayer_convert() is working. */
517   MultilayerConvertContext *ctx = ctx_v;
518   /* If we've found a first combined pass, skip all the rest ones. */
519   if (ctx->combined_pass != NULL) {
520     MEM_freeN(rect);
521     return;
522   }
523   if (STREQ(pass_name, RE_PASSNAME_COMBINED) || STREQ(chan_id, "RGBA") || STREQ(chan_id, "RGB")) {
524     ctx->combined_pass = rect;
525     ctx->num_combined_channels = num_channels;
526   }
527   else {
528     MEM_freeN(rect);
529   }
530 }
531 
532 #endif /* WITH_OPENEXR */
533 
534 /* Will try to make image buffer usable when originating from the multi-layer
535  * source.
536  * Internally finds a first combined pass and uses that as a buffer. Not ideal,
537  * but is better than a complete empty buffer. */
BKE_movieclip_convert_multilayer_ibuf(struct ImBuf * ibuf)538 void BKE_movieclip_convert_multilayer_ibuf(struct ImBuf *ibuf)
539 {
540   if (ibuf == NULL) {
541     return;
542   }
543 #ifdef WITH_OPENEXR
544   if (ibuf->ftype != IMB_FTYPE_OPENEXR || ibuf->userdata == NULL) {
545     return;
546   }
547   MultilayerConvertContext ctx;
548   ctx.combined_pass = NULL;
549   ctx.num_combined_channels = 0;
550   IMB_exr_multilayer_convert(ibuf->userdata,
551                              &ctx,
552                              movieclip_convert_multilayer_add_view,
553                              movieclip_convert_multilayer_add_layer,
554                              movieclip_convert_multilayer_add_pass);
555   if (ctx.combined_pass != NULL) {
556     BLI_assert(ibuf->rect_float == NULL);
557     ibuf->rect_float = ctx.combined_pass;
558     ibuf->channels = ctx.num_combined_channels;
559     ibuf->flags |= IB_rectfloat;
560     ibuf->mall |= IB_rectfloat;
561   }
562   IMB_exr_close(ibuf->userdata);
563   ibuf->userdata = NULL;
564 #endif
565 }
566 
movieclip_load_sequence_file(MovieClip * clip,const MovieClipUser * user,int framenr,int flag)567 static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
568                                            const MovieClipUser *user,
569                                            int framenr,
570                                            int flag)
571 {
572   struct ImBuf *ibuf;
573   char name[FILE_MAX];
574   int loadflag;
575   bool use_proxy = false;
576   char *colorspace;
577 
578   use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
579   if (use_proxy) {
580     int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
581     get_proxy_fname(clip, user->render_size, undistort, framenr, name);
582 
583     /* Well, this is a bit weird, but proxies for movie sources
584      * are built in the same exact color space as the input,
585      *
586      * But image sequences are built in the display space.
587      */
588     if (clip->source == MCLIP_SRC_MOVIE) {
589       colorspace = clip->colorspace_settings.name;
590     }
591     else {
592       colorspace = NULL;
593     }
594   }
595   else {
596     get_sequence_fname(clip, framenr, name);
597     colorspace = clip->colorspace_settings.name;
598   }
599 
600   loadflag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
601 
602   /* read ibuf */
603   ibuf = IMB_loadiffname(name, loadflag, colorspace);
604   BKE_movieclip_convert_multilayer_ibuf(ibuf);
605 
606   return ibuf;
607 }
608 
movieclip_open_anim_file(MovieClip * clip)609 static void movieclip_open_anim_file(MovieClip *clip)
610 {
611   char str[FILE_MAX];
612 
613   if (!clip->anim) {
614     BLI_strncpy(str, clip->filepath, FILE_MAX);
615     BLI_path_abs(str, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
616 
617     /* FIXME: make several stream accessible in image editor, too */
618     clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name);
619 
620     if (clip->anim) {
621       if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
622         char dir[FILE_MAX];
623         BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
624         BLI_path_abs(dir, BKE_main_blendfile_path_from_global());
625         IMB_anim_set_index_dir(clip->anim, dir);
626       }
627     }
628   }
629 }
630 
movieclip_load_movie_file(MovieClip * clip,const MovieClipUser * user,int framenr,int flag)631 static ImBuf *movieclip_load_movie_file(MovieClip *clip,
632                                         const MovieClipUser *user,
633                                         int framenr,
634                                         int flag)
635 {
636   ImBuf *ibuf = NULL;
637   int tc = get_timecode(clip, flag);
638   int proxy = rendersize_to_proxy(user, flag);
639 
640   movieclip_open_anim_file(clip);
641 
642   if (clip->anim) {
643     int fra = framenr - clip->start_frame + clip->frame_offset;
644 
645     ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
646   }
647 
648   return ibuf;
649 }
650 
movieclip_calc_length(MovieClip * clip)651 static void movieclip_calc_length(MovieClip *clip)
652 {
653   if (clip->source == MCLIP_SRC_MOVIE) {
654     movieclip_open_anim_file(clip);
655 
656     if (clip->anim) {
657       clip->len = IMB_anim_get_duration(clip->anim, clip->proxy.tc);
658     }
659   }
660   else if (clip->source == MCLIP_SRC_SEQUENCE) {
661     unsigned short numlen;
662     char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
663 
664     BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
665 
666     if (numlen == 0) {
667       /* there's no number group in file name, assume it's single framed sequence */
668       clip->len = 1;
669     }
670     else {
671       clip->len = 0;
672       for (;;) {
673         get_sequence_fname(clip, clip->len + clip->start_frame, name);
674 
675         if (BLI_exists(name)) {
676           clip->len++;
677         }
678         else {
679           break;
680         }
681       }
682     }
683   }
684 }
685 
686 /*********************** image buffer cache *************************/
687 
688 typedef struct MovieClipCache {
689   /* regular movie cache */
690   struct MovieCache *moviecache;
691 
692   /* cached postprocessed shot */
693   struct {
694     ImBuf *ibuf;
695     int framenr;
696     int flag;
697 
698     /* cache for undistorted shot */
699     float focal_length;
700     float principal[2];
701     float polynomial_k[3];
702     float division_k[2];
703     float nuke_k[2];
704     float brown_k[4];
705     float brown_p[2];
706     short distortion_model;
707     bool undistortion_used;
708 
709     int proxy;
710     short render_flag;
711   } postprocessed;
712 
713   /* cache for stable shot */
714   struct {
715     ImBuf *reference_ibuf;
716 
717     ImBuf *ibuf;
718     int framenr;
719     int postprocess_flag;
720 
721     float loc[2], scale, angle, aspect;
722     int proxy, filter;
723     short render_flag;
724   } stabilized;
725 
726   int sequence_offset;
727 
728   bool is_still_sequence;
729 } MovieClipCache;
730 
731 typedef struct MovieClipImBufCacheKey {
732   int framenr;
733   int proxy;
734   short render_flag;
735 } MovieClipImBufCacheKey;
736 
737 typedef struct MovieClipCachePriorityData {
738   int framenr;
739 } MovieClipCachePriorityData;
740 
user_frame_to_cache_frame(MovieClip * clip,int framenr)741 static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
742 {
743   int index;
744 
745   index = framenr - clip->start_frame + clip->frame_offset;
746 
747   if (clip->source == MCLIP_SRC_SEQUENCE) {
748     if (clip->cache->sequence_offset == -1) {
749       unsigned short numlen;
750       char head[FILE_MAX], tail[FILE_MAX];
751 
752       BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
753 
754       /* see comment in get_sequence_fname */
755       clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
756     }
757 
758     index += clip->cache->sequence_offset;
759   }
760 
761   if (index < 0) {
762     return framenr - index;
763   }
764 
765   return framenr;
766 }
767 
moviecache_keydata(void * userkey,int * framenr,int * proxy,int * render_flags)768 static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
769 {
770   const MovieClipImBufCacheKey *key = userkey;
771 
772   *framenr = key->framenr;
773   *proxy = key->proxy;
774   *render_flags = key->render_flag;
775 }
776 
moviecache_hashhash(const void * keyv)777 static unsigned int moviecache_hashhash(const void *keyv)
778 {
779   const MovieClipImBufCacheKey *key = keyv;
780   int rval = key->framenr;
781 
782   return rval;
783 }
784 
moviecache_hashcmp(const void * av,const void * bv)785 static bool moviecache_hashcmp(const void *av, const void *bv)
786 {
787   const MovieClipImBufCacheKey *a = av;
788   const MovieClipImBufCacheKey *b = bv;
789 
790   return ((a->framenr != b->framenr) || (a->proxy != b->proxy) ||
791           (a->render_flag != b->render_flag));
792 }
793 
moviecache_getprioritydata(void * key_v)794 static void *moviecache_getprioritydata(void *key_v)
795 {
796   MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)key_v;
797   MovieClipCachePriorityData *priority_data;
798 
799   priority_data = MEM_callocN(sizeof(*priority_data), "movie cache clip priority data");
800   priority_data->framenr = key->framenr;
801 
802   return priority_data;
803 }
804 
moviecache_getitempriority(void * last_userkey_v,void * priority_data_v)805 static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
806 {
807   MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *)last_userkey_v;
808   MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
809 
810   return -abs(last_userkey->framenr - priority_data->framenr);
811 }
812 
moviecache_prioritydeleter(void * priority_data_v)813 static void moviecache_prioritydeleter(void *priority_data_v)
814 {
815   MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
816 
817   MEM_freeN(priority_data);
818 }
819 
get_imbuf_cache(MovieClip * clip,const MovieClipUser * user,int flag)820 static ImBuf *get_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
821 {
822   if (clip->cache) {
823     MovieClipImBufCacheKey key;
824 
825     if (!clip->cache->is_still_sequence) {
826       key.framenr = user_frame_to_cache_frame(clip, user->framenr);
827     }
828     else {
829       key.framenr = 1;
830     }
831 
832     if (flag & MCLIP_USE_PROXY) {
833       key.proxy = rendersize_to_proxy(user, flag);
834       key.render_flag = user->render_flag;
835     }
836     else {
837       key.proxy = IMB_PROXY_NONE;
838       key.render_flag = 0;
839     }
840 
841     return IMB_moviecache_get(clip->cache->moviecache, &key);
842   }
843 
844   return NULL;
845 }
846 
has_imbuf_cache(MovieClip * clip,MovieClipUser * user,int flag)847 static bool has_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
848 {
849   if (clip->cache) {
850     MovieClipImBufCacheKey key;
851 
852     key.framenr = user_frame_to_cache_frame(clip, user->framenr);
853 
854     if (flag & MCLIP_USE_PROXY) {
855       key.proxy = rendersize_to_proxy(user, flag);
856       key.render_flag = user->render_flag;
857     }
858     else {
859       key.proxy = IMB_PROXY_NONE;
860       key.render_flag = 0;
861     }
862 
863     return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
864   }
865 
866   return false;
867 }
868 
put_imbuf_cache(MovieClip * clip,const MovieClipUser * user,ImBuf * ibuf,int flag,bool destructive)869 static bool put_imbuf_cache(
870     MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
871 {
872   MovieClipImBufCacheKey key;
873 
874   if (clip->cache == NULL) {
875     struct MovieCache *moviecache;
876 
877     // char cache_name[64];
878     // BLI_snprintf(cache_name, sizeof(cache_name), "movie %s", clip->id.name);
879 
880     clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
881 
882     moviecache = IMB_moviecache_create(
883         "movieclip", sizeof(MovieClipImBufCacheKey), moviecache_hashhash, moviecache_hashcmp);
884 
885     IMB_moviecache_set_getdata_callback(moviecache, moviecache_keydata);
886     IMB_moviecache_set_priority_callback(moviecache,
887                                          moviecache_getprioritydata,
888                                          moviecache_getitempriority,
889                                          moviecache_prioritydeleter);
890 
891     clip->cache->moviecache = moviecache;
892     clip->cache->sequence_offset = -1;
893     if (clip->source == MCLIP_SRC_SEQUENCE) {
894       unsigned short numlen;
895       BLI_path_sequence_decode(clip->filepath, NULL, NULL, &numlen);
896       clip->cache->is_still_sequence = (numlen == 0);
897     }
898   }
899 
900   if (!clip->cache->is_still_sequence) {
901     key.framenr = user_frame_to_cache_frame(clip, user->framenr);
902   }
903   else {
904     key.framenr = 1;
905   }
906 
907   if (flag & MCLIP_USE_PROXY) {
908     key.proxy = rendersize_to_proxy(user, flag);
909     key.render_flag = user->render_flag;
910   }
911   else {
912     key.proxy = IMB_PROXY_NONE;
913     key.render_flag = 0;
914   }
915 
916   if (destructive) {
917     IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
918     return true;
919   }
920 
921   return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
922 }
923 
moviecache_check_free_proxy(ImBuf * UNUSED (ibuf),void * userkey,void * UNUSED (userdata))924 static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf), void *userkey, void *UNUSED(userdata))
925 {
926   MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey;
927 
928   return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
929 }
930 
931 /*********************** common functions *************************/
932 
933 /* only image block itself */
movieclip_alloc(Main * bmain,const char * name)934 static MovieClip *movieclip_alloc(Main *bmain, const char *name)
935 {
936   MovieClip *clip;
937 
938   clip = BKE_id_new(bmain, ID_MC, name);
939 
940   return clip;
941 }
942 
movieclip_load_get_size(MovieClip * clip)943 static void movieclip_load_get_size(MovieClip *clip)
944 {
945   int width, height;
946   MovieClipUser user = {0};
947 
948   user.framenr = 1;
949   BKE_movieclip_get_size(clip, &user, &width, &height);
950 
951   if (width && height) {
952     clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
953     clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
954   }
955   else {
956     clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
957   }
958 }
959 
detect_clip_source(Main * bmain,MovieClip * clip)960 static void detect_clip_source(Main *bmain, MovieClip *clip)
961 {
962   ImBuf *ibuf;
963   char name[FILE_MAX];
964 
965   BLI_strncpy(name, clip->filepath, sizeof(name));
966   BLI_path_abs(name, BKE_main_blendfile_path(bmain));
967 
968   ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
969   if (ibuf) {
970     clip->source = MCLIP_SRC_SEQUENCE;
971     IMB_freeImBuf(ibuf);
972   }
973   else {
974     clip->source = MCLIP_SRC_MOVIE;
975   }
976 }
977 
978 /* checks if image was already loaded, then returns same image
979  * otherwise creates new.
980  * does not load ibuf itself
981  * pass on optional frame for #name images */
BKE_movieclip_file_add(Main * bmain,const char * name)982 MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
983 {
984   MovieClip *clip;
985   int file;
986   char str[FILE_MAX];
987 
988   BLI_strncpy(str, name, sizeof(str));
989   BLI_path_abs(str, BKE_main_blendfile_path(bmain));
990 
991   /* exists? */
992   file = BLI_open(str, O_BINARY | O_RDONLY, 0);
993   if (file == -1) {
994     return NULL;
995   }
996   close(file);
997 
998   /* ** add new movieclip ** */
999 
1000   /* create a short library name */
1001   clip = movieclip_alloc(bmain, BLI_path_basename(name));
1002   BLI_strncpy(clip->filepath, name, sizeof(clip->filepath));
1003 
1004   detect_clip_source(bmain, clip);
1005 
1006   movieclip_load_get_size(clip);
1007   if (clip->lastsize[0]) {
1008     int width = clip->lastsize[0];
1009 
1010     clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
1011   }
1012 
1013   movieclip_calc_length(clip);
1014 
1015   return clip;
1016 }
1017 
BKE_movieclip_file_add_exists_ex(Main * bmain,const char * filepath,bool * r_exists)1018 MovieClip *BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
1019 {
1020   MovieClip *clip;
1021   char str[FILE_MAX], strtest[FILE_MAX];
1022 
1023   BLI_strncpy(str, filepath, sizeof(str));
1024   BLI_path_abs(str, BKE_main_blendfile_path(bmain));
1025 
1026   /* first search an identical filepath */
1027   for (clip = bmain->movieclips.first; clip; clip = clip->id.next) {
1028     BLI_strncpy(strtest, clip->filepath, sizeof(clip->filepath));
1029     BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &clip->id));
1030 
1031     if (BLI_path_cmp(strtest, str) == 0) {
1032       id_us_plus(&clip->id); /* officially should not, it doesn't link here! */
1033       if (r_exists) {
1034         *r_exists = true;
1035       }
1036       return clip;
1037     }
1038   }
1039 
1040   if (r_exists) {
1041     *r_exists = false;
1042   }
1043   return BKE_movieclip_file_add(bmain, filepath);
1044 }
1045 
BKE_movieclip_file_add_exists(Main * bmain,const char * filepath)1046 MovieClip *BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
1047 {
1048   return BKE_movieclip_file_add_exists_ex(bmain, filepath, NULL);
1049 }
1050 
real_ibuf_size(const MovieClip * clip,const MovieClipUser * user,const ImBuf * ibuf,int * width,int * height)1051 static void real_ibuf_size(
1052     const MovieClip *clip, const MovieClipUser *user, const ImBuf *ibuf, int *width, int *height)
1053 {
1054   *width = ibuf->x;
1055   *height = ibuf->y;
1056 
1057   if (clip->flag & MCLIP_USE_PROXY) {
1058     switch (user->render_size) {
1059       case MCLIP_PROXY_RENDER_SIZE_25:
1060         (*width) *= 4;
1061         (*height) *= 4;
1062         break;
1063 
1064       case MCLIP_PROXY_RENDER_SIZE_50:
1065         (*width) *= 2.0f;
1066         (*height) *= 2.0f;
1067         break;
1068 
1069       case MCLIP_PROXY_RENDER_SIZE_75:
1070         *width = ((float)*width) * 4.0f / 3.0f;
1071         *height = ((float)*height) * 4.0f / 3.0f;
1072         break;
1073     }
1074   }
1075 }
1076 
get_undistorted_ibuf(MovieClip * clip,struct MovieDistortion * distortion,ImBuf * ibuf)1077 static ImBuf *get_undistorted_ibuf(MovieClip *clip,
1078                                    struct MovieDistortion *distortion,
1079                                    ImBuf *ibuf)
1080 {
1081   ImBuf *undistibuf;
1082 
1083   if (distortion) {
1084     undistibuf = BKE_tracking_distortion_exec(
1085         distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1);
1086   }
1087   else {
1088     undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
1089   }
1090 
1091   IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y);
1092 
1093   return undistibuf;
1094 }
1095 
need_undistortion_postprocess(const MovieClipUser * user,int clip_flag)1096 static bool need_undistortion_postprocess(const MovieClipUser *user, int clip_flag)
1097 {
1098   bool result = 0;
1099   const bool uses_full_frame = ((clip_flag & MCLIP_USE_PROXY) == 0) ||
1100                                (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL);
1101   /* Only full undistorted render can be used as on-fly undistorting image. */
1102   result |= uses_full_frame && (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
1103   return result;
1104 }
1105 
need_postprocessed_frame(const MovieClipUser * user,int clip_flag,int postprocess_flag)1106 static bool need_postprocessed_frame(const MovieClipUser *user,
1107                                      int clip_flag,
1108                                      int postprocess_flag)
1109 {
1110   bool result = (postprocess_flag != 0);
1111   result |= need_undistortion_postprocess(user, clip_flag);
1112   return result;
1113 }
1114 
check_undistortion_cache_flags(const MovieClip * clip)1115 static bool check_undistortion_cache_flags(const MovieClip *clip)
1116 {
1117   const MovieClipCache *cache = clip->cache;
1118   const MovieTrackingCamera *camera = &clip->tracking.camera;
1119 
1120   if (camera->focal != cache->postprocessed.focal_length) {
1121     return false;
1122   }
1123 
1124   /* check for distortion model changes */
1125   if (!equals_v2v2(camera->principal, cache->postprocessed.principal)) {
1126     return false;
1127   }
1128 
1129   if (camera->distortion_model != cache->postprocessed.distortion_model) {
1130     return false;
1131   }
1132 
1133   if (!equals_v3v3(&camera->k1, cache->postprocessed.polynomial_k)) {
1134     return false;
1135   }
1136 
1137   if (!equals_v2v2(&camera->division_k1, cache->postprocessed.division_k)) {
1138     return false;
1139   }
1140 
1141   if (!equals_v2v2(&camera->nuke_k1, cache->postprocessed.nuke_k)) {
1142     return false;
1143   }
1144 
1145   if (!equals_v4v4(&camera->brown_k1, cache->postprocessed.brown_k)) {
1146     return false;
1147   }
1148   if (!equals_v2v2(&camera->brown_p1, cache->postprocessed.brown_p)) {
1149     return false;
1150   }
1151 
1152   return true;
1153 }
1154 
get_postprocessed_cached_frame(const MovieClip * clip,const MovieClipUser * user,int flag,int postprocess_flag)1155 static ImBuf *get_postprocessed_cached_frame(const MovieClip *clip,
1156                                              const MovieClipUser *user,
1157                                              int flag,
1158                                              int postprocess_flag)
1159 {
1160   const MovieClipCache *cache = clip->cache;
1161   int framenr = user->framenr;
1162   short proxy = IMB_PROXY_NONE;
1163   int render_flag = 0;
1164 
1165   if (flag & MCLIP_USE_PROXY) {
1166     proxy = rendersize_to_proxy(user, flag);
1167     render_flag = user->render_flag;
1168   }
1169 
1170   /* no cache or no cached postprocessed image */
1171   if (!clip->cache || !clip->cache->postprocessed.ibuf) {
1172     return NULL;
1173   }
1174 
1175   /* postprocessing happened for other frame */
1176   if (cache->postprocessed.framenr != framenr) {
1177     return NULL;
1178   }
1179 
1180   /* cached ibuf used different proxy settings */
1181   if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy) {
1182     return NULL;
1183   }
1184 
1185   if (cache->postprocessed.flag != postprocess_flag) {
1186     return NULL;
1187   }
1188 
1189   if (need_undistortion_postprocess(user, flag)) {
1190     if (!check_undistortion_cache_flags(clip)) {
1191       return NULL;
1192     }
1193   }
1194   else if (cache->postprocessed.undistortion_used) {
1195     return NULL;
1196   }
1197 
1198   IMB_refImBuf(cache->postprocessed.ibuf);
1199 
1200   return cache->postprocessed.ibuf;
1201 }
1202 
postprocess_frame(MovieClip * clip,const MovieClipUser * user,ImBuf * ibuf,int flag,int postprocess_flag)1203 static ImBuf *postprocess_frame(
1204     MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1205 {
1206   ImBuf *postproc_ibuf = NULL;
1207 
1208   if (need_undistortion_postprocess(user, flag)) {
1209     postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf);
1210   }
1211   else {
1212     postproc_ibuf = IMB_dupImBuf(ibuf);
1213   }
1214 
1215   if (postprocess_flag) {
1216     bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
1217     bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
1218     bool disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
1219     bool grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
1220 
1221     if (disable_red || disable_green || disable_blue || grayscale) {
1222       BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1);
1223     }
1224   }
1225 
1226   return postproc_ibuf;
1227 }
1228 
put_postprocessed_frame_to_cache(MovieClip * clip,const MovieClipUser * user,ImBuf * ibuf,int flag,int postprocess_flag)1229 static void put_postprocessed_frame_to_cache(
1230     MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1231 {
1232   MovieClipCache *cache = clip->cache;
1233   MovieTrackingCamera *camera = &clip->tracking.camera;
1234 
1235   cache->postprocessed.framenr = user->framenr;
1236   cache->postprocessed.flag = postprocess_flag;
1237 
1238   if (flag & MCLIP_USE_PROXY) {
1239     cache->postprocessed.proxy = rendersize_to_proxy(user, flag);
1240     cache->postprocessed.render_flag = user->render_flag;
1241   }
1242   else {
1243     cache->postprocessed.proxy = IMB_PROXY_NONE;
1244     cache->postprocessed.render_flag = 0;
1245   }
1246 
1247   if (need_undistortion_postprocess(user, flag)) {
1248     cache->postprocessed.distortion_model = camera->distortion_model;
1249     cache->postprocessed.focal_length = camera->focal;
1250     copy_v2_v2(cache->postprocessed.principal, camera->principal);
1251     copy_v3_v3(cache->postprocessed.polynomial_k, &camera->k1);
1252     copy_v2_v2(cache->postprocessed.division_k, &camera->division_k1);
1253     copy_v2_v2(cache->postprocessed.nuke_k, &camera->nuke_k1);
1254     copy_v4_v4(cache->postprocessed.brown_k, &camera->brown_k1);
1255     copy_v2_v2(cache->postprocessed.brown_p, &camera->brown_p1);
1256     cache->postprocessed.undistortion_used = true;
1257   }
1258   else {
1259     cache->postprocessed.undistortion_used = false;
1260   }
1261 
1262   IMB_refImBuf(ibuf);
1263 
1264   if (cache->postprocessed.ibuf) {
1265     IMB_freeImBuf(cache->postprocessed.ibuf);
1266   }
1267 
1268   cache->postprocessed.ibuf = ibuf;
1269 }
1270 
movieclip_get_postprocessed_ibuf(MovieClip * clip,const MovieClipUser * user,int flag,int postprocess_flag,int cache_flag)1271 static ImBuf *movieclip_get_postprocessed_ibuf(
1272     MovieClip *clip, const MovieClipUser *user, int flag, int postprocess_flag, int cache_flag)
1273 {
1274   ImBuf *ibuf = NULL;
1275   int framenr = user->framenr;
1276   bool need_postprocess = false;
1277 
1278   /* cache isn't threadsafe itself and also loading of movies
1279    * can't happen from concurrent threads that's why we use lock here */
1280   BLI_thread_lock(LOCK_MOVIECLIP);
1281 
1282   /* try to obtain cached postprocessed frame first */
1283   if (need_postprocessed_frame(user, flag, postprocess_flag)) {
1284     ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
1285 
1286     if (!ibuf) {
1287       need_postprocess = true;
1288     }
1289   }
1290 
1291   if (!ibuf) {
1292     ibuf = get_imbuf_cache(clip, user, flag);
1293   }
1294 
1295   if (!ibuf) {
1296     bool use_sequence = false;
1297 
1298     /* undistorted proxies for movies should be read as image sequence */
1299     use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
1300                    (user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL);
1301 
1302     if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
1303       ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
1304     }
1305     else {
1306       ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
1307     }
1308 
1309     if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1310       put_imbuf_cache(clip, user, ibuf, flag, true);
1311     }
1312   }
1313 
1314   if (ibuf) {
1315     clip->lastframe = framenr;
1316     real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
1317 
1318     /* postprocess frame and put to cache if needed*/
1319     if (need_postprocess) {
1320       ImBuf *tmpibuf = ibuf;
1321       ibuf = postprocess_frame(clip, user, tmpibuf, flag, postprocess_flag);
1322       IMB_freeImBuf(tmpibuf);
1323       if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1324         put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
1325       }
1326     }
1327   }
1328 
1329   BLI_thread_unlock(LOCK_MOVIECLIP);
1330 
1331   /* Fallback render in case proxies are not enabled or built */
1332   if (!ibuf && user->render_flag & MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER &&
1333       user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL) {
1334     MovieClipUser user_fallback = *user;
1335     user_fallback.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1336 
1337     ibuf = movieclip_get_postprocessed_ibuf(
1338         clip, &user_fallback, flag, postprocess_flag, cache_flag);
1339   }
1340 
1341   return ibuf;
1342 }
1343 
BKE_movieclip_get_ibuf(MovieClip * clip,MovieClipUser * user)1344 ImBuf *BKE_movieclip_get_ibuf(MovieClip *clip, MovieClipUser *user)
1345 {
1346   return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
1347 }
1348 
BKE_movieclip_get_ibuf_flag(MovieClip * clip,MovieClipUser * user,int flag,int cache_flag)1349 ImBuf *BKE_movieclip_get_ibuf_flag(MovieClip *clip, MovieClipUser *user, int flag, int cache_flag)
1350 {
1351   return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
1352 }
1353 
BKE_movieclip_get_postprocessed_ibuf(MovieClip * clip,MovieClipUser * user,int postprocess_flag)1354 ImBuf *BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip,
1355                                             MovieClipUser *user,
1356                                             int postprocess_flag)
1357 {
1358   return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
1359 }
1360 
get_stable_cached_frame(MovieClip * clip,MovieClipUser * user,ImBuf * reference_ibuf,int framenr,int postprocess_flag)1361 static ImBuf *get_stable_cached_frame(
1362     MovieClip *clip, MovieClipUser *user, ImBuf *reference_ibuf, int framenr, int postprocess_flag)
1363 {
1364   MovieClipCache *cache = clip->cache;
1365   MovieTracking *tracking = &clip->tracking;
1366   ImBuf *stableibuf;
1367   float tloc[2], tscale, tangle;
1368   short proxy = IMB_PROXY_NONE;
1369   int render_flag = 0;
1370   int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1371 
1372   if (clip->flag & MCLIP_USE_PROXY) {
1373     proxy = rendersize_to_proxy(user, clip->flag);
1374     render_flag = user->render_flag;
1375   }
1376 
1377   /* there's no cached frame or it was calculated for another frame */
1378   if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr) {
1379     return NULL;
1380   }
1381 
1382   if (cache->stabilized.reference_ibuf != reference_ibuf) {
1383     return NULL;
1384   }
1385 
1386   /* cached ibuf used different proxy settings */
1387   if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy) {
1388     return NULL;
1389   }
1390 
1391   if (cache->stabilized.postprocess_flag != postprocess_flag) {
1392     return NULL;
1393   }
1394 
1395   /* stabilization also depends on pixel aspect ratio */
1396   if (cache->stabilized.aspect != tracking->camera.pixel_aspect) {
1397     return NULL;
1398   }
1399 
1400   if (cache->stabilized.filter != tracking->stabilization.filter) {
1401     return NULL;
1402   }
1403 
1404   stableibuf = cache->stabilized.ibuf;
1405 
1406   BKE_tracking_stabilization_data_get(
1407       clip, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
1408 
1409   /* check for stabilization parameters */
1410   if (tscale != cache->stabilized.scale || tangle != cache->stabilized.angle ||
1411       !equals_v2v2(tloc, cache->stabilized.loc)) {
1412     return NULL;
1413   }
1414 
1415   IMB_refImBuf(stableibuf);
1416 
1417   return stableibuf;
1418 }
1419 
put_stabilized_frame_to_cache(MovieClip * clip,MovieClipUser * user,ImBuf * ibuf,int framenr,int postprocess_flag)1420 static ImBuf *put_stabilized_frame_to_cache(
1421     MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int framenr, int postprocess_flag)
1422 {
1423   MovieClipCache *cache = clip->cache;
1424   MovieTracking *tracking = &clip->tracking;
1425   ImBuf *stableibuf;
1426   float tloc[2], tscale, tangle;
1427   int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1428 
1429   stableibuf = BKE_tracking_stabilize_frame(clip, clip_framenr, ibuf, tloc, &tscale, &tangle);
1430 
1431   copy_v2_v2(cache->stabilized.loc, tloc);
1432 
1433   cache->stabilized.reference_ibuf = ibuf;
1434   cache->stabilized.scale = tscale;
1435   cache->stabilized.angle = tangle;
1436   cache->stabilized.framenr = framenr;
1437   cache->stabilized.aspect = tracking->camera.pixel_aspect;
1438   cache->stabilized.filter = tracking->stabilization.filter;
1439 
1440   if (clip->flag & MCLIP_USE_PROXY) {
1441     cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
1442     cache->stabilized.render_flag = user->render_flag;
1443   }
1444   else {
1445     cache->stabilized.proxy = IMB_PROXY_NONE;
1446     cache->stabilized.render_flag = 0;
1447   }
1448 
1449   cache->stabilized.postprocess_flag = postprocess_flag;
1450 
1451   if (cache->stabilized.ibuf) {
1452     IMB_freeImBuf(cache->stabilized.ibuf);
1453   }
1454 
1455   cache->stabilized.ibuf = stableibuf;
1456 
1457   IMB_refImBuf(stableibuf);
1458 
1459   return stableibuf;
1460 }
1461 
BKE_movieclip_get_stable_ibuf(MovieClip * clip,MovieClipUser * user,float loc[2],float * scale,float * angle,int postprocess_flag)1462 ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip,
1463                                      MovieClipUser *user,
1464                                      float loc[2],
1465                                      float *scale,
1466                                      float *angle,
1467                                      int postprocess_flag)
1468 {
1469   ImBuf *ibuf, *stableibuf = NULL;
1470   int framenr = user->framenr;
1471 
1472   ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
1473 
1474   if (!ibuf) {
1475     return NULL;
1476   }
1477 
1478   if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
1479     MovieClipCache *cache = clip->cache;
1480 
1481     stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
1482 
1483     if (!stableibuf) {
1484       stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
1485     }
1486 
1487     if (loc) {
1488       copy_v2_v2(loc, cache->stabilized.loc);
1489     }
1490 
1491     if (scale) {
1492       *scale = cache->stabilized.scale;
1493     }
1494 
1495     if (angle) {
1496       *angle = cache->stabilized.angle;
1497     }
1498   }
1499   else {
1500     if (loc) {
1501       zero_v2(loc);
1502     }
1503 
1504     if (scale) {
1505       *scale = 1.0f;
1506     }
1507 
1508     if (angle) {
1509       *angle = 0.0f;
1510     }
1511 
1512     stableibuf = ibuf;
1513   }
1514 
1515   if (stableibuf != ibuf) {
1516     IMB_freeImBuf(ibuf);
1517     ibuf = stableibuf;
1518   }
1519 
1520   return ibuf;
1521 }
1522 
BKE_movieclip_has_frame(MovieClip * clip,MovieClipUser * user)1523 bool BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
1524 {
1525   ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1526 
1527   if (ibuf) {
1528     IMB_freeImBuf(ibuf);
1529     return true;
1530   }
1531 
1532   return false;
1533 }
1534 
BKE_movieclip_get_size(MovieClip * clip,MovieClipUser * user,int * width,int * height)1535 void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height)
1536 {
1537 #if 0
1538   /* originally was needed to support image sequences with different image dimensions,
1539    * which might be useful for such things as reconstruction of unordered image sequence,
1540    * or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded
1541    * cache lookups and even unwanted non-proxied files loading when doing mask parenting,
1542    * so let's disable this for now and assume image sequence consists of images with
1543    * equal sizes (sergey)
1544    * TODO(sergey): Support reading sequences of different resolution.
1545    */
1546   if (user->framenr == clip->lastframe) {
1547 #endif
1548   if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
1549     *width = clip->lastsize[0];
1550     *height = clip->lastsize[1];
1551   }
1552   else {
1553     ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1554 
1555     if (ibuf && ibuf->x && ibuf->y) {
1556       real_ibuf_size(clip, user, ibuf, width, height);
1557     }
1558     else {
1559       *width = clip->lastsize[0];
1560       *height = clip->lastsize[1];
1561     }
1562 
1563     if (ibuf) {
1564       IMB_freeImBuf(ibuf);
1565     }
1566   }
1567 }
1568 void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2])
1569 {
1570   int width, height;
1571   BKE_movieclip_get_size(clip, user, &width, &height);
1572 
1573   size[0] = (float)width;
1574   size[1] = (float)height;
1575 }
1576 
1577 int BKE_movieclip_get_duration(MovieClip *clip)
1578 {
1579   if (!clip->len) {
1580     movieclip_calc_length(clip);
1581   }
1582 
1583   return clip->len;
1584 }
1585 
1586 float BKE_movieclip_get_fps(MovieClip *clip)
1587 {
1588   if (clip->source != MCLIP_SRC_MOVIE) {
1589     return 0.0f;
1590   }
1591   movieclip_open_anim_file(clip);
1592   if (clip->anim == NULL) {
1593     return 0.0f;
1594   }
1595   short frs_sec;
1596   float frs_sec_base;
1597   if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
1598     return (float)frs_sec / frs_sec_base;
1599   }
1600   return 0.0f;
1601 }
1602 
1603 void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
1604 {
1605   *aspx = 1.0;
1606 
1607   /* x is always 1 */
1608   *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
1609 }
1610 
1611 /* get segments of cached frames. useful for debugging cache policies */
1612 void BKE_movieclip_get_cache_segments(MovieClip *clip,
1613                                       MovieClipUser *user,
1614                                       int *r_totseg,
1615                                       int **r_points)
1616 {
1617   *r_totseg = 0;
1618   *r_points = NULL;
1619 
1620   if (clip->cache) {
1621     int proxy = rendersize_to_proxy(user, clip->flag);
1622 
1623     IMB_moviecache_get_cache_segments(
1624         clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
1625   }
1626 }
1627 
1628 void BKE_movieclip_user_set_frame(MovieClipUser *iuser, int framenr)
1629 {
1630   /* TODO: clamp framenr here? */
1631 
1632   iuser->framenr = framenr;
1633 }
1634 
1635 static void free_buffers(MovieClip *clip)
1636 {
1637   if (clip->cache) {
1638     IMB_moviecache_free(clip->cache->moviecache);
1639 
1640     if (clip->cache->postprocessed.ibuf) {
1641       IMB_freeImBuf(clip->cache->postprocessed.ibuf);
1642     }
1643 
1644     if (clip->cache->stabilized.ibuf) {
1645       IMB_freeImBuf(clip->cache->stabilized.ibuf);
1646     }
1647 
1648     MEM_freeN(clip->cache);
1649     clip->cache = NULL;
1650   }
1651 
1652   if (clip->anim) {
1653     IMB_free_anim(clip->anim);
1654     clip->anim = NULL;
1655   }
1656 
1657   MovieClip_RuntimeGPUTexture *tex;
1658   for (tex = clip->runtime.gputextures.first; tex; tex = tex->next) {
1659     for (int i = 0; i < TEXTARGET_COUNT; i++) {
1660       if (tex->gputexture[i] != NULL) {
1661         GPU_texture_free(tex->gputexture[i]);
1662         tex->gputexture[i] = NULL;
1663       }
1664     }
1665   }
1666   BLI_freelistN(&clip->runtime.gputextures);
1667 }
1668 
1669 void BKE_movieclip_clear_cache(MovieClip *clip)
1670 {
1671   free_buffers(clip);
1672 }
1673 
1674 void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
1675 {
1676   if (clip->cache && clip->cache->moviecache) {
1677     IMB_moviecache_cleanup(clip->cache->moviecache, moviecache_check_free_proxy, NULL);
1678   }
1679 }
1680 
1681 void BKE_movieclip_reload(Main *bmain, MovieClip *clip)
1682 {
1683   /* clear cache */
1684   free_buffers(clip);
1685 
1686   /* update clip source */
1687   detect_clip_source(bmain, clip);
1688 
1689   clip->lastsize[0] = clip->lastsize[1] = 0;
1690   movieclip_load_get_size(clip);
1691 
1692   movieclip_calc_length(clip);
1693 
1694   /* same as for image update -- don't use notifiers because they are not 100% sure to succeeded
1695    * (node trees which are not currently visible wouldn't be refreshed)
1696    */
1697   {
1698     Scene *scene;
1699     for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
1700       if (scene->nodetree) {
1701         nodeUpdateID(scene->nodetree, &clip->id);
1702       }
1703     }
1704   }
1705 }
1706 
1707 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
1708 {
1709   if (scopes->ok) {
1710     return;
1711   }
1712 
1713   if (scopes->track_preview) {
1714     IMB_freeImBuf(scopes->track_preview);
1715     scopes->track_preview = NULL;
1716   }
1717 
1718   if (scopes->track_search) {
1719     IMB_freeImBuf(scopes->track_search);
1720     scopes->track_search = NULL;
1721   }
1722 
1723   scopes->marker = NULL;
1724   scopes->track = NULL;
1725   scopes->track_locked = true;
1726 
1727   if (clip) {
1728     MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
1729 
1730     if (act_track) {
1731       MovieTrackingTrack *track = act_track;
1732       int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1733       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1734 
1735       scopes->marker = marker;
1736       scopes->track = track;
1737 
1738       if (marker->flag & MARKER_DISABLED) {
1739         scopes->track_disabled = true;
1740       }
1741       else {
1742         ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1743 
1744         scopes->track_disabled = false;
1745 
1746         if (ibuf && (ibuf->rect || ibuf->rect_float)) {
1747           MovieTrackingMarker undist_marker = *marker;
1748 
1749           if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1750             int width, height;
1751             float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1752 
1753             BKE_movieclip_get_size(clip, user, &width, &height);
1754 
1755             undist_marker.pos[0] *= width;
1756             undist_marker.pos[1] *= height * aspy;
1757 
1758             BKE_tracking_undistort_v2(
1759                 &clip->tracking, width, height, undist_marker.pos, undist_marker.pos);
1760 
1761             undist_marker.pos[0] /= width;
1762             undist_marker.pos[1] /= height * aspy;
1763           }
1764 
1765           scopes->track_search = BKE_tracking_get_search_imbuf(
1766               ibuf, track, &undist_marker, true, true);
1767 
1768           scopes->undist_marker = undist_marker;
1769 
1770           scopes->frame_width = ibuf->x;
1771           scopes->frame_height = ibuf->y;
1772 
1773           scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
1774         }
1775 
1776         IMB_freeImBuf(ibuf);
1777       }
1778 
1779       if ((track->flag & TRACK_LOCKED) == 0) {
1780         float pat_min[2], pat_max[2];
1781 
1782         scopes->track_locked = false;
1783 
1784         /* XXX: would work fine with non-transformed patterns, but would likely fail
1785          *      with transformed patterns, but that would be easier to debug when
1786          *      we'll have real pattern sampling (at least to test) */
1787         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1788 
1789         scopes->slide_scale[0] = pat_max[0] - pat_min[0];
1790         scopes->slide_scale[1] = pat_max[1] - pat_min[1];
1791       }
1792     }
1793   }
1794 
1795   scopes->framenr = user->framenr;
1796   scopes->ok = true;
1797 }
1798 
1799 static void movieclip_build_proxy_ibuf(
1800     MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
1801 {
1802   char name[FILE_MAX];
1803   int quality, rectx, recty;
1804   int size = rendersize_to_number(proxy_render_size);
1805   ImBuf *scaleibuf;
1806 
1807   get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
1808 
1809   rectx = ibuf->x * size / 100.0f;
1810   recty = ibuf->y * size / 100.0f;
1811 
1812   scaleibuf = IMB_dupImBuf(ibuf);
1813 
1814   if (threaded) {
1815     IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
1816   }
1817   else {
1818     IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
1819   }
1820 
1821   quality = clip->proxy.quality;
1822   scaleibuf->ftype = IMB_FTYPE_JPG;
1823   scaleibuf->foptions.quality = quality;
1824   /* unsupported feature only confuses other s/w */
1825   if (scaleibuf->planes == 32) {
1826     scaleibuf->planes = 24;
1827   }
1828 
1829   /* TODO: currently the most weak part of multi-threaded proxies,
1830    *       could be solved in a way that thread only prepares memory
1831    *       buffer and write to disk happens separately
1832    */
1833   BLI_thread_lock(LOCK_MOVIECLIP);
1834 
1835   BLI_make_existing_file(name);
1836   if (IMB_saveiff(scaleibuf, name, IB_rect) == 0) {
1837     perror(name);
1838   }
1839 
1840   BLI_thread_unlock(LOCK_MOVIECLIP);
1841 
1842   IMB_freeImBuf(scaleibuf);
1843 }
1844 
1845 /* note: currently used by proxy job for movies, threading happens within single frame
1846  * (meaning scaling shall be threaded)
1847  */
1848 void BKE_movieclip_build_proxy_frame(MovieClip *clip,
1849                                      int clip_flag,
1850                                      struct MovieDistortion *distortion,
1851                                      int cfra,
1852                                      int *build_sizes,
1853                                      int build_count,
1854                                      bool undistorted)
1855 {
1856   ImBuf *ibuf;
1857   MovieClipUser user;
1858 
1859   if (!build_count) {
1860     return;
1861   }
1862 
1863   user.framenr = cfra;
1864   user.render_flag = 0;
1865   user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
1866 
1867   ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1868 
1869   if (ibuf) {
1870     ImBuf *tmpibuf = ibuf;
1871     int i;
1872 
1873     if (undistorted) {
1874       tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1875     }
1876 
1877     for (i = 0; i < build_count; i++) {
1878       movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
1879     }
1880 
1881     IMB_freeImBuf(ibuf);
1882 
1883     if (tmpibuf != ibuf) {
1884       IMB_freeImBuf(tmpibuf);
1885     }
1886   }
1887 }
1888 
1889 /* note: currently used by proxy job for sequences, threading happens within sequence
1890  * (different threads handles different frames, no threading within frame is needed)
1891  */
1892 void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip,
1893                                               ImBuf *ibuf,
1894                                               struct MovieDistortion *distortion,
1895                                               int cfra,
1896                                               int *build_sizes,
1897                                               int build_count,
1898                                               bool undistorted)
1899 {
1900   if (!build_count) {
1901     return;
1902   }
1903 
1904   if (ibuf) {
1905     ImBuf *tmpibuf = ibuf;
1906     int i;
1907 
1908     if (undistorted) {
1909       tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1910     }
1911 
1912     for (i = 0; i < build_count; i++) {
1913       movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
1914     }
1915 
1916     if (tmpibuf != ibuf) {
1917       IMB_freeImBuf(tmpibuf);
1918     }
1919   }
1920 }
1921 
1922 float BKE_movieclip_remap_scene_to_clip_frame(const MovieClip *clip, float framenr)
1923 {
1924   return framenr - (float)clip->start_frame + 1.0f;
1925 }
1926 
1927 float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, float framenr)
1928 {
1929   return framenr + (float)clip->start_frame - 1.0f;
1930 }
1931 
1932 void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char *name)
1933 {
1934   if (clip->source == MCLIP_SRC_SEQUENCE) {
1935     int use_proxy;
1936 
1937     use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
1938                 user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
1939 
1940     if (use_proxy) {
1941       int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1942       get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
1943     }
1944     else {
1945       get_sequence_fname(clip, user->framenr, name);
1946     }
1947   }
1948   else {
1949     BLI_strncpy(name, clip->filepath, FILE_MAX);
1950     BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
1951   }
1952 }
1953 
1954 ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
1955 {
1956   ImBuf *ibuf = NULL;
1957 
1958   if (clip->source == MCLIP_SRC_MOVIE) {
1959     BLI_thread_lock(LOCK_MOVIECLIP);
1960     ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
1961     BLI_thread_unlock(LOCK_MOVIECLIP);
1962   }
1963 
1964   return ibuf;
1965 }
1966 
1967 bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
1968 {
1969   bool has_frame = false;
1970 
1971   BLI_thread_lock(LOCK_MOVIECLIP);
1972   has_frame = has_imbuf_cache(clip, user, clip->flag);
1973   BLI_thread_unlock(LOCK_MOVIECLIP);
1974 
1975   return has_frame;
1976 }
1977 
1978 bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf)
1979 {
1980   bool result;
1981 
1982   BLI_thread_lock(LOCK_MOVIECLIP);
1983   result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
1984   BLI_thread_unlock(LOCK_MOVIECLIP);
1985 
1986   return result;
1987 }
1988 
1989 static void movieclip_selection_sync(MovieClip *clip_dst, const MovieClip *clip_src)
1990 {
1991   BLI_assert(clip_dst != clip_src);
1992   MovieTracking *tracking_dst = &clip_dst->tracking, tracking_src = clip_src->tracking;
1993   /* Syncs the active object, track and plane track. */
1994   tracking_dst->objectnr = tracking_src.objectnr;
1995   const int active_track_index = BLI_findindex(&tracking_src.tracks, tracking_src.act_track);
1996   const int active_plane_track_index = BLI_findindex(&tracking_src.plane_tracks,
1997                                                      tracking_src.act_plane_track);
1998   tracking_dst->act_track = BLI_findlink(&tracking_dst->tracks, active_track_index);
1999   tracking_dst->act_plane_track = BLI_findlink(&tracking_dst->plane_tracks,
2000                                                active_plane_track_index);
2001 
2002   /* Syncs the tracking selection flag. */
2003   MovieTrackingObject *tracking_object_dst, *tracking_object_src;
2004   tracking_object_src = tracking_src.objects.first;
2005 
2006   for (tracking_object_dst = tracking_dst->objects.first; tracking_object_dst != NULL;
2007        tracking_object_dst = tracking_object_dst->next,
2008       tracking_object_src = tracking_object_src->next) {
2009     ListBase *tracksbase_dst, *tracksbase_src;
2010     tracksbase_dst = BKE_tracking_object_get_tracks(tracking_dst, tracking_object_dst);
2011     tracksbase_src = BKE_tracking_object_get_tracks(&tracking_src, tracking_object_src);
2012 
2013     MovieTrackingTrack *track_dst, *track_src;
2014     track_src = tracksbase_src->first;
2015     for (track_dst = tracksbase_dst->first; track_dst != NULL;
2016          track_dst = track_dst->next, track_src = track_src->next) {
2017       track_dst->flag = track_src->flag;
2018       track_dst->pat_flag = track_src->pat_flag;
2019       track_dst->search_flag = track_src->search_flag;
2020     }
2021   }
2022 }
2023 
2024 static void movieclip_eval_update_reload(struct Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
2025 {
2026   BKE_movieclip_reload(bmain, clip);
2027   if (DEG_is_active(depsgraph)) {
2028     MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id);
2029     BKE_movieclip_reload(bmain, clip_orig);
2030   }
2031 }
2032 
2033 static void movieclip_eval_update_generic(struct Depsgraph *depsgraph, MovieClip *clip)
2034 {
2035   BKE_tracking_dopesheet_tag_update(&clip->tracking);
2036   if (DEG_is_active(depsgraph)) {
2037     MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id);
2038     BKE_tracking_dopesheet_tag_update(&clip_orig->tracking);
2039   }
2040 }
2041 
2042 void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
2043 {
2044   DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip);
2045   if (clip->id.recalc & ID_RECALC_SOURCE) {
2046     movieclip_eval_update_reload(depsgraph, bmain, clip);
2047   }
2048   else {
2049     movieclip_eval_update_generic(depsgraph, clip);
2050   }
2051 }
2052 
2053 void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, MovieClip *clip)
2054 {
2055   DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip);
2056   movieclip_selection_sync(clip, (MovieClip *)clip->id.orig_id);
2057 }
2058 
2059 /* -------------------------------------------------------------------- */
2060 /** \name GPU textures
2061  * \{ */
2062 
2063 static GPUTexture **movieclip_get_gputexture_ptr(MovieClip *clip,
2064                                                  MovieClipUser *cuser,
2065                                                  eGPUTextureTarget textarget)
2066 {
2067   /* Check if we have an existing entry for that clip user. */
2068   MovieClip_RuntimeGPUTexture *tex;
2069   for (tex = clip->runtime.gputextures.first; tex; tex = tex->next) {
2070     if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) {
2071       break;
2072     }
2073   }
2074 
2075   /* If not, allocate a new one. */
2076   if (tex == NULL) {
2077     tex = (MovieClip_RuntimeGPUTexture *)MEM_mallocN(sizeof(MovieClip_RuntimeGPUTexture),
2078                                                      __func__);
2079 
2080     for (int i = 0; i < TEXTARGET_COUNT; i++) {
2081       tex->gputexture[i] = NULL;
2082     }
2083 
2084     memcpy(&tex->user, cuser, sizeof(MovieClipUser));
2085     BLI_addtail(&clip->runtime.gputextures, tex);
2086   }
2087 
2088   return &tex->gputexture[textarget];
2089 }
2090 
2091 GPUTexture *BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser)
2092 {
2093   if (clip == NULL) {
2094     return NULL;
2095   }
2096 
2097   GPUTexture **tex = movieclip_get_gputexture_ptr(clip, cuser, TEXTARGET_2D);
2098   if (*tex) {
2099     return *tex;
2100   }
2101 
2102   /* check if we have a valid image buffer */
2103   ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
2104   if (ibuf == NULL) {
2105     fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
2106     *tex = GPU_texture_create_error(2, false);
2107     return *tex;
2108   }
2109 
2110   /* This only means RGBA16F instead of RGBA32F. */
2111   const bool high_bitdepth = false;
2112   const bool store_premultiplied = ibuf->rect_float ? false : true;
2113   *tex = IMB_create_gpu_texture(clip->id.name + 2, ibuf, high_bitdepth, store_premultiplied);
2114 
2115   /* Do not generate mips for movieclips... too slow. */
2116   GPU_texture_mipmap_mode(*tex, false, true);
2117 
2118   IMB_freeImBuf(ibuf);
2119 
2120   return *tex;
2121 }
2122 
2123 void BKE_movieclip_free_gputexture(struct MovieClip *clip)
2124 {
2125   /* number of gpu textures to keep around as cache
2126    * We don't want to keep too many GPU textures for
2127    * movie clips around, as they can be large.*/
2128   const int MOVIECLIP_NUM_GPUTEXTURES = 1;
2129 
2130   while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) {
2131     MovieClip_RuntimeGPUTexture *tex = (MovieClip_RuntimeGPUTexture *)BLI_pophead(
2132         &clip->runtime.gputextures);
2133     for (int i = 0; i < TEXTARGET_COUNT; i++) {
2134       /* free glsl image binding */
2135       if (tex->gputexture[i]) {
2136         GPU_texture_free(tex->gputexture[i]);
2137         tex->gputexture[i] = NULL;
2138       }
2139     }
2140     MEM_freeN(tex);
2141   }
2142 }
2143 /** \} */
2144