Blender V5.0
movieclip.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdio>
10#include <cstring>
11#include <fcntl.h>
12#include <optional>
13
14#ifndef WIN32
15# include <unistd.h>
16#else
17# include <io.h>
18#endif
19
20#include <ctime>
21
22#include "MEM_guardedalloc.h"
23
24/* Allow using deprecated functionality for .blend file I/O. */
25#define DNA_DEPRECATED_ALLOW
26
27#include "DNA_defaults.h"
29
30#include "DNA_movieclip_types.h"
31#include "DNA_node_types.h"
32#include "DNA_scene_types.h"
33#include "DNA_space_types.h"
34
35#include "BLI_fileops.h"
36#include "BLI_listbase.h"
37#include "BLI_math_vector.h"
38#include "BLI_path_utils.hh"
39#include "BLI_string.h"
40#include "BLI_threads.h"
41#include "BLI_utildefines.h"
42
43#include "BLT_translation.hh"
44
45#include "BKE_bpath.hh"
46#include "BKE_colortools.hh"
47#include "BKE_idtype.hh"
48#include "BKE_image.hh" /* openanim */
49#include "BKE_lib_id.hh"
50#include "BKE_lib_query.hh"
51#include "BKE_library.hh"
52#include "BKE_main.hh"
53#include "BKE_movieclip.h"
55#include "BKE_tracking.h"
56
58#include "IMB_imbuf.hh"
59#include "IMB_imbuf_types.hh"
60#include "IMB_moviecache.hh"
61#include "IMB_openexr.hh"
62
63#include "MOV_read.hh"
64
65#include "DEG_depsgraph.hh"
67
68#include "DRW_engine.hh"
69
70#include "GPU_texture.hh"
71
72#include "BLO_read_write.hh"
73
74#include "CLG_log.h"
75
76static CLG_LogRef LOG = {"gpu.texture"};
77
78static void free_buffers(MovieClip *clip);
79
82{
83 /* TODO: we could store those in undo cache storage as well, and preserve them instead of
84 * re-creating them... */
86
87 clip->runtime.last_update = 0;
88}
89
100
101static void movie_clip_copy_data(Main * /*bmain*/,
102 std::optional<Library *> /*owner_library*/,
103 ID *id_dst,
104 const ID *id_src,
105 const int flag)
106{
107 MovieClip *movie_clip_dst = (MovieClip *)id_dst;
108 const MovieClip *movie_clip_src = (const MovieClip *)id_src;
109
110 /* We never handle user-count here for owned data. */
111 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
112
113 movie_clip_dst->anim = nullptr;
114 movie_clip_dst->cache = nullptr;
115
116 BKE_tracking_copy(&movie_clip_dst->tracking, &movie_clip_src->tracking, flag_subdata);
117 movie_clip_dst->tracking_context = nullptr;
118
120 &movie_clip_src->colorspace_settings);
121}
122
123static void movie_clip_free_data(ID *id)
124{
125 MovieClip *movie_clip = (MovieClip *)id;
126
127 /* Also frees animation-data. */
128 free_buffers(movie_clip);
129
130 BKE_tracking_free(&movie_clip->tracking);
131}
132
134{
135 MovieClip *movie_clip = (MovieClip *)id;
136 MovieTracking *tracking = &movie_clip->tracking;
137
139
140 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
141 LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) {
143 }
144 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &object->plane_tracks) {
146 }
147 }
148}
149
151 IDTypeForeachCacheFunctionCallback function_callback,
152 void *user_data)
153{
154 MovieClip *movie_clip = (MovieClip *)id;
155 IDCacheKey key{};
156 key.id_session_uid = id->session_uid;
157 key.identifier = offsetof(MovieClip, cache);
158 function_callback(id, &key, (void **)&movie_clip->cache, 0, user_data);
159
160 key.identifier = offsetof(MovieClip, tracking.camera.intrinsics);
161 function_callback(id, &key, (&movie_clip->tracking.camera.intrinsics), 0, user_data);
162}
163
165{
166 MovieClip *movie_clip = (MovieClip *)id;
168 bpath_data, movie_clip->filepath, sizeof(movie_clip->filepath));
169}
170
172{
173 MovieTrackingTrack *track;
174
175 track = static_cast<MovieTrackingTrack *>(tracks->first);
176 while (track) {
177 BLO_write_struct(writer, MovieTrackingTrack, track);
178
179 if (track->markers) {
181 }
182
183 track = track->next;
184 }
185}
186
187static void write_moviePlaneTracks(BlendWriter *writer, ListBase *plane_tracks_base)
188{
189 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
190 BLO_write_struct(writer, MovieTrackingPlaneTrack, plane_track);
191
192 BLO_write_pointer_array(writer, plane_track->point_tracksnr, plane_track->point_tracks);
194 writer, MovieTrackingPlaneMarker, plane_track->markersnr, plane_track->markers);
195 }
196}
197
199 MovieTrackingReconstruction *reconstruction)
200{
201 if (reconstruction->camnr) {
203 writer, MovieReconstructedCamera, reconstruction->camnr, reconstruction->cameras);
204 }
205}
206
207static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
208{
209 MovieClip *clip = (MovieClip *)id;
210
211 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
212 clip->anim = nullptr;
213 clip->tracking_context = nullptr;
214 clip->tracking.stats = nullptr;
215
216 MovieTracking *tracking = &clip->tracking;
217
218 BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
219 BKE_id_blend_write(writer, &clip->id);
220
221 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
222 BLO_write_struct(writer, MovieTrackingObject, object);
223 write_movieTracks(writer, &object->tracks);
224 write_moviePlaneTracks(writer, &object->plane_tracks);
225 write_movieReconstruction(writer, &object->reconstruction);
226 }
227}
228
230 MovieTrackingReconstruction *reconstruction)
231{
233 reader, MovieReconstructedCamera, reconstruction->camnr, &reconstruction->cameras);
234}
235
236static void direct_link_movieTracks(BlendDataReader *reader, ListBase *tracksbase)
237{
238 BLO_read_struct_list(reader, MovieTrackingTrack, tracksbase);
239
240 LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
241 BLO_read_struct_array(reader, MovieTrackingMarker, track->markersnr, &track->markers);
242 }
243}
244
245static void direct_link_moviePlaneTracks(BlendDataReader *reader, ListBase *plane_tracks_base)
246{
247 BLO_read_struct_list(reader, MovieTrackingPlaneTrack, plane_tracks_base);
248
249 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
251 reader, plane_track->point_tracksnr, (void **)&plane_track->point_tracks);
252 for (int i = 0; i < plane_track->point_tracksnr; i++) {
253 BLO_read_struct(reader, MovieTrackingTrack, &plane_track->point_tracks[i]);
254 }
255
257 reader, MovieTrackingPlaneMarker, plane_track->markersnr, &plane_track->markers);
258 }
259}
260
262{
263 MovieClip *clip = (MovieClip *)id;
264 MovieTracking *tracking = &clip->tracking;
265
266 direct_link_movieTracks(reader, &tracking->tracks_legacy);
269
272
273 clip->anim = nullptr;
274 clip->tracking_context = nullptr;
275 clip->tracking.stats = nullptr;
276
277 /* Needed for proper versioning, will be nullptr for all newer files anyway. */
279
280 clip->tracking.dopesheet.ok = 0;
283
285
286 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
287 direct_link_movieTracks(reader, &object->tracks);
288 direct_link_moviePlaneTracks(reader, &object->plane_tracks);
289 direct_link_movieReconstruction(reader, &object->reconstruction);
290
291 BLO_read_struct(reader, MovieTrackingTrack, &object->active_track);
292 BLO_read_struct(reader, MovieTrackingPlaneTrack, &object->active_plane_track);
293 }
294
296}
297
299 /*id_code*/ MovieClip::id_type,
300 /*id_filter*/ FILTER_ID_MC,
301 /*dependencies_id_types*/ FILTER_ID_GD_LEGACY | FILTER_ID_IM,
302 /*main_listbase_index*/ INDEX_ID_MC,
303 /*struct_size*/ sizeof(MovieClip),
304 /*name*/ "MovieClip",
305 /*name_plural*/ N_("movieclips"),
306 /*translation_context*/ BLT_I18NCONTEXT_ID_MOVIECLIP,
308 /*asset_type_info*/ nullptr,
309
310 /*init_data*/ movie_clip_init_data,
311 /*copy_data*/ movie_clip_copy_data,
312 /*free_data*/ movie_clip_free_data,
313 /*make_local*/ nullptr,
314 /*foreach_id*/ movie_clip_foreach_id,
315 /*foreach_cache*/ movie_clip_foreach_cache,
316 /*foreach_path*/ movie_clip_foreach_path,
317 /*foreach_working_space_color*/ nullptr,
318 /*owner_pointer_get*/ nullptr,
319
320 /*blend_write*/ movieclip_blend_write,
321 /*blend_read_data*/ movieclip_blend_read_data,
322 /*blend_read_after_liblink*/ nullptr,
323
324 /*blend_read_undo_preserve*/ nullptr,
325
326 /*lib_override_apply_post*/ nullptr,
327};
328
329/*********************** movieclip buffer loaders *************************/
330
331static int sequence_guess_offset(const char *full_name, int head_len, ushort numlen)
332{
333 char num[FILE_MAX] = {0};
334
335 BLI_strncpy(num, full_name + head_len, numlen + 1);
336
337 return atoi(num);
338}
339
340static int rendersize_to_proxy(const MovieClipUser *user, int flag)
341{
342 if ((flag & MCLIP_USE_PROXY) == 0) {
343 return IMB_PROXY_NONE;
344 }
345
346 switch (user->render_size) {
348 return IMB_PROXY_25;
349
351 return IMB_PROXY_50;
352
354 return IMB_PROXY_75;
355
357 return IMB_PROXY_100;
358
360 return IMB_PROXY_NONE;
361 }
362
363 return IMB_PROXY_NONE;
364}
365
366static int rendersize_to_number(int render_size)
367{
368 switch (render_size) {
370 return 25;
371
373 return 50;
374
376 return 75;
377
379 return 100;
380
382 return 100;
383 }
384
385 return 100;
386}
387
388static int get_timecode(MovieClip *clip, int flag)
389{
390 if ((flag & MCLIP_USE_PROXY) == 0) {
391 return IMB_TC_NONE;
392 }
393
394 return clip->proxy.tc;
395}
396
397static void get_sequence_filepath(const MovieClip *clip,
398 const int framenr,
399 char filepath[FILE_MAX])
400{
401 ushort numlen;
402 char head[FILE_MAX], tail[FILE_MAX];
403 int offset;
404
405 BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
406 BLI_path_sequence_decode(filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
407
408 /* Movie-clips always points to first image from sequence, auto-guess offset for now.
409 * Could be something smarter in the future. */
410 offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
411
412 if (numlen) {
414 FILE_MAX,
415 head,
416 tail,
417 numlen,
418 offset + framenr - clip->start_frame + clip->frame_offset);
419 }
420 else {
421 BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
422 }
423
424 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
425}
426
427/* supposed to work with sequences only */
428static void get_proxy_filepath(const MovieClip *clip,
429 int proxy_render_size,
430 bool undistorted,
431 int framenr,
432 char filepath[FILE_MAX])
433{
434 int size = rendersize_to_number(proxy_render_size);
435 char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
436 int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset;
437
438 BLI_path_split_dir_file(clip->filepath, clipdir, FILE_MAX, clipfile, FILE_MAX);
439
440 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
441 STRNCPY(dir, clip->proxy.dir);
442 }
443 else {
444 SNPRINTF(dir, "%s" SEP_STR "BL_proxy", clipdir);
445 }
446
447 if (undistorted) {
448 BLI_snprintf(filepath,
449 FILE_MAX,
450 "%s" SEP_STR "%s" SEP_STR "proxy_%d_undistorted" SEP_STR "%08d",
451 dir,
452 clipfile,
453 size,
454 proxynr);
455 }
456 else {
457 BLI_snprintf(filepath,
458 FILE_MAX,
459 "%s" SEP_STR "%s" SEP_STR "proxy_%d" SEP_STR "%08d",
460 dir,
461 clipfile,
462 size,
463 proxynr);
464 }
465
467 BLI_path_frame(filepath, FILE_MAX, 1, 0);
468 BLI_strncat(filepath, ".jpg", FILE_MAX);
469}
470
471#ifdef WITH_IMAGE_OPENEXR
472
473namespace {
474
475struct MultilayerConvertContext {
476 float *combined_pass;
477 int num_combined_channels;
478};
479
480} // namespace
481
482static void *movieclip_convert_multilayer_add_view(void * /*ctx_v*/, const char * /*view_name*/)
483{
484 return nullptr;
485}
486
487static void *movieclip_convert_multilayer_add_layer(void *ctx_v, const char * /*layer_name*/)
488{
489 /* Return dummy non-nullptr value, we don't use layer handle but need to return
490 * something, so render API invokes the add_pass() callbacks. */
491 return ctx_v;
492}
493
494static void movieclip_convert_multilayer_add_pass(void * /*layer*/,
495 void *ctx_v,
496 const char *pass_name,
497 float *rect,
498 int num_channels,
499 const char *chan_id,
500 const char * /*view_name*/)
501{
502 /* NOTE: This function must free pass pixels data if it is not used, this
503 * is how IMB_exr_multilayer_convert() is working. */
504 MultilayerConvertContext *ctx = static_cast<MultilayerConvertContext *>(ctx_v);
505 /* If we've found a first combined pass, skip all the rest ones. */
506 if (ctx->combined_pass != nullptr) {
507 MEM_freeN(rect);
508 return;
509 }
510 if (STREQ(pass_name, RE_PASSNAME_COMBINED) || STR_ELEM(chan_id, "RGBA", "RGB")) {
511 ctx->combined_pass = rect;
512 ctx->num_combined_channels = num_channels;
513 }
514 else {
515 MEM_freeN(rect);
516 }
517}
518
519#endif /* WITH_IMAGE_OPENEXR */
520
522{
523 if (ibuf == nullptr) {
524 return;
525 }
526#ifdef WITH_IMAGE_OPENEXR
527 if (ibuf->ftype != IMB_FTYPE_OPENEXR || ibuf->exrhandle == nullptr) {
528 return;
529 }
530 MultilayerConvertContext ctx;
531 ctx.combined_pass = nullptr;
532 ctx.num_combined_channels = 0;
534 &ctx,
535 movieclip_convert_multilayer_add_view,
536 movieclip_convert_multilayer_add_layer,
537 movieclip_convert_multilayer_add_pass);
538 if (ctx.combined_pass != nullptr) {
539 BLI_assert(ibuf->float_buffer.data == nullptr);
540 IMB_assign_float_buffer(ibuf, ctx.combined_pass, IB_TAKE_OWNERSHIP);
541 ibuf->channels = ctx.num_combined_channels;
542 }
544 ibuf->exrhandle = nullptr;
545#endif
546}
547
549 const MovieClipUser *user,
550 int framenr,
551 int flag)
552{
553 ImBuf *ibuf;
554 char filepath[FILE_MAX];
555 int loadflag;
556 bool use_proxy = false;
557 char *colorspace;
558
560 if (use_proxy) {
561 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
562 get_proxy_filepath(clip, user->render_size, undistort, framenr, filepath);
563
564 /* Well, this is a bit weird, but proxies for movie sources
565 * are built in the same exact color space as the input,
566 *
567 * But image sequences are built in the display space.
568 */
569 if (clip->source == MCLIP_SRC_MOVIE) {
570 colorspace = clip->colorspace_settings.name;
571 }
572 else {
573 colorspace = nullptr;
574 }
575 }
576 else {
577 get_sequence_filepath(clip, framenr, filepath);
578 colorspace = clip->colorspace_settings.name;
579 }
580
582
583 /* read ibuf */
584 ibuf = IMB_load_image_from_filepath(filepath, loadflag, colorspace);
586
587 return ibuf;
588}
589
591{
592 char filepath_abs[FILE_MAX];
593
594 if (!clip->anim) {
595 STRNCPY(filepath_abs, clip->filepath);
596 BLI_path_abs(filepath_abs, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
597
598 /* FIXME: make several stream accessible in image editor, too */
599 clip->anim = openanim(filepath_abs, IB_byte_data, 0, false, clip->colorspace_settings.name);
600
601 if (clip->anim) {
602 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
603 char dir[FILE_MAX];
604 STRNCPY(dir, clip->proxy.dir);
606 MOV_set_custom_proxy_dir(clip->anim, dir);
607 }
608 }
609 }
610}
611
613 const MovieClipUser *user,
614 int framenr,
615 int flag)
616{
617 ImBuf *ibuf = nullptr;
618 int tc = get_timecode(clip, flag);
619 int proxy = rendersize_to_proxy(user, flag);
620
622
623 if (clip->anim) {
624 int fra = framenr - clip->start_frame + clip->frame_offset;
625
626 ibuf = MOV_decode_frame(clip->anim, fra, IMB_Timecode_Type(tc), IMB_Proxy_Size(proxy));
627 }
628
629 return ibuf;
630}
631
633{
634 if (clip->source == MCLIP_SRC_MOVIE) {
636
637 if (clip->anim) {
639 }
640 }
641 else if (clip->source == MCLIP_SRC_SEQUENCE) {
642 ushort numlen;
643 char filepath[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
644
645 BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
646
647 if (numlen == 0) {
648 /* there's no number group in file name, assume it's single framed sequence */
649 clip->len = 1;
650 }
651 else {
652 clip->len = 0;
653 for (;;) {
654 get_sequence_filepath(clip, clip->len + clip->start_frame, filepath);
655
656 if (BLI_exists(filepath)) {
657 clip->len++;
658 }
659 else {
660 break;
661 }
662 }
663 }
664 }
665}
666
667/*********************** image buffer cache *************************/
668
670 /* regular movie cache */
672
673 /* cached postprocessed shot */
674 struct {
677 int flag;
678
679 /* cache for undistorted shot */
682 float polynomial_k[3];
683 float division_k[2];
684 float nuke_k[2];
685 float brown_k[4];
686 float brown_p[2];
689
690 int proxy;
693
694 /* cache for stable shot */
695 struct {
697
698 ImBuf *ibuf;
699 int framenr;
701
702 float loc[2], scale, angle, aspect;
704 short render_flag;
706
708
710};
711
717
721
722static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
723{
724 int index;
725
726 index = framenr - clip->start_frame + clip->frame_offset;
727
728 if (clip->source == MCLIP_SRC_SEQUENCE) {
729 if (clip->cache->sequence_offset == -1) {
730 ushort numlen;
731 char head[FILE_MAX], tail[FILE_MAX];
732
733 BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
734
735 /* see comment in get_sequence_filepath */
736 clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
737 }
738
739 index += clip->cache->sequence_offset;
740 }
741
742 if (index < 0) {
743 return framenr - index;
744 }
745
746 return framenr;
747}
748
749static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
750{
751 const MovieClipImBufCacheKey *key = static_cast<const MovieClipImBufCacheKey *>(userkey);
752
753 *framenr = key->framenr;
754 *proxy = key->proxy;
755 *render_flags = key->render_flag;
756}
757
758static uint moviecache_hashhash(const void *keyv)
759{
760 const MovieClipImBufCacheKey *key = static_cast<const MovieClipImBufCacheKey *>(keyv);
761 int rval = key->framenr;
762
763 return rval;
764}
765
766static bool moviecache_hashcmp(const void *av, const void *bv)
767{
768 const MovieClipImBufCacheKey *a = static_cast<const MovieClipImBufCacheKey *>(av);
769 const MovieClipImBufCacheKey *b = static_cast<const MovieClipImBufCacheKey *>(bv);
770
771 return ((a->framenr != b->framenr) || (a->proxy != b->proxy) ||
772 (a->render_flag != b->render_flag));
773}
774
775static void *moviecache_getprioritydata(void *key_v)
776{
778 MovieClipCachePriorityData *priority_data;
779
780 priority_data = MEM_callocN<MovieClipCachePriorityData>("movie cache clip priority data");
781 priority_data->framenr = key->framenr;
782
783 return priority_data;
784}
785
786static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
787{
788 MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *)last_userkey_v;
789 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
790
791 return -abs(last_userkey->framenr - priority_data->framenr);
792}
793
794static void moviecache_prioritydeleter(void *priority_data_v)
795{
796 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
797
798 MEM_freeN(priority_data);
799}
800
801static ImBuf *get_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
802{
803 if (clip->cache) {
805
806 if (!clip->cache->is_still_sequence) {
807 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
808 }
809 else {
810 key.framenr = 1;
811 }
812
813 if (flag & MCLIP_USE_PROXY) {
814 key.proxy = rendersize_to_proxy(user, flag);
815 key.render_flag = user->render_flag;
816 }
817 else {
818 key.proxy = IMB_PROXY_NONE;
819 key.render_flag = 0;
820 }
821
822 return IMB_moviecache_get(clip->cache->moviecache, &key, nullptr);
823 }
824
825 return nullptr;
826}
827
828static bool has_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
829{
830 if (clip->cache) {
832
833 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
834
835 if (flag & MCLIP_USE_PROXY) {
836 key.proxy = rendersize_to_proxy(user, flag);
837 key.render_flag = user->render_flag;
838 }
839 else {
840 key.proxy = IMB_PROXY_NONE;
841 key.render_flag = 0;
842 }
843
844 return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
845 }
846
847 return false;
848}
849
850static bool put_imbuf_cache(
851 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
852{
854
855 if (clip->cache == nullptr) {
856 MovieCache *moviecache;
857
858 // char cache_name[64];
859 // SNPRINTF(cache_name, "movie %s", clip->id.name);
860
861 clip->cache = MEM_callocN<MovieClipCache>("movieClipCache");
862
863 moviecache = IMB_moviecache_create(
865
871
872 clip->cache->moviecache = moviecache;
873 clip->cache->sequence_offset = -1;
874 if (clip->source == MCLIP_SRC_SEQUENCE) {
875 ushort numlen;
876 BLI_path_sequence_decode(clip->filepath, nullptr, 0, nullptr, 0, &numlen);
877 clip->cache->is_still_sequence = (numlen == 0);
878 }
879 }
880
881 if (!clip->cache->is_still_sequence) {
882 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
883 }
884 else {
885 key.framenr = 1;
886 }
887
888 if (flag & MCLIP_USE_PROXY) {
889 key.proxy = rendersize_to_proxy(user, flag);
890 key.render_flag = user->render_flag;
891 }
892 else {
893 key.proxy = IMB_PROXY_NONE;
894 key.render_flag = 0;
895 }
896
897 if (destructive) {
898 IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
899 return true;
900 }
901
902 return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
903}
904
905static bool moviecache_check_free_proxy(ImBuf * /*ibuf*/, void *userkey, void * /*userdata*/)
906{
908
909 return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
910}
911
912/*********************** common functions *************************/
913
914/* only image block itself */
915static MovieClip *movieclip_alloc(Main *bmain, const char *name)
916{
917 MovieClip *clip;
918
919 clip = BKE_id_new<MovieClip>(bmain, name);
920
921 return clip;
922}
923
925{
926 int width, height;
928
930 BKE_movieclip_get_size(clip, &user, &width, &height);
931
932 if (!width || !height) {
933 clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
934 }
935}
936
937static void detect_clip_source(Main *bmain, MovieClip *clip)
938{
939 ImBuf *ibuf;
940 char filepath[FILE_MAX];
941
942 STRNCPY(filepath, clip->filepath);
943 BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &clip->id));
944
946 if (ibuf) {
948 IMB_freeImBuf(ibuf);
949 }
950 else {
951 clip->source = MCLIP_SRC_MOVIE;
952 }
953}
954
955MovieClip *BKE_movieclip_file_add(Main *bmain, const char *filepath)
956{
957 MovieClip *clip;
958 int file;
959 char filepath_abs[FILE_MAX];
960
961 STRNCPY(filepath_abs, filepath);
962 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
963
964 /* exists? */
965 file = BLI_open(filepath_abs, O_BINARY | O_RDONLY, 0);
966 if (file == -1) {
967 return nullptr;
968 }
969 close(file);
970
971 /* ** add new movieclip ** */
972
973 /* create a short library name */
974 clip = movieclip_alloc(bmain, BLI_path_basename(filepath));
975 STRNCPY(clip->filepath, filepath);
976
977 detect_clip_source(bmain, clip);
978
980 if (clip->lastsize[0]) {
981 int width = clip->lastsize[0];
982
983 clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
984 }
985
987
988 return clip;
989}
990
991MovieClip *BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
992{
993 MovieClip *clip;
994 char filepath_abs[FILE_MAX], filepath_test[FILE_MAX];
995
996 STRNCPY(filepath_abs, filepath);
997 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
998
999 /* first search an identical filepath */
1000 for (clip = static_cast<MovieClip *>(bmain->movieclips.first); clip;
1001 clip = static_cast<MovieClip *>(clip->id.next))
1002 {
1003 STRNCPY(filepath_test, clip->filepath);
1004 BLI_path_abs(filepath_test, ID_BLEND_PATH(bmain, &clip->id));
1005
1006 if (BLI_path_cmp(filepath_test, filepath_abs) == 0) {
1007 id_us_plus(&clip->id); /* officially should not, it doesn't link here! */
1008 if (r_exists) {
1009 *r_exists = true;
1010 }
1011 return clip;
1012 }
1013 }
1014
1015 if (r_exists) {
1016 *r_exists = false;
1017 }
1018 return BKE_movieclip_file_add(bmain, filepath);
1019}
1020
1021MovieClip *BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
1022{
1023 return BKE_movieclip_file_add_exists_ex(bmain, filepath, nullptr);
1024}
1025
1026static void real_ibuf_size(
1027 const MovieClip *clip, const MovieClipUser *user, const ImBuf *ibuf, int *width, int *height)
1028{
1029 *width = ibuf->x;
1030 *height = ibuf->y;
1031
1032 if (clip->flag & MCLIP_USE_PROXY) {
1033 switch (user->render_size) {
1035 (*width) *= 4;
1036 (*height) *= 4;
1037 break;
1038
1040 (*width) *= 2.0f;
1041 (*height) *= 2.0f;
1042 break;
1043
1045 *width = float(*width) * 4.0f / 3.0f;
1046 *height = float(*height) * 4.0f / 3.0f;
1047 break;
1048 }
1049 }
1050}
1051
1053{
1054 ImBuf *undistibuf;
1055
1056 if (distortion) {
1057 undistibuf = BKE_tracking_distortion_exec(
1058 distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, true);
1059 }
1060 else {
1061 undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
1062 }
1063
1064 IMB_scale(undistibuf, ibuf->x, ibuf->y, IMBScaleFilter::Box, false);
1065
1066 return undistibuf;
1067}
1068
1069static bool need_undistortion_postprocess(const MovieClipUser *user, int clip_flag)
1070{
1071 bool result = false;
1072 const bool uses_full_frame = ((clip_flag & MCLIP_USE_PROXY) == 0) ||
1074 /* Only full undistorted render can be used as on-fly undistorting image. */
1075 result |= uses_full_frame && (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
1076 return result;
1077}
1078
1080 int clip_flag,
1081 int postprocess_flag)
1082{
1083 bool result = (postprocess_flag != 0);
1084 result |= need_undistortion_postprocess(user, clip_flag);
1085 return result;
1086}
1087
1089{
1090 const MovieClipCache *cache = clip->cache;
1091 const MovieTrackingCamera *camera = &clip->tracking.camera;
1092
1093 if (camera->focal != cache->postprocessed.focal_length) {
1094 return false;
1095 }
1096
1097 /* check for distortion model changes */
1099 return false;
1100 }
1101
1102 if (camera->distortion_model != cache->postprocessed.distortion_model) {
1103 return false;
1104 }
1105
1106 if (!equals_v3v3(&camera->k1, cache->postprocessed.polynomial_k)) {
1107 return false;
1108 }
1109
1110 if (!equals_v2v2(&camera->division_k1, cache->postprocessed.division_k)) {
1111 return false;
1112 }
1113
1114 if (!equals_v2v2(&camera->nuke_k1, cache->postprocessed.nuke_k)) {
1115 return false;
1116 }
1117
1118 if (!equals_v4v4(&camera->brown_k1, cache->postprocessed.brown_k)) {
1119 return false;
1120 }
1121 if (!equals_v2v2(&camera->brown_p1, cache->postprocessed.brown_p)) {
1122 return false;
1123 }
1124
1125 return true;
1126}
1127
1129 const MovieClipUser *user,
1130 int flag,
1131 int postprocess_flag)
1132{
1133 const MovieClipCache *cache = clip->cache;
1134 int framenr = user->framenr;
1135 short proxy = IMB_PROXY_NONE;
1136 int render_flag = 0;
1137
1138 if (flag & MCLIP_USE_PROXY) {
1139 proxy = rendersize_to_proxy(user, flag);
1140 render_flag = user->render_flag;
1141 }
1142
1143 /* no cache or no cached postprocessed image */
1144 if (!clip->cache || !clip->cache->postprocessed.ibuf) {
1145 return nullptr;
1146 }
1147
1148 /* Postprocessing happened for other frame. */
1149 if (cache->postprocessed.framenr != framenr) {
1150 return nullptr;
1151 }
1152
1153 /* cached ibuf used different proxy settings */
1154 if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy) {
1155 return nullptr;
1156 }
1157
1158 if (cache->postprocessed.flag != postprocess_flag) {
1159 return nullptr;
1160 }
1161
1163 if (!check_undistortion_cache_flags(clip)) {
1164 return nullptr;
1165 }
1166 }
1167 else if (cache->postprocessed.undistortion_used) {
1168 return nullptr;
1169 }
1170
1172
1173 return cache->postprocessed.ibuf;
1174}
1175
1177 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1178{
1179 ImBuf *postproc_ibuf = nullptr;
1180
1182 postproc_ibuf = get_undistorted_ibuf(clip, nullptr, ibuf);
1183 }
1184 else {
1185 postproc_ibuf = IMB_dupImBuf(ibuf);
1186 }
1187
1188 if (postprocess_flag) {
1189 bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
1190 bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
1191 bool disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
1192 bool grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
1193
1194 if (disable_red || disable_green || disable_blue || grayscale) {
1195 BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, true);
1196 }
1197 }
1198
1199 return postproc_ibuf;
1200}
1201
1203 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1204{
1205 MovieClipCache *cache = clip->cache;
1206 MovieTrackingCamera *camera = &clip->tracking.camera;
1207
1208 cache->postprocessed.framenr = user->framenr;
1209 cache->postprocessed.flag = postprocess_flag;
1210
1211 if (flag & MCLIP_USE_PROXY) {
1213 cache->postprocessed.render_flag = user->render_flag;
1214 }
1215 else {
1217 cache->postprocessed.render_flag = 0;
1218 }
1219
1222 cache->postprocessed.focal_length = camera->focal;
1224 copy_v3_v3(cache->postprocessed.polynomial_k, &camera->k1);
1226 copy_v2_v2(cache->postprocessed.nuke_k, &camera->nuke_k1);
1227 copy_v4_v4(cache->postprocessed.brown_k, &camera->brown_k1);
1228 copy_v2_v2(cache->postprocessed.brown_p, &camera->brown_p1);
1229 cache->postprocessed.undistortion_used = true;
1230 }
1231 else {
1232 cache->postprocessed.undistortion_used = false;
1233 }
1234
1235 IMB_refImBuf(ibuf);
1236
1237 if (cache->postprocessed.ibuf) {
1239 }
1240
1241 cache->postprocessed.ibuf = ibuf;
1242}
1243
1245 MovieClip *clip, const MovieClipUser *user, int flag, int postprocess_flag, int cache_flag)
1246{
1247 ImBuf *ibuf = nullptr;
1248 int framenr = user->framenr;
1249 bool need_postprocess = false;
1250
1251 /* cache isn't threadsafe itself and also loading of movies
1252 * can't happen from concurrent threads that's why we use lock here */
1254
1255 /* try to obtain cached postprocessed frame first */
1256 if (need_postprocessed_frame(user, flag, postprocess_flag)) {
1257 ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
1258
1259 if (!ibuf) {
1260 need_postprocess = true;
1261 }
1262 }
1263
1264 if (!ibuf) {
1265 ibuf = get_imbuf_cache(clip, user, flag);
1266 }
1267
1268 if (!ibuf) {
1269 bool use_sequence = false;
1270
1271 /* undistorted proxies for movies should be read as image sequence */
1272 use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
1274
1275 if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
1276 ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
1277 }
1278 else {
1279 ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
1280 }
1281
1282 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1283 put_imbuf_cache(clip, user, ibuf, flag, true);
1284 }
1285 }
1286
1287 if (ibuf) {
1288 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
1289
1290 /* Post-process frame and put to cache if needed. */
1291 if (need_postprocess) {
1292 ImBuf *tmpibuf = ibuf;
1293 ibuf = postprocess_frame(clip, user, tmpibuf, flag, postprocess_flag);
1294 IMB_freeImBuf(tmpibuf);
1295 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1296 put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
1297 }
1298 }
1299 }
1300
1302
1303 /* Fallback render in case proxies are not enabled or built */
1306 {
1307 MovieClipUser user_fallback = *user;
1309
1311 clip, &user_fallback, flag, postprocess_flag, cache_flag);
1312 }
1313
1314 return ibuf;
1315}
1316
1318{
1319 return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
1320}
1321
1323 const MovieClipUser *user,
1324 const int flag,
1325 const int cache_flag)
1326{
1327 return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
1328}
1329
1331 const MovieClipUser *user,
1332 const int postprocess_flag)
1333{
1334 return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
1335}
1336
1338 const MovieClipUser *user,
1339 ImBuf *reference_ibuf,
1340 const int framenr,
1341 const int postprocess_flag)
1342{
1343 MovieClipCache *cache = clip->cache;
1344 MovieTracking *tracking = &clip->tracking;
1345 ImBuf *stableibuf;
1346 float tloc[2], tscale, tangle;
1347 short proxy = IMB_PROXY_NONE;
1348 int render_flag = 0;
1349 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1350
1351 if (clip->flag & MCLIP_USE_PROXY) {
1352 proxy = rendersize_to_proxy(user, clip->flag);
1353 render_flag = user->render_flag;
1354 }
1355
1356 /* there's no cached frame or it was calculated for another frame */
1357 if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr) {
1358 return nullptr;
1359 }
1360
1361 if (cache->stabilized.reference_ibuf != reference_ibuf) {
1362 return nullptr;
1363 }
1364
1365 /* cached ibuf used different proxy settings */
1366 if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy) {
1367 return nullptr;
1368 }
1369
1370 if (cache->stabilized.postprocess_flag != postprocess_flag) {
1371 return nullptr;
1372 }
1373
1374 /* stabilization also depends on pixel aspect ratio */
1375 if (cache->stabilized.aspect != tracking->camera.pixel_aspect) {
1376 return nullptr;
1377 }
1378
1379 if (cache->stabilized.filter != tracking->stabilization.filter) {
1380 return nullptr;
1381 }
1382
1383 stableibuf = cache->stabilized.ibuf;
1384
1386 clip, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
1387
1388 /* check for stabilization parameters */
1389 if (tscale != cache->stabilized.scale || tangle != cache->stabilized.angle ||
1390 !equals_v2v2(tloc, cache->stabilized.loc))
1391 {
1392 return nullptr;
1393 }
1394
1395 IMB_refImBuf(stableibuf);
1396
1397 return stableibuf;
1398}
1399
1401 const MovieClipUser *user,
1402 ImBuf *ibuf,
1403 const int framenr,
1404 const int postprocess_flag)
1405{
1406 MovieClipCache *cache = clip->cache;
1407 MovieTracking *tracking = &clip->tracking;
1408 ImBuf *stableibuf;
1409 float tloc[2], tscale, tangle;
1410 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1411
1412 stableibuf = BKE_tracking_stabilize_frame(clip, clip_framenr, ibuf, tloc, &tscale, &tangle);
1413
1414 copy_v2_v2(cache->stabilized.loc, tloc);
1415
1416 cache->stabilized.reference_ibuf = ibuf;
1417 cache->stabilized.scale = tscale;
1418 cache->stabilized.angle = tangle;
1419 cache->stabilized.framenr = framenr;
1420 cache->stabilized.aspect = tracking->camera.pixel_aspect;
1421 cache->stabilized.filter = tracking->stabilization.filter;
1422
1423 if (clip->flag & MCLIP_USE_PROXY) {
1424 cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
1425 cache->stabilized.render_flag = user->render_flag;
1426 }
1427 else {
1429 cache->stabilized.render_flag = 0;
1430 }
1431
1432 cache->stabilized.postprocess_flag = postprocess_flag;
1433
1434 if (cache->stabilized.ibuf) {
1436 }
1437
1438 cache->stabilized.ibuf = stableibuf;
1439
1440 IMB_refImBuf(stableibuf);
1441
1442 return stableibuf;
1443}
1444
1446 const MovieClipUser *user,
1447 const int postprocess_flag,
1448 float r_loc[2],
1449 float *r_scale,
1450 float *r_angle)
1451{
1452 ImBuf *ibuf, *stableibuf = nullptr;
1453 int framenr = user->framenr;
1454
1455 ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
1456
1457 if (!ibuf) {
1458 return nullptr;
1459 }
1460
1462 MovieClipCache *cache = clip->cache;
1463
1464 stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
1465
1466 if (!stableibuf) {
1467 stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
1468 }
1469
1470 if (r_loc) {
1471 copy_v2_v2(r_loc, cache->stabilized.loc);
1472 }
1473
1474 if (r_scale) {
1475 *r_scale = cache->stabilized.scale;
1476 }
1477
1478 if (r_angle) {
1479 *r_angle = cache->stabilized.angle;
1480 }
1481 }
1482 else {
1483 if (r_loc) {
1484 zero_v2(r_loc);
1485 }
1486
1487 if (r_scale) {
1488 *r_scale = 1.0f;
1489 }
1490
1491 if (r_angle) {
1492 *r_angle = 0.0f;
1493 }
1494
1495 stableibuf = ibuf;
1496 }
1497
1498 if (stableibuf != ibuf) {
1499 IMB_freeImBuf(ibuf);
1500 ibuf = stableibuf;
1501 }
1502
1503 return ibuf;
1504}
1505
1507{
1508 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1509
1510 if (ibuf) {
1511 IMB_freeImBuf(ibuf);
1512 return true;
1513 }
1514
1515 return false;
1516}
1517
1519 const MovieClipUser *user,
1520 int *r_width,
1521 int *r_height)
1522{
1523 /* TODO(sergey): Support reading sequences of different resolution. */
1524 if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
1525 *r_width = clip->lastsize[0];
1526 *r_height = clip->lastsize[1];
1527 }
1528 else {
1529 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1530
1531 if (ibuf && ibuf->x && ibuf->y) {
1532 real_ibuf_size(clip, user, ibuf, r_width, r_height);
1533 }
1534 else {
1535 *r_width = clip->lastsize[0];
1536 *r_height = clip->lastsize[1];
1537 }
1538
1539 if (ibuf) {
1540 IMB_freeImBuf(ibuf);
1541 }
1542 }
1543}
1544void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
1545{
1546 int width, height;
1547 BKE_movieclip_get_size(clip, user, &width, &height);
1548
1549 r_size[0] = float(width);
1550 r_size[1] = float(height);
1551}
1552
1554{
1555 if (!clip->len) {
1557 }
1558
1559 return clip->len;
1560}
1561
1563{
1564 if (clip->source != MCLIP_SRC_MOVIE) {
1565 return 0.0f;
1566 }
1568 if (clip->anim == nullptr) {
1569 return 0.0f;
1570 }
1571 return MOV_get_fps(clip->anim);
1572}
1573
1574void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
1575{
1576 *aspx = 1.0;
1577
1578 /* x is always 1 */
1579 *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
1580}
1581
1583 const MovieClipUser *user,
1584 int *r_totseg,
1585 int **r_points)
1586{
1587 *r_totseg = 0;
1588 *r_points = nullptr;
1589
1590 if (clip->cache) {
1591 int proxy = rendersize_to_proxy(user, clip->flag);
1592
1595 clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
1597 }
1598}
1599
1601{
1602 /* TODO: clamp framenr here? */
1603
1604 user->framenr = framenr;
1605}
1606
1607static void free_buffers(MovieClip *clip)
1608{
1609 if (clip->cache) {
1611
1612 if (clip->cache->postprocessed.ibuf) {
1614 }
1615
1616 if (clip->cache->stabilized.ibuf) {
1618 }
1619
1620 MEM_freeN(clip->cache);
1621 clip->cache = nullptr;
1622 }
1623
1624 if (clip->anim) {
1625 MOV_close(clip->anim);
1626 clip->anim = nullptr;
1627 }
1628
1630 for (tex = static_cast<MovieClip_RuntimeGPUTexture *>(clip->runtime.gputextures.first); tex;
1631 tex = static_cast<MovieClip_RuntimeGPUTexture *>(tex->next))
1632 {
1633 for (int i = 0; i < TEXTARGET_COUNT; i++) {
1634 if (tex->gputexture[i] != nullptr) {
1636 tex->gputexture[i] = nullptr;
1637 }
1638 }
1639 }
1641}
1642
1644{
1645 free_buffers(clip);
1646}
1647
1649{
1650 if (clip->cache && clip->cache->moviecache) {
1652 }
1653}
1654
1656{
1657 /* clear cache */
1658 free_buffers(clip);
1659
1660 /* update clip source */
1661 detect_clip_source(bmain, clip);
1662
1663 /* Tag for re-calculation of the actual size. */
1664 clip->lastsize[0] = clip->lastsize[1] = 0;
1665
1668
1669 BKE_ntree_update_tag_id_changed(bmain, &clip->id);
1670}
1671
1673 const MovieClipUser *user,
1674 MovieClipScopes *scopes)
1675{
1676 if (scopes->ok) {
1677 return;
1678 }
1679
1680 if (scopes->track_preview) {
1682 scopes->track_preview = nullptr;
1683 }
1684
1685 if (scopes->track_search) {
1686 IMB_freeImBuf(scopes->track_search);
1687 scopes->track_search = nullptr;
1688 }
1689
1690 scopes->marker = nullptr;
1691 scopes->track = nullptr;
1692 scopes->track_locked = true;
1693
1694 scopes->scene_framenr = user->framenr;
1695 scopes->ok = true;
1696
1697 if (clip == nullptr) {
1698 return;
1699 }
1700
1701 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
1702 MovieTrackingTrack *track = tracking_object->active_track;
1703 if (track == nullptr) {
1704 return;
1705 }
1706
1707 const int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1708 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1709
1710 scopes->marker = marker;
1711 scopes->track = track;
1712
1713 if (marker->flag & MARKER_DISABLED) {
1714 scopes->track_disabled = true;
1715 }
1716 else {
1717 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1718
1719 scopes->track_disabled = false;
1720
1721 if (ibuf && (ibuf->byte_buffer.data || ibuf->float_buffer.data)) {
1722 MovieTrackingMarker undist_marker = *marker;
1723
1725 int width, height;
1726 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1727
1728 BKE_movieclip_get_size(clip, user, &width, &height);
1729
1730 undist_marker.pos[0] *= width;
1731 undist_marker.pos[1] *= height * aspy;
1732
1734 &clip->tracking, width, height, undist_marker.pos, undist_marker.pos);
1735
1736 undist_marker.pos[0] /= width;
1737 undist_marker.pos[1] /= height * aspy;
1738 }
1739
1741 ibuf, track, &undist_marker, true, true);
1742
1743 scopes->undist_marker = undist_marker;
1744
1745 scopes->frame_width = ibuf->x;
1746 scopes->frame_height = ibuf->y;
1747
1748 scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
1749 }
1750
1751 IMB_freeImBuf(ibuf);
1752 }
1753
1754 if ((track->flag & TRACK_LOCKED) == 0) {
1755 float pat_min[2], pat_max[2];
1756
1757 scopes->track_locked = false;
1758
1759 /* XXX: would work fine with non-transformed patterns, but would likely fail
1760 * with transformed patterns, but that would be easier to debug when
1761 * we'll have real pattern sampling (at least to test) */
1762 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1763
1764 scopes->slide_scale[0] = pat_max[0] - pat_min[0];
1765 scopes->slide_scale[1] = pat_max[1] - pat_min[1];
1766 }
1767}
1768
1770 const ImBuf *ibuf,
1771 int cfra,
1772 int proxy_render_size,
1773 bool undistorted,
1774 bool threaded)
1775{
1776 char filepath[FILE_MAX];
1777 int quality, rectx, recty;
1778 int size = rendersize_to_number(proxy_render_size);
1779
1780 get_proxy_filepath(clip, proxy_render_size, undistorted, cfra, filepath);
1781
1782 rectx = ibuf->x * size / 100.0f;
1783 recty = ibuf->y * size / 100.0f;
1784
1785 ImBuf *scaleibuf = IMB_scale_into_new(ibuf, rectx, recty, IMBScaleFilter::Bilinear, threaded);
1786
1787 quality = clip->proxy.quality;
1788 scaleibuf->ftype = IMB_FTYPE_JPG;
1789 scaleibuf->foptions.quality = quality;
1790 /* unsupported feature only confuses other s/w */
1791 if (scaleibuf->planes == 32) {
1792 scaleibuf->planes = 24;
1793 }
1794
1795 /* TODO: currently the most weak part of multi-threaded proxies,
1796 * could be solved in a way that thread only prepares memory
1797 * buffer and write to disk happens separately
1798 */
1800
1802 if (IMB_save_image(scaleibuf, filepath, IB_byte_data) == 0) {
1803 perror(filepath);
1804 }
1805
1807
1808 IMB_freeImBuf(scaleibuf);
1809}
1810
1812 int clip_flag,
1813 MovieDistortion *distortion,
1814 int cfra,
1815 const int *build_sizes,
1816 int build_count,
1817 bool undistorted)
1818{
1819 ImBuf *ibuf;
1820 MovieClipUser user;
1821
1822 if (!build_count) {
1823 return;
1824 }
1825
1826 user.framenr = cfra;
1827 user.render_flag = 0;
1829
1830 ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1831
1832 if (ibuf) {
1833 ImBuf *tmpibuf = ibuf;
1834 int i;
1835
1836 if (undistorted) {
1837 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1838 }
1839
1840 for (i = 0; i < build_count; i++) {
1841 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
1842 }
1843
1844 IMB_freeImBuf(ibuf);
1845
1846 if (tmpibuf != ibuf) {
1847 IMB_freeImBuf(tmpibuf);
1848 }
1849 }
1850}
1851
1853 ImBuf *ibuf,
1854 MovieDistortion *distortion,
1855 int cfra,
1856 const int *build_sizes,
1857 int build_count,
1858 bool undistorted)
1859{
1860 if (!build_count) {
1861 return;
1862 }
1863
1864 if (ibuf) {
1865 ImBuf *tmpibuf = ibuf;
1866 int i;
1867
1868 if (undistorted) {
1869 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1870 }
1871
1872 for (i = 0; i < build_count; i++) {
1873 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
1874 }
1875
1876 if (tmpibuf != ibuf) {
1877 IMB_freeImBuf(tmpibuf);
1878 }
1879 }
1880}
1881
1883{
1884 return clip->flag & MCLIP_USE_PROXY;
1885}
1886
1887float BKE_movieclip_remap_scene_to_clip_frame(const MovieClip *clip, const float framenr)
1888{
1889 return framenr - float(clip->start_frame) + 1.0f;
1890}
1891
1892float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, const float framenr)
1893{
1894 return framenr + float(clip->start_frame) - 1.0f;
1895}
1896
1897void BKE_movieclip_filepath_for_frame(MovieClip *clip, const MovieClipUser *user, char *filepath)
1898{
1899 if (clip->source == MCLIP_SRC_SEQUENCE) {
1900 int use_proxy;
1901
1902 use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
1904
1905 if (use_proxy) {
1906 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1907 get_proxy_filepath(clip, user->render_size, undistort, user->framenr, filepath);
1908 }
1909 else {
1910 get_sequence_filepath(clip, user->framenr, filepath);
1911 }
1912 }
1913 else {
1914 BLI_strncpy(filepath, clip->filepath, FILE_MAX);
1915 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
1916 }
1917}
1918
1920{
1921 ImBuf *ibuf = nullptr;
1922
1923 if (clip->source == MCLIP_SRC_MOVIE) {
1924 ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
1925 }
1926
1927 return ibuf;
1928}
1929
1931{
1932 bool has_frame = false;
1933
1935 has_frame = has_imbuf_cache(clip, user, clip->flag);
1937
1938 return has_frame;
1939}
1940
1942{
1943 bool result;
1944
1946 result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
1948
1949 return result;
1950}
1951
1952static void movieclip_eval_update_reload(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
1953{
1954 BKE_movieclip_reload(bmain, clip);
1955 if (DEG_is_active(depsgraph)) {
1956 MovieClip *clip_orig = DEG_get_original(clip);
1957 BKE_movieclip_reload(bmain, clip_orig);
1958 }
1959}
1960
1962{
1964 if (DEG_is_active(depsgraph)) {
1965 MovieClip *clip_orig = DEG_get_original(clip);
1967 }
1968}
1969
1970void BKE_movieclip_eval_update(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
1971{
1972 DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip);
1973 if (clip->id.recalc & ID_RECALC_SOURCE) {
1975 }
1976 else {
1978 }
1980}
1981
1982/* -------------------------------------------------------------------- */
1985
1987 MovieClipUser *cuser,
1988 eGPUTextureTarget textarget)
1989{
1990 /* Check if we have an existing entry for that clip user. */
1992 for (tex = static_cast<MovieClip_RuntimeGPUTexture *>(clip->runtime.gputextures.first); tex;
1993 tex = static_cast<MovieClip_RuntimeGPUTexture *>(tex->next))
1994 {
1995 if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) {
1996 break;
1997 }
1998 }
1999
2000 /* If not, allocate a new one. */
2001 if (tex == nullptr) {
2003
2004 for (int i = 0; i < TEXTARGET_COUNT; i++) {
2005 tex->gputexture[i] = nullptr;
2006 }
2007
2008 memcpy(&tex->user, cuser, sizeof(MovieClipUser));
2009 BLI_addtail(&clip->runtime.gputextures, tex);
2010 }
2011
2012 return &tex->gputexture[textarget];
2013}
2014
2016{
2017 if (clip == nullptr) {
2018 return nullptr;
2019 }
2020
2022 if (*tex) {
2023 return *tex;
2024 }
2025
2026 /* check if we have a valid image buffer */
2027 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
2028 if (ibuf == nullptr) {
2029 CLOG_ERROR(&LOG, "Failed to create GPU texture from Blender movie clip");
2030 *tex = GPU_texture_create_error(2, false);
2031 return *tex;
2032 }
2033
2034 /* This only means RGBA16F instead of RGBA32F. */
2035 const bool high_bitdepth = false;
2036 const bool store_premultiplied = ibuf->float_buffer.data ? false : true;
2037 *tex = IMB_create_gpu_texture(clip->id.name + 2, ibuf, high_bitdepth, store_premultiplied);
2038
2039 /* Do not generate mips for movieclips... too slow. */
2040 GPU_texture_mipmap_mode(*tex, false, true);
2041
2042 IMB_freeImBuf(ibuf);
2043
2044 return *tex;
2045}
2046
2048{
2049 /* Number of gpu textures to keep around as cache.
2050 * We don't want to keep too many GPU textures for
2051 * movie clips around, as they can be large. */
2052 const int MOVIECLIP_NUM_GPUTEXTURES = 1;
2053
2054 while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) {
2056 &clip->runtime.gputextures);
2057 for (int i = 0; i < TEXTARGET_COUNT; i++) {
2058 /* Free GLSL image binding. */
2059 if (tex->gputexture[i]) {
2061 tex->gputexture[i] = nullptr;
2062 }
2063 }
2064 MEM_freeN(tex);
2065 }
2066}
2067
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:125
void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings)
void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, const ColorManagedColorspaceSettings *settings)
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:47
IDTypeInfo IDType_ID_MC
Definition movieclip.cc:298
MovieReader * openanim(const char *filepath, int ibuf_flags, int streamindex, bool keep_original_colorspace, char colorspace[IMA_MAX_SPACE])
void id_us_plus(ID *id)
Definition lib_id.cc:358
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2631
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
#define MOVIECLIP_CACHE_SKIP
#define MOVIECLIP_PREVIEW_GRAYSCALE
#define MOVIECLIP_DISABLE_BLUE
#define MOVIECLIP_DISABLE_RED
#define MOVIECLIP_DISABLE_GREEN
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
void BKE_tracking_settings_init(struct MovieTracking *tracking)
Definition tracking.cc:330
void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
Definition tracking.cc:2903
struct ImBuf * BKE_tracking_stabilize_frame(struct MovieClip *clip, int framenr, struct ImBuf *ibuf, float translation[2], float *scale, float *angle)
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
struct ImBuf * BKE_tracking_undistort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, int calibration_width, int calibration_height, float overscan)
Definition tracking.cc:2465
void BKE_tracking_free(struct MovieTracking *tracking)
Definition tracking.cc:161
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking)
Definition tracking.cc:3439
void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src, int flag)
struct ImBuf * BKE_tracking_distortion_exec(struct MovieDistortion *distortion, struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan, bool undistort)
Definition tracking.cc:2318
void BKE_tracking_stabilization_data_get(struct MovieClip *clip, int framenr, int width, int height, float translation[2], float *scale, float *angle)
struct ImBuf * BKE_tracking_get_search_imbuf(const struct ImBuf *ibuf, const struct MovieTrackingTrack *track, const struct MovieTrackingMarker *marker, bool anchored, bool disable_channels)
void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker, float min[2], float max[2])
void BKE_tracking_undistort_v2(struct MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
Definition tracking.cc:2442
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:360
#define O_BINARY
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
Definition fileops_c.cc:452
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:252
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool equals_v4v4(const float v1[4], const float v2[4]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
ATTR_WARN_UNUSED_RESULT const size_t num
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
void BLI_path_split_dir_file(const char *filepath, char *dir, size_t dir_maxncpy, char *file, size_t file_maxncpy) ATTR_NONNULL(1
int BLI_path_sequence_decode(const char *path, char *head, size_t head_maxncpy, char *tail, size_t tail_maxncpy, unsigned short *r_digits_len)
Definition path_utils.cc:58
bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits) ATTR_NONNULL(1)
#define BLI_path_cmp
void BLI_path_sequence_encode(char *path, size_t path_maxncpy, const char *head, const char *tail, unsigned short numlen, int pic)
#define STR_ELEM(...)
Definition BLI_string.h:661
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:604
char char size_t char * BLI_strncat(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
unsigned short ushort
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_thread_lock(int type)
Definition threads.cc:328
@ LOCK_MOVIECLIP
Definition BLI_threads.h:68
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Definition readfile.cc:5880
#define BLT_I18NCONTEXT_ID_MOVIECLIP
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
uint64_t DEG_get_update_count(const Depsgraph *depsgraph)
Definition depsgraph.cc:355
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
T * DEG_get_original(T *id)
#define FILTER_ID_GD_LEGACY
Definition DNA_ID.h:1202
#define FILTER_ID_MC
Definition DNA_ID.h:1210
@ ID_RECALC_SOURCE
Definition DNA_ID.h:1143
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition DNA_ID.h:688
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:685
@ INDEX_ID_MC
Definition DNA_ID.h:1308
#define FILTER_ID_IM
Definition DNA_ID.h:1204
#define DNA_struct_default_get(struct_name)
eGPUTextureTarget
@ TEXTARGET_2D
@ TEXTARGET_COUNT
@ MCLIP_USE_PROXY_CUSTOM_DIR
@ MCLIP_USE_PROXY
@ MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER
@ MCLIP_PROXY_RENDER_UNDISTORT
@ MCLIP_PROXY_RENDER_SIZE_75
@ MCLIP_PROXY_RENDER_SIZE_100
@ MCLIP_PROXY_RENDER_SIZE_50
@ MCLIP_PROXY_RENDER_SIZE_FULL
@ MCLIP_PROXY_RENDER_SIZE_25
@ MCLIP_SRC_SEQUENCE
@ MCLIP_SRC_MOVIE
#define RE_PASSNAME_COMBINED
#define IMG_SIZE_FALLBACK
@ TRACK_PREVIEW_ALPHA
@ TRACK_LOCKED
@ TRACKING_2D_STABILIZATION
@ MARKER_DISABLED
void GPU_texture_mipmap_mode(blender::gpu::Texture *texture, bool use_mipmap, bool use_filter)
blender::gpu::Texture * GPU_texture_create_error(int dimension, bool array)
void GPU_texture_free(blender::gpu::Texture *texture)
ImBuf * IMB_load_image_from_filepath(const char *filepath, const int flags, char r_colorspace[IM_MAX_SPACE]=nullptr)
Definition readimage.cc:189
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
blender::gpu::Texture * IMB_create_gpu_texture(const char *name, ImBuf *ibuf, bool use_high_bitdepth, bool use_premult)
Definition util_gpu.cc:327
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
void IMB_freeImBuf(ImBuf *ibuf)
void IMB_refImBuf(ImBuf *ibuf)
ImBuf * IMB_scale_into_new(const ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:489
bool IMB_save_image(ImBuf *ibuf, const char *filepath, const int flags)
Definition writeimage.cc:23
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:465
@ IMB_FTYPE_JPG
@ IMB_FTYPE_OPENEXR
IMB_Proxy_Size
@ IMB_PROXY_100
@ IMB_PROXY_75
@ IMB_PROXY_50
@ IMB_PROXY_25
@ IMB_PROXY_NONE
@ IB_TAKE_OWNERSHIP
@ IB_byte_data
@ IB_metadata
@ IB_multilayer
@ IB_alphamode_detect
@ IB_test
bool IMB_moviecache_put_if_possible(MovieCache *cache, void *userkey, ImBuf *ibuf)
void IMB_moviecache_free(MovieCache *cache)
bool IMB_moviecache_has_frame(MovieCache *cache, void *userkey)
void IMB_moviecache_cleanup(MovieCache *cache, bool(cleanup_check_cb)(ImBuf *ibuf, void *userkey, void *userdata), void *userdata)
ImBuf * IMB_moviecache_get(MovieCache *cache, void *userkey, bool *r_is_cached_empty)
void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
void IMB_moviecache_set_getdata_callback(MovieCache *cache, MovieCacheGetKeyDataFP getdatafp)
void IMB_moviecache_set_priority_callback(MovieCache *cache, MovieCacheGetPriorityDataFP getprioritydatafp, MovieCacheGetItemPriorityFP getitempriorityfp, MovieCachePriorityDeleterFP prioritydeleterfp)
void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_flags, int *r_totseg, int **r_points)
MovieCache * IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp)
void IMB_exr_close(ExrHandle *handle)
void IMB_exr_multilayer_convert(ExrHandle *handle, void *base, void *(*addview)(void *base, const char *str), void *(*addlayer)(void *base, const char *str), void(*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view))
Read Guarded memory(de)allocation.
IMB_Timecode_Type
Definition MOV_enums.hh:44
@ IMB_TC_NONE
Definition MOV_enums.hh:46
BMesh const char void * data
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
#define offsetof(t, d)
#define abs
#define LOG(level)
Definition log.h:97
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void MOV_set_custom_proxy_dir(MovieReader *anim, const char *dir)
void MOV_close(MovieReader *anim)
Definition movie_read.cc:66
int MOV_get_duration_frames(MovieReader *anim, IMB_Timecode_Type tc)
float MOV_get_fps(const MovieReader *anim)
ImBuf * MOV_decode_frame(MovieReader *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
static void movie_clip_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition movieclip.cc:164
static bool has_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
Definition movieclip.cc:828
static void movieclip_calc_length(MovieClip *clip)
Definition movieclip.cc:632
void BKE_movieclip_update_scopes(MovieClip *clip, const MovieClipUser *user, MovieClipScopes *scopes)
static bool need_undistortion_postprocess(const MovieClipUser *user, int clip_flag)
static void direct_link_movieTracks(BlendDataReader *reader, ListBase *tracksbase)
Definition movieclip.cc:236
static void direct_link_movieReconstruction(BlendDataReader *reader, MovieTrackingReconstruction *reconstruction)
Definition movieclip.cc:229
ImBuf * BKE_movieclip_get_postprocessed_ibuf(MovieClip *clip, const MovieClipUser *user, const int postprocess_flag)
void BKE_movieclip_reload(Main *bmain, MovieClip *clip)
ImBuf * BKE_movieclip_get_stable_ibuf(MovieClip *clip, const MovieClipUser *user, const int postprocess_flag, float r_loc[2], float *r_scale, float *r_angle)
static blender::gpu::Texture ** movieclip_get_gputexture_ptr(MovieClip *clip, MovieClipUser *cuser, eGPUTextureTarget textarget)
MovieClip * BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
Definition movieclip.cc:991
static int sequence_guess_offset(const char *full_name, int head_len, ushort numlen)
Definition movieclip.cc:331
float BKE_movieclip_remap_scene_to_clip_frame(const MovieClip *clip, const float framenr)
static bool moviecache_hashcmp(const void *av, const void *bv)
Definition movieclip.cc:766
void BKE_movieclip_user_set_frame(MovieClipUser *user, int framenr)
static void movie_clip_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
Definition movieclip.cc:150
float BKE_movieclip_get_fps(MovieClip *clip)
static bool put_imbuf_cache(MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
Definition movieclip.cc:850
static void direct_link_moviePlaneTracks(BlendDataReader *reader, ListBase *plane_tracks_base)
Definition movieclip.cc:245
static ImBuf * get_stable_cached_frame(MovieClip *clip, const MovieClipUser *user, ImBuf *reference_ibuf, const int framenr, const int postprocess_flag)
static void free_buffers(MovieClip *clip)
static bool check_undistortion_cache_flags(const MovieClip *clip)
void BKE_movieclip_clear_proxy_cache(MovieClip *clip)
static void get_proxy_filepath(const MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char filepath[FILE_MAX])
Definition movieclip.cc:428
void BKE_movieclip_clear_cache(MovieClip *clip)
float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, const float framenr)
static void moviecache_prioritydeleter(void *priority_data_v)
Definition movieclip.cc:794
static void * moviecache_getprioritydata(void *key_v)
Definition movieclip.cc:775
bool BKE_movieclip_has_frame(MovieClip *clip, const MovieClipUser *user)
static void movieclip_load_get_size(MovieClip *clip)
Definition movieclip.cc:924
static ImBuf * movieclip_load_sequence_file(MovieClip *clip, const MovieClipUser *user, int framenr, int flag)
Definition movieclip.cc:548
static void write_movieReconstruction(BlendWriter *writer, MovieTrackingReconstruction *reconstruction)
Definition movieclip.cc:198
static int rendersize_to_proxy(const MovieClipUser *user, int flag)
Definition movieclip.cc:340
bool BKE_movieclip_proxy_enabled(MovieClip *clip)
static bool need_postprocessed_frame(const MovieClipUser *user, int clip_flag, int postprocess_flag)
static void put_postprocessed_frame_to_cache(MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
Definition movieclip.cc:749
static ImBuf * get_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
Definition movieclip.cc:801
bool BKE_movieclip_has_cached_frame(MovieClip *clip, const MovieClipUser *user)
static ImBuf * get_postprocessed_cached_frame(const MovieClip *clip, const MovieClipUser *user, int flag, int postprocess_flag)
blender::gpu::Texture * BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser)
void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, MovieDistortion *distortion, int cfra, const int *build_sizes, int build_count, bool undistorted)
bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf)
static void get_sequence_filepath(const MovieClip *clip, const int framenr, char filepath[FILE_MAX])
Definition movieclip.cc:397
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
static void movieclip_build_proxy_ibuf(const MovieClip *clip, const ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
static void movie_clip_runtime_reset(MovieClip *clip)
Definition movieclip.cc:81
static ImBuf * postprocess_frame(MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
void BKE_movieclip_eval_update(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
static uint moviecache_hashhash(const void *keyv)
Definition movieclip.cc:758
static void detect_clip_source(Main *bmain, MovieClip *clip)
Definition movieclip.cc:937
static ImBuf * movieclip_load_movie_file(MovieClip *clip, const MovieClipUser *user, int framenr, int flag)
Definition movieclip.cc:612
static void movieclip_eval_update_reload(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
ImBuf * BKE_movieclip_get_ibuf_flag(MovieClip *clip, const MovieClipUser *user, const int flag, const int cache_flag)
static int get_timecode(MovieClip *clip, int flag)
Definition movieclip.cc:388
static void write_moviePlaneTracks(BlendWriter *writer, ListBase *plane_tracks_base)
Definition movieclip.cc:187
void BKE_movieclip_convert_multilayer_ibuf(ImBuf *ibuf)
Definition movieclip.cc:521
void BKE_movieclip_get_cache_segments(MovieClip *clip, const MovieClipUser *user, int *r_totseg, int **r_points)
static void movieclip_open_anim_file(MovieClip *clip)
Definition movieclip.cc:590
int BKE_movieclip_get_duration(MovieClip *clip)
static void movieclip_eval_update_generic(Depsgraph *depsgraph, MovieClip *clip)
void BKE_movieclip_free_gputexture(MovieClip *clip)
ImBuf * BKE_movieclip_get_ibuf(MovieClip *clip, const MovieClipUser *user)
static MovieClip * movieclip_alloc(Main *bmain, const char *name)
Definition movieclip.cc:915
static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
Definition movieclip.cc:261
void BKE_movieclip_filepath_for_frame(MovieClip *clip, const MovieClipUser *user, char *filepath)
static ImBuf * put_stabilized_frame_to_cache(MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, const int framenr, const int postprocess_flag)
void BKE_movieclip_get_size(MovieClip *clip, const MovieClipUser *user, int *r_width, int *r_height)
static ImBuf * get_undistorted_ibuf(MovieClip *clip, MovieDistortion *distortion, ImBuf *ibuf)
static int rendersize_to_number(int render_size)
Definition movieclip.cc:366
static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
Definition movieclip.cc:786
static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition movieclip.cc:207
static void movie_clip_init_data(ID *id)
Definition movieclip.cc:90
MovieClip * BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
MovieClip * BKE_movieclip_file_add(Main *bmain, const char *filepath)
Definition movieclip.cc:955
static bool moviecache_check_free_proxy(ImBuf *, void *userkey, void *)
Definition movieclip.cc:905
static void movie_clip_foreach_id(ID *id, LibraryForeachIDData *data)
Definition movieclip.cc:133
void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
static void movie_clip_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
Definition movieclip.cc:101
void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, MovieDistortion *distortion, int cfra, const int *build_sizes, int build_count, bool undistorted)
static void real_ibuf_size(const MovieClip *clip, const MovieClipUser *user, const ImBuf *ibuf, int *width, int *height)
static void write_movieTracks(BlendWriter *writer, ListBase *tracks)
Definition movieclip.cc:171
static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
Definition movieclip.cc:722
static ImBuf * movieclip_get_postprocessed_ibuf(MovieClip *clip, const MovieClipUser *user, int flag, int postprocess_flag, int cache_flag)
ImBuf * BKE_movieclip_anim_ibuf_for_frame_no_lock(MovieClip *clip, const MovieClipUser *user)
static void movie_clip_free_data(ID *id)
Definition movieclip.cc:123
const char * name
unsigned int id_session_uid
Definition BKE_idtype.hh:77
size_t identifier
Definition BKE_idtype.hh:82
Definition DNA_ID.h:414
unsigned int recalc
Definition DNA_ID.h:445
char name[258]
Definition DNA_ID.h:432
void * next
Definition DNA_ID.h:417
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
unsigned char planes
enum eImbFileType ftype
ExrHandle * exrhandle
void * first
ListBase movieclips
Definition BKE_main.hh:311
struct MovieClipCache::@075054362334176072160251166206245170224323103351 stabilized
MovieCache * moviecache
Definition movieclip.cc:671
struct MovieClipCache::@273040017035212004373306135155220132016177004360 postprocessed
float nuke_k[2]
Definition movieclip.cc:684
short distortion_model
Definition movieclip.cc:687
float division_k[2]
Definition movieclip.cc:683
float brown_p[2]
Definition movieclip.cc:686
float principal_point[2]
Definition movieclip.cc:681
ImBuf * reference_ibuf
Definition movieclip.cc:696
bool undistortion_used
Definition movieclip.cc:688
float brown_k[4]
Definition movieclip.cc:685
bool is_still_sequence
Definition movieclip.cc:709
float polynomial_k[3]
Definition movieclip.cc:682
struct ImBuf * track_preview
struct ImBuf * track_search
struct MovieTrackingMarker undist_marker
struct MovieTrackingMarker * marker
struct MovieTrackingTrack * track
struct ListBase gputextures
struct MovieClipCache * cache
struct MovieReader * anim
char filepath[1024]
void * tracking_context
struct MovieClipProxy proxy
struct MovieClip_Runtime runtime
struct MovieTracking tracking
struct bGPdata * gpd
ColorManagedColorspaceSettings colorspace_settings
MovieTrackingTrack * active_track
struct MovieReconstructedCamera * cameras
MovieTrackingTrack * rot_track_legacy
MovieTrackingMarker * markers
struct MovieTrackingTrack * next
MovieTrackingDopesheet dopesheet
MovieTrackingStats * stats
MovieTrackingPlaneTrack * act_plane_track_legacy
MovieTrackingReconstruction reconstruction_legacy
MovieTrackingStabilization stabilization
ListBase plane_tracks_legacy
MovieTrackingTrack * act_track_legacy
MovieTrackingCamera camera
i
Definition text_draw.cc:230
ListBase tracks
Definition tracking.cc:71
#define SEP_STR
Definition unit.cc:39
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:145