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