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