Blender V4.3
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"
28
30#include "DNA_movieclip_types.h"
31#include "DNA_node_types.h"
32#include "DNA_object_types.h"
33#include "DNA_scene_types.h"
34#include "DNA_screen_types.h"
35#include "DNA_space_types.h"
36#include "DNA_view3d_types.h"
37
38#include "BLI_utildefines.h"
39
40#include "BLI_blenlib.h"
41#include "BLI_ghash.h"
42#include "BLI_math_vector.h"
43#include "BLI_threads.h"
44
45#include "BLT_translation.hh"
46
47#include "BKE_bpath.hh"
48#include "BKE_colortools.hh"
49#include "BKE_idtype.hh"
50#include "BKE_image.hh" /* openanim */
51#include "BKE_lib_id.hh"
52#include "BKE_lib_query.hh"
53#include "BKE_main.hh"
54#include "BKE_movieclip.h"
56#include "BKE_tracking.h"
57
58#include "IMB_imbuf.hh"
59#include "IMB_imbuf_types.hh"
60#include "IMB_moviecache.hh"
61#include "IMB_openexr.hh"
62
63#include "DEG_depsgraph.hh"
65
66#include "DRW_engine.hh"
67
68#include "GPU_texture.hh"
69
70#include "BLO_read_write.hh"
71
72static void free_buffers(MovieClip *clip);
73
84
85static void movie_clip_copy_data(Main * /*bmain*/,
86 std::optional<Library *> /*owner_library*/,
87 ID *id_dst,
88 const ID *id_src,
89 const int flag)
90{
91 MovieClip *movie_clip_dst = (MovieClip *)id_dst;
92 const MovieClip *movie_clip_src = (const MovieClip *)id_src;
93
94 /* We never handle user-count here for owned data. */
95 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
96
97 movie_clip_dst->anim = nullptr;
98 movie_clip_dst->cache = nullptr;
99
100 BKE_tracking_copy(&movie_clip_dst->tracking, &movie_clip_src->tracking, flag_subdata);
101 movie_clip_dst->tracking_context = nullptr;
102
103 BLI_listbase_clear((ListBase *)&movie_clip_dst->drawdata);
104
106 &movie_clip_src->colorspace_settings);
107}
108
109static void movie_clip_free_data(ID *id)
110{
111 MovieClip *movie_clip = (MovieClip *)id;
112
113 /* Also frees animdata. */
114 free_buffers(movie_clip);
115
116 BKE_tracking_free(&movie_clip->tracking);
118}
119
121{
122 MovieClip *movie_clip = (MovieClip *)id;
123 MovieTracking *tracking = &movie_clip->tracking;
124
126
127 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
128 LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) {
130 }
131 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &object->plane_tracks) {
133 }
134 }
135}
136
138 IDTypeForeachCacheFunctionCallback function_callback,
139 void *user_data)
140{
141 MovieClip *movie_clip = (MovieClip *)id;
142 IDCacheKey key{};
143 key.id_session_uid = id->session_uid;
144 key.identifier = offsetof(MovieClip, cache);
145 function_callback(id, &key, (void **)&movie_clip->cache, 0, user_data);
146
147 key.identifier = offsetof(MovieClip, tracking.camera.intrinsics);
148 function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data);
149}
150
152{
153 MovieClip *movie_clip = (MovieClip *)id;
155 bpath_data, movie_clip->filepath, sizeof(movie_clip->filepath));
156}
157
159{
160 MovieTrackingTrack *track;
161
162 track = static_cast<MovieTrackingTrack *>(tracks->first);
163 while (track) {
164 BLO_write_struct(writer, MovieTrackingTrack, track);
165
166 if (track->markers) {
168 }
169
170 track = track->next;
171 }
172}
173
174static void write_moviePlaneTracks(BlendWriter *writer, ListBase *plane_tracks_base)
175{
176 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
177 BLO_write_struct(writer, MovieTrackingPlaneTrack, plane_track);
178
179 BLO_write_pointer_array(writer, plane_track->point_tracksnr, plane_track->point_tracks);
181 writer, MovieTrackingPlaneMarker, plane_track->markersnr, plane_track->markers);
182 }
183}
184
186 MovieTrackingReconstruction *reconstruction)
187{
188 if (reconstruction->camnr) {
190 writer, MovieReconstructedCamera, reconstruction->camnr, reconstruction->cameras);
191 }
192}
193
194static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
195{
196 MovieClip *clip = (MovieClip *)id;
197
198 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
199 clip->anim = nullptr;
200 clip->tracking_context = nullptr;
201 clip->tracking.stats = nullptr;
202
203 MovieTracking *tracking = &clip->tracking;
204
205 BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
206 BKE_id_blend_write(writer, &clip->id);
207
208 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
209 BLO_write_struct(writer, MovieTrackingObject, object);
210 write_movieTracks(writer, &object->tracks);
211 write_moviePlaneTracks(writer, &object->plane_tracks);
212 write_movieReconstruction(writer, &object->reconstruction);
213 }
214}
215
217 MovieTrackingReconstruction *reconstruction)
218{
220 reader, MovieReconstructedCamera, reconstruction->camnr, &reconstruction->cameras);
221}
222
223static void direct_link_movieTracks(BlendDataReader *reader, ListBase *tracksbase)
224{
225 BLO_read_struct_list(reader, MovieTrackingTrack, tracksbase);
226
227 LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
228 BLO_read_struct_array(reader, MovieTrackingMarker, track->markersnr, &track->markers);
229 }
230}
231
232static void direct_link_moviePlaneTracks(BlendDataReader *reader, ListBase *plane_tracks_base)
233{
234 BLO_read_struct_list(reader, MovieTrackingPlaneTrack, plane_tracks_base);
235
236 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
238 reader, plane_track->point_tracksnr, (void **)&plane_track->point_tracks);
239 for (int i = 0; i < plane_track->point_tracksnr; i++) {
240 BLO_read_struct(reader, MovieTrackingTrack, &plane_track->point_tracks[i]);
241 }
242
244 reader, MovieTrackingPlaneMarker, plane_track->markersnr, &plane_track->markers);
245 }
246}
247
249{
250 MovieClip *clip = (MovieClip *)id;
251 MovieTracking *tracking = &clip->tracking;
252
253 direct_link_movieTracks(reader, &tracking->tracks_legacy);
256
259
260 clip->anim = nullptr;
261 clip->tracking_context = nullptr;
262 clip->tracking.stats = nullptr;
263
264 /* TODO: we could store those in undo cache storage as well, and preserve them instead of
265 * re-creating them... */
267
268 /* Needed for proper versioning, will be nullptr for all newer files anyway. */
270
271 clip->tracking.dopesheet.ok = 0;
274
276
277 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
278 direct_link_movieTracks(reader, &object->tracks);
279 direct_link_moviePlaneTracks(reader, &object->plane_tracks);
280 direct_link_movieReconstruction(reader, &object->reconstruction);
281
282 BLO_read_struct(reader, MovieTrackingTrack, &object->active_track);
283 BLO_read_struct(reader, MovieTrackingPlaneTrack, &object->active_plane_track);
284 }
285}
286
288 /*id_code*/ ID_MC,
289 /*id_filter*/ FILTER_ID_MC,
290 /*dependencies_id_types*/ FILTER_ID_GD_LEGACY | FILTER_ID_IM,
291 /*main_listbase_index*/ INDEX_ID_MC,
292 /*struct_size*/ sizeof(MovieClip),
293 /*name*/ "MovieClip",
294 /*name_plural*/ N_("movieclips"),
295 /*translation_context*/ BLT_I18NCONTEXT_ID_MOVIECLIP,
297 /*asset_type_info*/ nullptr,
298
299 /*init_data*/ movie_clip_init_data,
300 /*copy_data*/ movie_clip_copy_data,
301 /*free_data*/ movie_clip_free_data,
302 /*make_local*/ nullptr,
303 /*foreach_id*/ movie_clip_foreach_id,
304 /*foreach_cache*/ movie_clip_foreach_cache,
305 /*foreach_path*/ movie_clip_foreach_path,
306 /*owner_pointer_get*/ nullptr,
307
308 /*blend_write*/ movieclip_blend_write,
309 /*blend_read_data*/ movieclip_blend_read_data,
310 /*blend_read_after_liblink*/ nullptr,
311
312 /*blend_read_undo_preserve*/ nullptr,
313
314 /*lib_override_apply_post*/ nullptr,
315};
316
317/*********************** movieclip buffer loaders *************************/
318
319static int sequence_guess_offset(const char *full_name, int head_len, ushort numlen)
320{
321 char num[FILE_MAX] = {0};
322
323 BLI_strncpy(num, full_name + head_len, numlen + 1);
324
325 return atoi(num);
326}
327
328static int rendersize_to_proxy(const MovieClipUser *user, int flag)
329{
330 if ((flag & MCLIP_USE_PROXY) == 0) {
331 return IMB_PROXY_NONE;
332 }
333
334 switch (user->render_size) {
336 return IMB_PROXY_25;
337
339 return IMB_PROXY_50;
340
342 return IMB_PROXY_75;
343
345 return IMB_PROXY_100;
346
348 return IMB_PROXY_NONE;
349 }
350
351 return IMB_PROXY_NONE;
352}
353
354static int rendersize_to_number(int render_size)
355{
356 switch (render_size) {
358 return 25;
359
361 return 50;
362
364 return 75;
365
367 return 100;
368
370 return 100;
371 }
372
373 return 100;
374}
375
376static int get_timecode(MovieClip *clip, int flag)
377{
378 if ((flag & MCLIP_USE_PROXY) == 0) {
379 return IMB_TC_NONE;
380 }
381
382 return clip->proxy.tc;
383}
384
385static void get_sequence_filepath(const MovieClip *clip,
386 const int framenr,
387 char filepath[FILE_MAX])
388{
389 ushort numlen;
390 char head[FILE_MAX], tail[FILE_MAX];
391 int offset;
392
393 BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
394 BLI_path_sequence_decode(filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
395
396 /* Movie-clips always points to first image from sequence, auto-guess offset for now.
397 * Could be something smarter in the future. */
398 offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
399
400 if (numlen) {
402 FILE_MAX,
403 head,
404 tail,
405 numlen,
406 offset + framenr - clip->start_frame + clip->frame_offset);
407 }
408 else {
409 BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
410 }
411
412 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
413}
414
415/* supposed to work with sequences only */
416static void get_proxy_filepath(const MovieClip *clip,
417 int proxy_render_size,
418 bool undistorted,
419 int framenr,
420 char filepath[FILE_MAX])
421{
422 int size = rendersize_to_number(proxy_render_size);
423 char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
424 int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset;
425
426 BLI_path_split_dir_file(clip->filepath, clipdir, FILE_MAX, clipfile, FILE_MAX);
427
428 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
429 STRNCPY(dir, clip->proxy.dir);
430 }
431 else {
432 SNPRINTF(dir, "%s" SEP_STR "BL_proxy", clipdir);
433 }
434
435 if (undistorted) {
436 BLI_snprintf(filepath,
437 FILE_MAX,
438 "%s" SEP_STR "%s" SEP_STR "proxy_%d_undistorted" SEP_STR "%08d",
439 dir,
440 clipfile,
441 size,
442 proxynr);
443 }
444 else {
445 BLI_snprintf(filepath,
446 FILE_MAX,
447 "%s" SEP_STR "%s" SEP_STR "proxy_%d" SEP_STR "%08d",
448 dir,
449 clipfile,
450 size,
451 proxynr);
452 }
453
455 BLI_path_frame(filepath, FILE_MAX, 1, 0);
456 BLI_strncat(filepath, ".jpg", FILE_MAX);
457}
458
459#ifdef WITH_OPENEXR
460
462 float *combined_pass;
463 int num_combined_channels;
464};
465
466static void *movieclip_convert_multilayer_add_view(void * /*ctx_v*/, const char * /*view_name*/)
467{
468 return nullptr;
469}
470
471static void *movieclip_convert_multilayer_add_layer(void *ctx_v, const char * /*layer_name*/)
472{
473 /* Return dummy non-nullptr value, we don't use layer handle but need to return
474 * something, so render API invokes the add_pass() callbacks. */
475 return ctx_v;
476}
477
478static void movieclip_convert_multilayer_add_pass(void * /*layer*/,
479 void *ctx_v,
480 const char *pass_name,
481 float *rect,
482 int num_channels,
483 const char *chan_id,
484 const char * /*view_name*/)
485{
486 /* NOTE: This function must free pass pixels data if it is not used, this
487 * is how IMB_exr_multilayer_convert() is working. */
488 MultilayerConvertContext *ctx = static_cast<MultilayerConvertContext *>(ctx_v);
489 /* If we've found a first combined pass, skip all the rest ones. */
490 if (ctx->combined_pass != nullptr) {
491 MEM_freeN(rect);
492 return;
493 }
494 if (STREQ(pass_name, RE_PASSNAME_COMBINED) || STR_ELEM(chan_id, "RGBA", "RGB")) {
495 ctx->combined_pass = rect;
496 ctx->num_combined_channels = num_channels;
497 }
498 else {
499 MEM_freeN(rect);
500 }
501}
502
503#endif /* WITH_OPENEXR */
504
506{
507 if (ibuf == nullptr) {
508 return;
509 }
510#ifdef WITH_OPENEXR
511 if (ibuf->ftype != IMB_FTYPE_OPENEXR || ibuf->userdata == nullptr) {
512 return;
513 }
515 ctx.combined_pass = nullptr;
516 ctx.num_combined_channels = 0;
518 &ctx,
519 movieclip_convert_multilayer_add_view,
520 movieclip_convert_multilayer_add_layer,
521 movieclip_convert_multilayer_add_pass);
522 if (ctx.combined_pass != nullptr) {
523 BLI_assert(ibuf->float_buffer.data == nullptr);
524 IMB_assign_float_buffer(ibuf, ctx.combined_pass, IB_TAKE_OWNERSHIP);
525 ibuf->channels = ctx.num_combined_channels;
526 }
527 IMB_exr_close(ibuf->userdata);
528 ibuf->userdata = nullptr;
529#endif
530}
531
533 const MovieClipUser *user,
534 int framenr,
535 int flag)
536{
537 ImBuf *ibuf;
538 char filepath[FILE_MAX];
539 int loadflag;
540 bool use_proxy = false;
541 char *colorspace;
542
544 if (use_proxy) {
545 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
546 get_proxy_filepath(clip, user->render_size, undistort, framenr, filepath);
547
548 /* Well, this is a bit weird, but proxies for movie sources
549 * are built in the same exact color space as the input,
550 *
551 * But image sequences are built in the display space.
552 */
553 if (clip->source == MCLIP_SRC_MOVIE) {
554 colorspace = clip->colorspace_settings.name;
555 }
556 else {
557 colorspace = nullptr;
558 }
559 }
560 else {
561 get_sequence_filepath(clip, framenr, filepath);
562 colorspace = clip->colorspace_settings.name;
563 }
564
566
567 /* read ibuf */
568 ibuf = IMB_loadiffname(filepath, loadflag, colorspace);
570
571 return ibuf;
572}
573
575{
576 char filepath_abs[FILE_MAX];
577
578 if (!clip->anim) {
579 STRNCPY(filepath_abs, clip->filepath);
580 BLI_path_abs(filepath_abs, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
581
582 /* FIXME: make several stream accessible in image editor, too */
583 clip->anim = openanim(filepath_abs, IB_rect, 0, clip->colorspace_settings.name);
584
585 if (clip->anim) {
586 if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
587 char dir[FILE_MAX];
588 STRNCPY(dir, clip->proxy.dir);
590 IMB_anim_set_index_dir(clip->anim, dir);
591 }
592 }
593 }
594}
595
597 const MovieClipUser *user,
598 int framenr,
599 int flag)
600{
601 ImBuf *ibuf = nullptr;
602 int tc = get_timecode(clip, flag);
603 int proxy = rendersize_to_proxy(user, flag);
604
606
607 if (clip->anim) {
608 int fra = framenr - clip->start_frame + clip->frame_offset;
609
610 ibuf = IMB_anim_absolute(clip->anim, fra, IMB_Timecode_Type(tc), IMB_Proxy_Size(proxy));
611 }
612
613 return ibuf;
614}
615
617{
618 if (clip->source == MCLIP_SRC_MOVIE) {
620
621 if (clip->anim) {
623 }
624 }
625 else if (clip->source == MCLIP_SRC_SEQUENCE) {
626 ushort numlen;
627 char filepath[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
628
629 BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
630
631 if (numlen == 0) {
632 /* there's no number group in file name, assume it's single framed sequence */
633 clip->len = 1;
634 }
635 else {
636 clip->len = 0;
637 for (;;) {
638 get_sequence_filepath(clip, clip->len + clip->start_frame, filepath);
639
640 if (BLI_exists(filepath)) {
641 clip->len++;
642 }
643 else {
644 break;
645 }
646 }
647 }
648 }
649}
650
651/*********************** image buffer cache *************************/
652
654 /* regular movie cache */
656
657 /* cached postprocessed shot */
658 struct {
661 int flag;
662
663 /* cache for undistorted shot */
666 float polynomial_k[3];
667 float division_k[2];
668 float nuke_k[2];
669 float brown_k[4];
670 float brown_p[2];
673
674 int proxy;
677
678 /* cache for stable shot */
679 struct {
681
682 ImBuf *ibuf;
683 int framenr;
685
686 float loc[2], scale, angle, aspect;
688 short render_flag;
690
692
694};
695
701
705
706static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
707{
708 int index;
709
710 index = framenr - clip->start_frame + clip->frame_offset;
711
712 if (clip->source == MCLIP_SRC_SEQUENCE) {
713 if (clip->cache->sequence_offset == -1) {
714 ushort numlen;
715 char head[FILE_MAX], tail[FILE_MAX];
716
717 BLI_path_sequence_decode(clip->filepath, head, sizeof(head), tail, sizeof(tail), &numlen);
718
719 /* see comment in get_sequence_filepath */
720 clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
721 }
722
723 index += clip->cache->sequence_offset;
724 }
725
726 if (index < 0) {
727 return framenr - index;
728 }
729
730 return framenr;
731}
732
733static void moviecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
734{
735 const MovieClipImBufCacheKey *key = static_cast<const MovieClipImBufCacheKey *>(userkey);
736
737 *framenr = key->framenr;
738 *proxy = key->proxy;
739 *render_flags = key->render_flag;
740}
741
742static uint moviecache_hashhash(const void *keyv)
743{
744 const MovieClipImBufCacheKey *key = static_cast<const MovieClipImBufCacheKey *>(keyv);
745 int rval = key->framenr;
746
747 return rval;
748}
749
750static bool moviecache_hashcmp(const void *av, const void *bv)
751{
752 const MovieClipImBufCacheKey *a = static_cast<const MovieClipImBufCacheKey *>(av);
753 const MovieClipImBufCacheKey *b = static_cast<const MovieClipImBufCacheKey *>(bv);
754
755 return ((a->framenr != b->framenr) || (a->proxy != b->proxy) ||
756 (a->render_flag != b->render_flag));
757}
758
759static void *moviecache_getprioritydata(void *key_v)
760{
762 MovieClipCachePriorityData *priority_data;
763
764 priority_data = static_cast<MovieClipCachePriorityData *>(
765 MEM_callocN(sizeof(*priority_data), "movie cache clip priority data"));
766 priority_data->framenr = key->framenr;
767
768 return priority_data;
769}
770
771static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
772{
773 MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *)last_userkey_v;
774 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
775
776 return -abs(last_userkey->framenr - priority_data->framenr);
777}
778
779static void moviecache_prioritydeleter(void *priority_data_v)
780{
781 MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *)priority_data_v;
782
783 MEM_freeN(priority_data);
784}
785
786static ImBuf *get_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
787{
788 if (clip->cache) {
790
791 if (!clip->cache->is_still_sequence) {
792 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
793 }
794 else {
795 key.framenr = 1;
796 }
797
798 if (flag & MCLIP_USE_PROXY) {
799 key.proxy = rendersize_to_proxy(user, flag);
800 key.render_flag = user->render_flag;
801 }
802 else {
803 key.proxy = IMB_PROXY_NONE;
804 key.render_flag = 0;
805 }
806
807 return IMB_moviecache_get(clip->cache->moviecache, &key, nullptr);
808 }
809
810 return nullptr;
811}
812
813static bool has_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
814{
815 if (clip->cache) {
817
818 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
819
820 if (flag & MCLIP_USE_PROXY) {
821 key.proxy = rendersize_to_proxy(user, flag);
822 key.render_flag = user->render_flag;
823 }
824 else {
825 key.proxy = IMB_PROXY_NONE;
826 key.render_flag = 0;
827 }
828
829 return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
830 }
831
832 return false;
833}
834
835static bool put_imbuf_cache(
836 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
837{
839
840 if (clip->cache == nullptr) {
841 MovieCache *moviecache;
842
843 // char cache_name[64];
844 // SNPRINTF(cache_name, "movie %s", clip->id.name);
845
846 clip->cache = static_cast<MovieClipCache *>(
847 MEM_callocN(sizeof(MovieClipCache), "movieClipCache"));
848
849 moviecache = IMB_moviecache_create(
851
857
858 clip->cache->moviecache = moviecache;
859 clip->cache->sequence_offset = -1;
860 if (clip->source == MCLIP_SRC_SEQUENCE) {
861 ushort numlen;
862 BLI_path_sequence_decode(clip->filepath, nullptr, 0, nullptr, 0, &numlen);
863 clip->cache->is_still_sequence = (numlen == 0);
864 }
865 }
866
867 if (!clip->cache->is_still_sequence) {
868 key.framenr = user_frame_to_cache_frame(clip, user->framenr);
869 }
870 else {
871 key.framenr = 1;
872 }
873
874 if (flag & MCLIP_USE_PROXY) {
875 key.proxy = rendersize_to_proxy(user, flag);
876 key.render_flag = user->render_flag;
877 }
878 else {
879 key.proxy = IMB_PROXY_NONE;
880 key.render_flag = 0;
881 }
882
883 if (destructive) {
884 IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
885 return true;
886 }
887
888 return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
889}
890
891static bool moviecache_check_free_proxy(ImBuf * /*ibuf*/, void *userkey, void * /*userdata*/)
892{
894
895 return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0);
896}
897
898/*********************** common functions *************************/
899
900/* only image block itself */
901static MovieClip *movieclip_alloc(Main *bmain, const char *name)
902{
903 MovieClip *clip;
904
905 clip = static_cast<MovieClip *>(BKE_id_new(bmain, ID_MC, name));
906
907 return clip;
908}
909
911{
912 int width, height;
914
916 BKE_movieclip_get_size(clip, &user, &width, &height);
917
918 if (!width || !height) {
919 clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
920 }
921}
922
923static void detect_clip_source(Main *bmain, MovieClip *clip)
924{
925 ImBuf *ibuf;
926 char filepath[FILE_MAX];
927
928 STRNCPY(filepath, clip->filepath);
929 BLI_path_abs(filepath, BKE_main_blendfile_path(bmain));
930
931 ibuf = IMB_testiffname(filepath, IB_rect | IB_multilayer);
932 if (ibuf) {
934 IMB_freeImBuf(ibuf);
935 }
936 else {
937 clip->source = MCLIP_SRC_MOVIE;
938 }
939}
940
941MovieClip *BKE_movieclip_file_add(Main *bmain, const char *filepath)
942{
943 MovieClip *clip;
944 int file;
945 char filepath_abs[FILE_MAX];
946
947 STRNCPY(filepath_abs, filepath);
948 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
949
950 /* exists? */
951 file = BLI_open(filepath_abs, O_BINARY | O_RDONLY, 0);
952 if (file == -1) {
953 return nullptr;
954 }
955 close(file);
956
957 /* ** add new movieclip ** */
958
959 /* create a short library name */
960 clip = movieclip_alloc(bmain, BLI_path_basename(filepath));
961 STRNCPY(clip->filepath, filepath);
962
963 detect_clip_source(bmain, clip);
964
966 if (clip->lastsize[0]) {
967 int width = clip->lastsize[0];
968
969 clip->tracking.camera.focal = 24.0f * width / clip->tracking.camera.sensor_width;
970 }
971
973
974 return clip;
975}
976
977MovieClip *BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
978{
979 MovieClip *clip;
980 char filepath_abs[FILE_MAX], filepath_test[FILE_MAX];
981
982 STRNCPY(filepath_abs, filepath);
983 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
984
985 /* first search an identical filepath */
986 for (clip = static_cast<MovieClip *>(bmain->movieclips.first); clip;
987 clip = static_cast<MovieClip *>(clip->id.next))
988 {
989 STRNCPY(filepath_test, clip->filepath);
990 BLI_path_abs(filepath_test, ID_BLEND_PATH(bmain, &clip->id));
991
992 if (BLI_path_cmp(filepath_test, filepath_abs) == 0) {
993 id_us_plus(&clip->id); /* officially should not, it doesn't link here! */
994 if (r_exists) {
995 *r_exists = true;
996 }
997 return clip;
998 }
999 }
1000
1001 if (r_exists) {
1002 *r_exists = false;
1003 }
1004 return BKE_movieclip_file_add(bmain, filepath);
1005}
1006
1007MovieClip *BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
1008{
1009 return BKE_movieclip_file_add_exists_ex(bmain, filepath, nullptr);
1010}
1011
1012static void real_ibuf_size(
1013 const MovieClip *clip, const MovieClipUser *user, const ImBuf *ibuf, int *width, int *height)
1014{
1015 *width = ibuf->x;
1016 *height = ibuf->y;
1017
1018 if (clip->flag & MCLIP_USE_PROXY) {
1019 switch (user->render_size) {
1021 (*width) *= 4;
1022 (*height) *= 4;
1023 break;
1024
1026 (*width) *= 2.0f;
1027 (*height) *= 2.0f;
1028 break;
1029
1031 *width = float(*width) * 4.0f / 3.0f;
1032 *height = float(*height) * 4.0f / 3.0f;
1033 break;
1034 }
1035 }
1036}
1037
1039{
1040 ImBuf *undistibuf;
1041
1042 if (distortion) {
1043 undistibuf = BKE_tracking_distortion_exec(
1044 distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, true);
1045 }
1046 else {
1047 undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f);
1048 }
1049
1050 IMB_scale(undistibuf, ibuf->x, ibuf->y, IMBScaleFilter::Box, false);
1051
1052 return undistibuf;
1053}
1054
1055static bool need_undistortion_postprocess(const MovieClipUser *user, int clip_flag)
1056{
1057 bool result = false;
1058 const bool uses_full_frame = ((clip_flag & MCLIP_USE_PROXY) == 0) ||
1060 /* Only full undistorted render can be used as on-fly undistorting image. */
1061 result |= uses_full_frame && (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
1062 return result;
1063}
1064
1066 int clip_flag,
1067 int postprocess_flag)
1068{
1069 bool result = (postprocess_flag != 0);
1070 result |= need_undistortion_postprocess(user, clip_flag);
1071 return result;
1072}
1073
1075{
1076 const MovieClipCache *cache = clip->cache;
1077 const MovieTrackingCamera *camera = &clip->tracking.camera;
1078
1079 if (camera->focal != cache->postprocessed.focal_length) {
1080 return false;
1081 }
1082
1083 /* check for distortion model changes */
1084 if (!equals_v2v2(camera->principal_point, cache->postprocessed.principal_point)) {
1085 return false;
1086 }
1087
1088 if (camera->distortion_model != cache->postprocessed.distortion_model) {
1089 return false;
1090 }
1091
1092 if (!equals_v3v3(&camera->k1, cache->postprocessed.polynomial_k)) {
1093 return false;
1094 }
1095
1096 if (!equals_v2v2(&camera->division_k1, cache->postprocessed.division_k)) {
1097 return false;
1098 }
1099
1100 if (!equals_v2v2(&camera->nuke_k1, cache->postprocessed.nuke_k)) {
1101 return false;
1102 }
1103
1104 if (!equals_v4v4(&camera->brown_k1, cache->postprocessed.brown_k)) {
1105 return false;
1106 }
1107 if (!equals_v2v2(&camera->brown_p1, cache->postprocessed.brown_p)) {
1108 return false;
1109 }
1110
1111 return true;
1112}
1113
1115 const MovieClipUser *user,
1116 int flag,
1117 int postprocess_flag)
1118{
1119 const MovieClipCache *cache = clip->cache;
1120 int framenr = user->framenr;
1121 short proxy = IMB_PROXY_NONE;
1122 int render_flag = 0;
1123
1124 if (flag & MCLIP_USE_PROXY) {
1125 proxy = rendersize_to_proxy(user, flag);
1126 render_flag = user->render_flag;
1127 }
1128
1129 /* no cache or no cached postprocessed image */
1130 if (!clip->cache || !clip->cache->postprocessed.ibuf) {
1131 return nullptr;
1132 }
1133
1134 /* Postprocessing happened for other frame. */
1135 if (cache->postprocessed.framenr != framenr) {
1136 return nullptr;
1137 }
1138
1139 /* cached ibuf used different proxy settings */
1140 if (cache->postprocessed.render_flag != render_flag || cache->postprocessed.proxy != proxy) {
1141 return nullptr;
1142 }
1143
1144 if (cache->postprocessed.flag != postprocess_flag) {
1145 return nullptr;
1146 }
1147
1149 if (!check_undistortion_cache_flags(clip)) {
1150 return nullptr;
1151 }
1152 }
1153 else if (cache->postprocessed.undistortion_used) {
1154 return nullptr;
1155 }
1156
1158
1159 return cache->postprocessed.ibuf;
1160}
1161
1163 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1164{
1165 ImBuf *postproc_ibuf = nullptr;
1166
1168 postproc_ibuf = get_undistorted_ibuf(clip, nullptr, ibuf);
1169 }
1170 else {
1171 postproc_ibuf = IMB_dupImBuf(ibuf);
1172 }
1173
1174 if (postprocess_flag) {
1175 bool disable_red = (postprocess_flag & MOVIECLIP_DISABLE_RED) != 0;
1176 bool disable_green = (postprocess_flag & MOVIECLIP_DISABLE_GREEN) != 0;
1177 bool disable_blue = (postprocess_flag & MOVIECLIP_DISABLE_BLUE) != 0;
1178 bool grayscale = (postprocess_flag & MOVIECLIP_PREVIEW_GRAYSCALE) != 0;
1179
1180 if (disable_red || disable_green || disable_blue || grayscale) {
1181 BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, true);
1182 }
1183 }
1184
1185 return postproc_ibuf;
1186}
1187
1189 MovieClip *clip, const MovieClipUser *user, ImBuf *ibuf, int flag, int postprocess_flag)
1190{
1191 MovieClipCache *cache = clip->cache;
1193
1194 cache->postprocessed.framenr = user->framenr;
1195 cache->postprocessed.flag = postprocess_flag;
1196
1197 if (flag & MCLIP_USE_PROXY) {
1199 cache->postprocessed.render_flag = user->render_flag;
1200 }
1201 else {
1203 cache->postprocessed.render_flag = 0;
1204 }
1205
1207 cache->postprocessed.distortion_model = camera->distortion_model;
1208 cache->postprocessed.focal_length = camera->focal;
1209 copy_v2_v2(cache->postprocessed.principal_point, camera->principal_point);
1211 copy_v2_v2(cache->postprocessed.division_k, &camera->division_k1);
1212 copy_v2_v2(cache->postprocessed.nuke_k, &camera->nuke_k1);
1213 copy_v4_v4(cache->postprocessed.brown_k, &camera->brown_k1);
1214 copy_v2_v2(cache->postprocessed.brown_p, &camera->brown_p1);
1215 cache->postprocessed.undistortion_used = true;
1216 }
1217 else {
1218 cache->postprocessed.undistortion_used = false;
1219 }
1220
1221 IMB_refImBuf(ibuf);
1222
1223 if (cache->postprocessed.ibuf) {
1225 }
1226
1227 cache->postprocessed.ibuf = ibuf;
1228}
1229
1231 MovieClip *clip, const MovieClipUser *user, int flag, int postprocess_flag, int cache_flag)
1232{
1233 ImBuf *ibuf = nullptr;
1234 int framenr = user->framenr;
1235 bool need_postprocess = false;
1236
1237 /* cache isn't threadsafe itself and also loading of movies
1238 * can't happen from concurrent threads that's why we use lock here */
1240
1241 /* try to obtain cached postprocessed frame first */
1242 if (need_postprocessed_frame(user, flag, postprocess_flag)) {
1243 ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag);
1244
1245 if (!ibuf) {
1246 need_postprocess = true;
1247 }
1248 }
1249
1250 if (!ibuf) {
1251 ibuf = get_imbuf_cache(clip, user, flag);
1252 }
1253
1254 if (!ibuf) {
1255 bool use_sequence = false;
1256
1257 /* undistorted proxies for movies should be read as image sequence */
1258 use_sequence = (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) &&
1260
1261 if (clip->source == MCLIP_SRC_SEQUENCE || use_sequence) {
1262 ibuf = movieclip_load_sequence_file(clip, user, framenr, flag);
1263 }
1264 else {
1265 ibuf = movieclip_load_movie_file(clip, user, framenr, flag);
1266 }
1267
1268 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1269 put_imbuf_cache(clip, user, ibuf, flag, true);
1270 }
1271 }
1272
1273 if (ibuf) {
1274 real_ibuf_size(clip, user, ibuf, &clip->lastsize[0], &clip->lastsize[1]);
1275
1276 /* Post-process frame and put to cache if needed. */
1277 if (need_postprocess) {
1278 ImBuf *tmpibuf = ibuf;
1279 ibuf = postprocess_frame(clip, user, tmpibuf, flag, postprocess_flag);
1280 IMB_freeImBuf(tmpibuf);
1281 if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) {
1282 put_postprocessed_frame_to_cache(clip, user, ibuf, flag, postprocess_flag);
1283 }
1284 }
1285 }
1286
1288
1289 /* Fallback render in case proxies are not enabled or built */
1292 {
1293 MovieClipUser user_fallback = *user;
1295
1297 clip, &user_fallback, flag, postprocess_flag, cache_flag);
1298 }
1299
1300 return ibuf;
1301}
1302
1304{
1305 return BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, 0);
1306}
1307
1309 const MovieClipUser *user,
1310 const int flag,
1311 const int cache_flag)
1312{
1313 return movieclip_get_postprocessed_ibuf(clip, user, flag, 0, cache_flag);
1314}
1315
1317 const MovieClipUser *user,
1318 const int postprocess_flag)
1319{
1320 return movieclip_get_postprocessed_ibuf(clip, user, clip->flag, postprocess_flag, 0);
1321}
1322
1324 const MovieClipUser *user,
1325 ImBuf *reference_ibuf,
1326 const int framenr,
1327 const int postprocess_flag)
1328{
1329 MovieClipCache *cache = clip->cache;
1330 MovieTracking *tracking = &clip->tracking;
1331 ImBuf *stableibuf;
1332 float tloc[2], tscale, tangle;
1333 short proxy = IMB_PROXY_NONE;
1334 int render_flag = 0;
1335 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1336
1337 if (clip->flag & MCLIP_USE_PROXY) {
1338 proxy = rendersize_to_proxy(user, clip->flag);
1339 render_flag = user->render_flag;
1340 }
1341
1342 /* there's no cached frame or it was calculated for another frame */
1343 if (!cache->stabilized.ibuf || cache->stabilized.framenr != framenr) {
1344 return nullptr;
1345 }
1346
1347 if (cache->stabilized.reference_ibuf != reference_ibuf) {
1348 return nullptr;
1349 }
1350
1351 /* cached ibuf used different proxy settings */
1352 if (cache->stabilized.render_flag != render_flag || cache->stabilized.proxy != proxy) {
1353 return nullptr;
1354 }
1355
1356 if (cache->stabilized.postprocess_flag != postprocess_flag) {
1357 return nullptr;
1358 }
1359
1360 /* stabilization also depends on pixel aspect ratio */
1361 if (cache->stabilized.aspect != tracking->camera.pixel_aspect) {
1362 return nullptr;
1363 }
1364
1365 if (cache->stabilized.filter != tracking->stabilization.filter) {
1366 return nullptr;
1367 }
1368
1369 stableibuf = cache->stabilized.ibuf;
1370
1372 clip, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle);
1373
1374 /* check for stabilization parameters */
1375 if (tscale != cache->stabilized.scale || tangle != cache->stabilized.angle ||
1376 !equals_v2v2(tloc, cache->stabilized.loc))
1377 {
1378 return nullptr;
1379 }
1380
1381 IMB_refImBuf(stableibuf);
1382
1383 return stableibuf;
1384}
1385
1387 const MovieClipUser *user,
1388 ImBuf *ibuf,
1389 const int framenr,
1390 const int postprocess_flag)
1391{
1392 MovieClipCache *cache = clip->cache;
1393 MovieTracking *tracking = &clip->tracking;
1394 ImBuf *stableibuf;
1395 float tloc[2], tscale, tangle;
1396 int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr);
1397
1398 stableibuf = BKE_tracking_stabilize_frame(clip, clip_framenr, ibuf, tloc, &tscale, &tangle);
1399
1400 copy_v2_v2(cache->stabilized.loc, tloc);
1401
1402 cache->stabilized.reference_ibuf = ibuf;
1403 cache->stabilized.scale = tscale;
1404 cache->stabilized.angle = tangle;
1405 cache->stabilized.framenr = framenr;
1406 cache->stabilized.aspect = tracking->camera.pixel_aspect;
1407 cache->stabilized.filter = tracking->stabilization.filter;
1408
1409 if (clip->flag & MCLIP_USE_PROXY) {
1410 cache->stabilized.proxy = rendersize_to_proxy(user, clip->flag);
1411 cache->stabilized.render_flag = user->render_flag;
1412 }
1413 else {
1415 cache->stabilized.render_flag = 0;
1416 }
1417
1418 cache->stabilized.postprocess_flag = postprocess_flag;
1419
1420 if (cache->stabilized.ibuf) {
1422 }
1423
1424 cache->stabilized.ibuf = stableibuf;
1425
1426 IMB_refImBuf(stableibuf);
1427
1428 return stableibuf;
1429}
1430
1432 const MovieClipUser *user,
1433 const int postprocess_flag,
1434 float r_loc[2],
1435 float *r_scale,
1436 float *r_angle)
1437{
1438 ImBuf *ibuf, *stableibuf = nullptr;
1439 int framenr = user->framenr;
1440
1441 ibuf = BKE_movieclip_get_postprocessed_ibuf(clip, user, postprocess_flag);
1442
1443 if (!ibuf) {
1444 return nullptr;
1445 }
1446
1448 MovieClipCache *cache = clip->cache;
1449
1450 stableibuf = get_stable_cached_frame(clip, user, ibuf, framenr, postprocess_flag);
1451
1452 if (!stableibuf) {
1453 stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
1454 }
1455
1456 if (r_loc) {
1457 copy_v2_v2(r_loc, cache->stabilized.loc);
1458 }
1459
1460 if (r_scale) {
1461 *r_scale = cache->stabilized.scale;
1462 }
1463
1464 if (r_angle) {
1465 *r_angle = cache->stabilized.angle;
1466 }
1467 }
1468 else {
1469 if (r_loc) {
1470 zero_v2(r_loc);
1471 }
1472
1473 if (r_scale) {
1474 *r_scale = 1.0f;
1475 }
1476
1477 if (r_angle) {
1478 *r_angle = 0.0f;
1479 }
1480
1481 stableibuf = ibuf;
1482 }
1483
1484 if (stableibuf != ibuf) {
1485 IMB_freeImBuf(ibuf);
1486 ibuf = stableibuf;
1487 }
1488
1489 return ibuf;
1490}
1491
1493{
1494 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1495
1496 if (ibuf) {
1497 IMB_freeImBuf(ibuf);
1498 return true;
1499 }
1500
1501 return false;
1502}
1503
1505 const MovieClipUser *user,
1506 int *r_width,
1507 int *r_height)
1508{
1509 /* TODO(sergey): Support reading sequences of different resolution. */
1510 if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
1511 *r_width = clip->lastsize[0];
1512 *r_height = clip->lastsize[1];
1513 }
1514 else {
1515 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1516
1517 if (ibuf && ibuf->x && ibuf->y) {
1518 real_ibuf_size(clip, user, ibuf, r_width, r_height);
1519 }
1520 else {
1521 *r_width = clip->lastsize[0];
1522 *r_height = clip->lastsize[1];
1523 }
1524
1525 if (ibuf) {
1526 IMB_freeImBuf(ibuf);
1527 }
1528 }
1529}
1530void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
1531{
1532 int width, height;
1533 BKE_movieclip_get_size(clip, user, &width, &height);
1534
1535 r_size[0] = float(width);
1536 r_size[1] = float(height);
1537}
1538
1540{
1541 if (!clip->len) {
1543 }
1544
1545 return clip->len;
1546}
1547
1549{
1550 if (clip->source != MCLIP_SRC_MOVIE) {
1551 return 0.0f;
1552 }
1554 if (clip->anim == nullptr) {
1555 return 0.0f;
1556 }
1557 short frs_sec;
1558 float frs_sec_base;
1559 if (IMB_anim_get_fps(clip->anim, true, &frs_sec, &frs_sec_base)) {
1560 return float(frs_sec) / frs_sec_base;
1561 }
1562 return 0.0f;
1563}
1564
1565void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
1566{
1567 *aspx = 1.0;
1568
1569 /* x is always 1 */
1570 *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect;
1571}
1572
1574 const MovieClipUser *user,
1575 int *r_totseg,
1576 int **r_points)
1577{
1578 *r_totseg = 0;
1579 *r_points = nullptr;
1580
1581 if (clip->cache) {
1582 int proxy = rendersize_to_proxy(user, clip->flag);
1583
1586 clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
1588 }
1589}
1590
1592{
1593 /* TODO: clamp framenr here? */
1594
1595 user->framenr = framenr;
1596}
1597
1598static void free_buffers(MovieClip *clip)
1599{
1600 if (clip->cache) {
1602
1603 if (clip->cache->postprocessed.ibuf) {
1605 }
1606
1607 if (clip->cache->stabilized.ibuf) {
1609 }
1610
1611 MEM_freeN(clip->cache);
1612 clip->cache = nullptr;
1613 }
1614
1615 if (clip->anim) {
1616 IMB_free_anim(clip->anim);
1617 clip->anim = nullptr;
1618 }
1619
1621 for (tex = static_cast<MovieClip_RuntimeGPUTexture *>(clip->runtime.gputextures.first); tex;
1622 tex = static_cast<MovieClip_RuntimeGPUTexture *>(tex->next))
1623 {
1624 for (int i = 0; i < TEXTARGET_COUNT; i++) {
1625 if (tex->gputexture[i] != nullptr) {
1627 tex->gputexture[i] = nullptr;
1628 }
1629 }
1630 }
1632}
1633
1635{
1636 free_buffers(clip);
1637}
1638
1640{
1641 if (clip->cache && clip->cache->moviecache) {
1643 }
1644}
1645
1647{
1648 /* clear cache */
1649 free_buffers(clip);
1650
1651 /* update clip source */
1652 detect_clip_source(bmain, clip);
1653
1654 /* Tag for re-calculation of the actual size. */
1655 clip->lastsize[0] = clip->lastsize[1] = 0;
1656
1659
1660 BKE_ntree_update_tag_id_changed(bmain, &clip->id);
1661}
1662
1664 const MovieClipUser *user,
1665 MovieClipScopes *scopes)
1666{
1667 if (scopes->ok) {
1668 return;
1669 }
1670
1671 if (scopes->track_preview) {
1673 scopes->track_preview = nullptr;
1674 }
1675
1676 if (scopes->track_search) {
1677 IMB_freeImBuf(scopes->track_search);
1678 scopes->track_search = nullptr;
1679 }
1680
1681 scopes->marker = nullptr;
1682 scopes->track = nullptr;
1683 scopes->track_locked = true;
1684
1685 scopes->scene_framenr = user->framenr;
1686 scopes->ok = true;
1687
1688 if (clip == nullptr) {
1689 return;
1690 }
1691
1692 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
1693 MovieTrackingTrack *track = tracking_object->active_track;
1694 if (track == nullptr) {
1695 return;
1696 }
1697
1698 const int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
1699 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1700
1701 scopes->marker = marker;
1702 scopes->track = track;
1703
1704 if (marker->flag & MARKER_DISABLED) {
1705 scopes->track_disabled = true;
1706 }
1707 else {
1708 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
1709
1710 scopes->track_disabled = false;
1711
1712 if (ibuf && (ibuf->byte_buffer.data || ibuf->float_buffer.data)) {
1713 MovieTrackingMarker undist_marker = *marker;
1714
1716 int width, height;
1717 float aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1718
1719 BKE_movieclip_get_size(clip, user, &width, &height);
1720
1721 undist_marker.pos[0] *= width;
1722 undist_marker.pos[1] *= height * aspy;
1723
1725 &clip->tracking, width, height, undist_marker.pos, undist_marker.pos);
1726
1727 undist_marker.pos[0] /= width;
1728 undist_marker.pos[1] /= height * aspy;
1729 }
1730
1732 ibuf, track, &undist_marker, true, true);
1733
1734 scopes->undist_marker = undist_marker;
1735
1736 scopes->frame_width = ibuf->x;
1737 scopes->frame_height = ibuf->y;
1738
1739 scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0;
1740 }
1741
1742 IMB_freeImBuf(ibuf);
1743 }
1744
1745 if ((track->flag & TRACK_LOCKED) == 0) {
1746 float pat_min[2], pat_max[2];
1747
1748 scopes->track_locked = false;
1749
1750 /* XXX: would work fine with non-transformed patterns, but would likely fail
1751 * with transformed patterns, but that would be easier to debug when
1752 * we'll have real pattern sampling (at least to test) */
1753 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1754
1755 scopes->slide_scale[0] = pat_max[0] - pat_min[0];
1756 scopes->slide_scale[1] = pat_max[1] - pat_min[1];
1757 }
1758}
1759
1761 MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
1762{
1763 char filepath[FILE_MAX];
1764 int quality, rectx, recty;
1765 int size = rendersize_to_number(proxy_render_size);
1766 ImBuf *scaleibuf;
1767
1768 get_proxy_filepath(clip, proxy_render_size, undistorted, cfra, filepath);
1769
1770 rectx = ibuf->x * size / 100.0f;
1771 recty = ibuf->y * size / 100.0f;
1772
1773 scaleibuf = IMB_dupImBuf(ibuf);
1774 IMB_scale(scaleibuf, rectx, recty, IMBScaleFilter::Bilinear, threaded);
1775
1776 quality = clip->proxy.quality;
1777 scaleibuf->ftype = IMB_FTYPE_JPG;
1778 scaleibuf->foptions.quality = quality;
1779 /* unsupported feature only confuses other s/w */
1780 if (scaleibuf->planes == 32) {
1781 scaleibuf->planes = 24;
1782 }
1783
1784 /* TODO: currently the most weak part of multi-threaded proxies,
1785 * could be solved in a way that thread only prepares memory
1786 * buffer and write to disk happens separately
1787 */
1789
1791 if (IMB_saveiff(scaleibuf, filepath, IB_rect) == 0) {
1792 perror(filepath);
1793 }
1794
1796
1797 IMB_freeImBuf(scaleibuf);
1798}
1799
1801 int clip_flag,
1802 MovieDistortion *distortion,
1803 int cfra,
1804 const int *build_sizes,
1805 int build_count,
1806 bool undistorted)
1807{
1808 ImBuf *ibuf;
1809 MovieClipUser user;
1810
1811 if (!build_count) {
1812 return;
1813 }
1814
1815 user.framenr = cfra;
1816 user.render_flag = 0;
1818
1819 ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
1820
1821 if (ibuf) {
1822 ImBuf *tmpibuf = ibuf;
1823 int i;
1824
1825 if (undistorted) {
1826 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1827 }
1828
1829 for (i = 0; i < build_count; i++) {
1830 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
1831 }
1832
1833 IMB_freeImBuf(ibuf);
1834
1835 if (tmpibuf != ibuf) {
1836 IMB_freeImBuf(tmpibuf);
1837 }
1838 }
1839}
1840
1842 ImBuf *ibuf,
1843 MovieDistortion *distortion,
1844 int cfra,
1845 const int *build_sizes,
1846 int build_count,
1847 bool undistorted)
1848{
1849 if (!build_count) {
1850 return;
1851 }
1852
1853 if (ibuf) {
1854 ImBuf *tmpibuf = ibuf;
1855 int i;
1856
1857 if (undistorted) {
1858 tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
1859 }
1860
1861 for (i = 0; i < build_count; i++) {
1862 movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
1863 }
1864
1865 if (tmpibuf != ibuf) {
1866 IMB_freeImBuf(tmpibuf);
1867 }
1868 }
1869}
1870
1872{
1873 return clip->flag & MCLIP_USE_PROXY;
1874}
1875
1876float BKE_movieclip_remap_scene_to_clip_frame(const MovieClip *clip, const float framenr)
1877{
1878 return framenr - float(clip->start_frame) + 1.0f;
1879}
1880
1881float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, const float framenr)
1882{
1883 return framenr + float(clip->start_frame) - 1.0f;
1884}
1885
1886void BKE_movieclip_filepath_for_frame(MovieClip *clip, const MovieClipUser *user, char *filepath)
1887{
1888 if (clip->source == MCLIP_SRC_SEQUENCE) {
1889 int use_proxy;
1890
1891 use_proxy = (clip->flag & MCLIP_USE_PROXY) &&
1893
1894 if (use_proxy) {
1895 int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1896 get_proxy_filepath(clip, user->render_size, undistort, user->framenr, filepath);
1897 }
1898 else {
1899 get_sequence_filepath(clip, user->framenr, filepath);
1900 }
1901 }
1902 else {
1903 BLI_strncpy(filepath, clip->filepath, FILE_MAX);
1904 BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
1905 }
1906}
1907
1909{
1910 ImBuf *ibuf = nullptr;
1911
1912 if (clip->source == MCLIP_SRC_MOVIE) {
1913 ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
1914 }
1915
1916 return ibuf;
1917}
1918
1920{
1921 bool has_frame = false;
1922
1924 has_frame = has_imbuf_cache(clip, user, clip->flag);
1926
1927 return has_frame;
1928}
1929
1931{
1932 bool result;
1933
1935 result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
1937
1938 return result;
1939}
1940
1941static void movieclip_eval_update_reload(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
1942{
1943 BKE_movieclip_reload(bmain, clip);
1944 if (DEG_is_active(depsgraph)) {
1945 MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id);
1946 BKE_movieclip_reload(bmain, clip_orig);
1947 }
1948}
1949
1951{
1953 if (DEG_is_active(depsgraph)) {
1954 MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id);
1956 }
1957}
1958
1959void BKE_movieclip_eval_update(Depsgraph *depsgraph, Main *bmain, MovieClip *clip)
1960{
1961 DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip);
1962 if (clip->id.recalc & ID_RECALC_SOURCE) {
1964 }
1965 else {
1967 }
1968}
1969
1970/* -------------------------------------------------------------------- */
1973
1974static GPUTexture **movieclip_get_gputexture_ptr(MovieClip *clip,
1975 MovieClipUser *cuser,
1976 eGPUTextureTarget textarget)
1977{
1978 /* Check if we have an existing entry for that clip user. */
1980 for (tex = static_cast<MovieClip_RuntimeGPUTexture *>(clip->runtime.gputextures.first); tex;
1981 tex = static_cast<MovieClip_RuntimeGPUTexture *>(tex->next))
1982 {
1983 if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) {
1984 break;
1985 }
1986 }
1987
1988 /* If not, allocate a new one. */
1989 if (tex == nullptr) {
1991 __func__);
1992
1993 for (int i = 0; i < TEXTARGET_COUNT; i++) {
1994 tex->gputexture[i] = nullptr;
1995 }
1996
1997 memcpy(&tex->user, cuser, sizeof(MovieClipUser));
1998 BLI_addtail(&clip->runtime.gputextures, tex);
1999 }
2000
2001 return &tex->gputexture[textarget];
2002}
2003
2005{
2006 if (clip == nullptr) {
2007 return nullptr;
2008 }
2009
2010 GPUTexture **tex = movieclip_get_gputexture_ptr(clip, cuser, TEXTARGET_2D);
2011 if (*tex) {
2012 return *tex;
2013 }
2014
2015 /* check if we have a valid image buffer */
2016 ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
2017 if (ibuf == nullptr) {
2018 fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
2019 *tex = GPU_texture_create_error(2, false);
2020 return *tex;
2021 }
2022
2023 /* This only means RGBA16F instead of RGBA32F. */
2024 const bool high_bitdepth = false;
2025 const bool store_premultiplied = ibuf->float_buffer.data ? false : true;
2026 *tex = IMB_create_gpu_texture(clip->id.name + 2, ibuf, high_bitdepth, store_premultiplied);
2027
2028 /* Do not generate mips for movieclips... too slow. */
2029 GPU_texture_mipmap_mode(*tex, false, true);
2030
2031 IMB_freeImBuf(ibuf);
2032
2033 return *tex;
2034}
2035
2037{
2038 /* Number of gpu textures to keep around as cache.
2039 * We don't want to keep too many GPU textures for
2040 * movie clips around, as they can be large. */
2041 const int MOVIECLIP_NUM_GPUTEXTURES = 1;
2042
2043 while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) {
2045 &clip->runtime.gputextures);
2046 for (int i = 0; i < TEXTARGET_COUNT; i++) {
2047 /* Free GLSL image binding. */
2048 if (tex->gputexture[i]) {
2050 tex->gputexture[i] = nullptr;
2051 }
2052 }
2053 MEM_freeN(tex);
2054 }
2055}
2056
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:123
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
Definition BKE_idtype.hh:98
IDTypeInfo IDType_ID_MC
Definition movieclip.cc:287
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
ImBufAnim * openanim(const char *filepath, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
void id_us_plus(ID *id)
Definition lib_id.cc:351
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
@ IDWALK_CB_USER
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
#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:329
void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
Definition tracking.cc:2876
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:2471
void BKE_tracking_free(struct MovieTracking *tracking)
Definition tracking.cc:160
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking)
Definition tracking.cc:3411
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:2324
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:2448
#define BLI_assert(a)
Definition BLI_assert.h:50
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:350
#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:429
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:251
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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])
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:57
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:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char char size_t char * BLI_strncat(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
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 short ushort
unsigned int uint
@ LOCK_MOVIECLIP
Definition BLI_threads.h:72
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_thread_lock(int type)
Definition threads.cc:328
#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)
void BLO_read_pointer_array(BlendDataReader *reader, int array_size, void **ptr_p)
Definition readfile.cc:5052
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
#define BLT_I18NCONTEXT_ID_MOVIECLIP
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
ID * DEG_get_original_id(ID *id)
#define FILTER_ID_GD_LEGACY
Definition DNA_ID.h:1169
#define FILTER_ID_MC
Definition DNA_ID.h:1177
@ ID_RECALC_SOURCE
Definition DNA_ID.h:1110
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition DNA_ID.h:649
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
@ INDEX_ID_MC
Definition DNA_ID.h:1276
#define FILTER_ID_IM
Definition DNA_ID.h:1171
@ ID_MC
#define DNA_struct_default_get(struct_name)
eGPUTextureTarget
@ TEXTARGET_2D
@ TEXTARGET_COUNT
@ MCLIP_USE_PROXY_CUSTOM_DIR
@ MCLIP_USE_PROXY
@ MCLIP_SRC_SEQUENCE
@ MCLIP_SRC_MOVIE
@ 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
Object is a sort of wrapper for general info.
#define RE_PASSNAME_COMBINED
#define IMG_SIZE_FALLBACK
@ TRACKING_2D_STABILIZATION
@ TRACK_PREVIEW_ALPHA
@ TRACK_LOCKED
@ MARKER_DISABLED
void DRW_drawdata_free(ID *id)
void GPU_texture_free(GPUTexture *texture)
GPUTexture * GPU_texture_create_error(int dimension, bool array)
void GPU_texture_mipmap_mode(GPUTexture *texture, bool use_mipmap, bool use_filter)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
ImBuf * IMB_testiffname(const char *filepath, int flags)
Definition readimage.cc:227
ImBuf * IMB_anim_absolute(ImBufAnim *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
void IMB_anim_set_index_dir(ImBufAnim *anim, const char *dir)
Definition indexer.cc:1336
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
bool IMB_anim_get_fps(const ImBufAnim *anim, bool no_av_base, short *r_frs_sec, float *r_frs_sec_base)
ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition readimage.cc:146
void IMB_free_anim(ImBufAnim *anim)
Definition anim_movie.cc:60
void IMB_refImBuf(ImBuf *ibuf)
GPUTexture * IMB_create_gpu_texture(const char *name, ImBuf *ibuf, bool use_high_bitdepth, bool use_premult)
Definition util_gpu.cc:312
int IMB_anim_get_duration(ImBufAnim *anim, IMB_Timecode_Type tc)
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:779
@ IMB_FTYPE_JPG
@ IMB_FTYPE_OPENEXR
IMB_Proxy_Size
@ IMB_PROXY_100
@ IMB_PROXY_75
@ IMB_PROXY_50
@ IMB_PROXY_25
@ IMB_PROXY_NONE
IMB_Timecode_Type
@ IMB_TC_NONE
Contains defines and structs used throughout the imbuf module.
@ IB_TAKE_OWNERSHIP
@ IB_metadata
@ IB_multilayer
@ IB_alphamode_detect
@ IB_rect
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(void *handle)
void IMB_exr_multilayer_convert(void *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.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
local_group_size(16, 16) .push_constant(Type b
#define offsetof(t, d)
draw_view in_light_buf[] float
bool IMB_saveiff(struct ImBuf *, const char *, int)
void IMB_freeImBuf(ImBuf *)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static void movie_clip_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition movieclip.cc:151
static bool has_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
Definition movieclip.cc:813
static void movieclip_calc_length(MovieClip *clip)
Definition movieclip.cc:616
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:223
static void direct_link_movieReconstruction(BlendDataReader *reader, MovieTrackingReconstruction *reconstruction)
Definition movieclip.cc:216
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)
GPUTexture * BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser)
MovieClip * BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
Definition movieclip.cc:977
static int sequence_guess_offset(const char *full_name, int head_len, ushort numlen)
Definition movieclip.cc:319
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:750
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:137
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:835
static void direct_link_moviePlaneTracks(BlendDataReader *reader, ListBase *plane_tracks_base)
Definition movieclip.cc:232
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:416
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:779
static void * moviecache_getprioritydata(void *key_v)
Definition movieclip.cc:759
bool BKE_movieclip_has_frame(MovieClip *clip, const MovieClipUser *user)
static void movieclip_load_get_size(MovieClip *clip)
Definition movieclip.cc:910
static ImBuf * movieclip_load_sequence_file(MovieClip *clip, const MovieClipUser *user, int framenr, int flag)
Definition movieclip.cc:532
static void write_movieReconstruction(BlendWriter *writer, MovieTrackingReconstruction *reconstruction)
Definition movieclip.cc:185
static int rendersize_to_proxy(const MovieClipUser *user, int flag)
Definition movieclip.cc:328
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:733
static ImBuf * get_imbuf_cache(MovieClip *clip, const MovieClipUser *user, int flag)
Definition movieclip.cc:786
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)
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:385
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
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:742
static void detect_clip_source(Main *bmain, MovieClip *clip)
Definition movieclip.cc:923
static ImBuf * movieclip_load_movie_file(MovieClip *clip, const MovieClipUser *user, int framenr, int flag)
Definition movieclip.cc:596
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:376
static void write_moviePlaneTracks(BlendWriter *writer, ListBase *plane_tracks_base)
Definition movieclip.cc:174
void BKE_movieclip_convert_multilayer_ibuf(ImBuf *ibuf)
Definition movieclip.cc:505
static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
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:574
int BKE_movieclip_get_duration(MovieClip *clip)
static void movieclip_eval_update_generic(Depsgraph *depsgraph, MovieClip *clip)
void BKE_movieclip_free_gputexture(MovieClip *clip)
static GPUTexture ** movieclip_get_gputexture_ptr(MovieClip *clip, MovieClipUser *cuser, eGPUTextureTarget textarget)
ImBuf * BKE_movieclip_get_ibuf(MovieClip *clip, const MovieClipUser *user)
static MovieClip * movieclip_alloc(Main *bmain, const char *name)
Definition movieclip.cc:901
static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
Definition movieclip.cc:248
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:354
static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v)
Definition movieclip.cc:771
static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition movieclip.cc:194
static void movie_clip_init_data(ID *id)
Definition movieclip.cc:74
MovieClip * BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
MovieClip * BKE_movieclip_file_add(Main *bmain, const char *filepath)
Definition movieclip.cc:941
static bool moviecache_check_free_proxy(ImBuf *, void *userkey, void *)
Definition movieclip.cc:891
static void movie_clip_foreach_id(ID *id, LibraryForeachIDData *data)
Definition movieclip.cc:120
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:85
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:158
static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
Definition movieclip.cc:706
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:109
static bool use_proxy(Editing *ed, Sequence *seq)
unsigned int id_session_uid
Definition BKE_idtype.hh:69
size_t identifier
Definition BKE_idtype.hh:72
Definition DNA_ID.h:413
unsigned int recalc
Definition DNA_ID.h:437
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
void * userdata
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
unsigned char planes
enum eImbFileType ftype
void * first
ListBase movieclips
Definition BKE_main.hh:242
struct MovieClipCache::@214020355161264013272007023203362077203211022077 stabilized
MovieCache * moviecache
Definition movieclip.cc:655
struct MovieClipCache::@326354131073027344372046314207273132006120074300 postprocessed
float nuke_k[2]
Definition movieclip.cc:668
short distortion_model
Definition movieclip.cc:671
float division_k[2]
Definition movieclip.cc:667
float brown_p[2]
Definition movieclip.cc:670
float principal_point[2]
Definition movieclip.cc:665
ImBuf * reference_ibuf
Definition movieclip.cc:680
bool undistortion_used
Definition movieclip.cc:672
float brown_k[4]
Definition movieclip.cc:669
bool is_still_sequence
Definition movieclip.cc:693
float polynomial_k[3]
Definition movieclip.cc:666
struct ImBuf * track_preview
struct ImBuf * track_search
struct MovieTrackingMarker undist_marker
struct MovieTrackingMarker * marker
struct MovieTrackingTrack * track
struct GPUTexture * gputexture[3]
struct ListBase gputextures
struct MovieClipCache * cache
struct ImBufAnim * anim
char filepath[1024]
void * tracking_context
struct MovieClipProxy proxy
DrawDataList drawdata
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
ListBase tracks
Definition tracking.cc:70
#define SEP_STR
Definition unit.cc:39
ccl_device_inline int abs(int x)
Definition util/math.h:120
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:138