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
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) {
132 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, plane_track->image, IDWALK_CB_USER);
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
158static void write_movieTracks(BlendWriter *writer, ListBase *tracks)
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
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
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);
254 direct_link_moviePlaneTracks(reader, &tracking->plane_tracks_legacy);
255 direct_link_movieReconstruction(reader, &tracking->reconstruction_legacy);
256
257 BLO_read_struct(reader, MovieTrackingTrack, &clip->tracking.act_track_legacy);
258 BLO_read_struct(reader, MovieTrackingPlaneTrack, &clip->tracking.act_plane_track_legacy);
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... */
266 BLI_listbase_clear(&clip->runtime.gputextures);
267
268 /* Needed for proper versioning, will be nullptr for all newer files anyway. */
269 BLO_read_struct(reader, MovieTrackingTrack, &clip->tracking.stabilization.rot_track_legacy);
270
271 clip->tracking.dopesheet.ok = 0;
272 BLI_listbase_clear(&clip->tracking.dopesheet.channels);
273 BLI_listbase_clear(&clip->tracking.dopesheet.coverage_segments);
274
275 BLO_read_struct_list(reader, MovieTrackingObject, &tracking->objects);
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) {
622 clip->len = IMB_anim_get_duration(clip->anim, IMB_Timecode_Type(clip->proxy.tc));
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) {
933 clip->source = MCLIP_SRC_SEQUENCE;
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;
1192 MovieTrackingCamera *camera = &clip->tracking.camera;
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);
1210 copy_v3_v3(cache->postprocessed.polynomial_k, &camera->k1);
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
1447 if (clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
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) {
1601 IMB_moviecache_free(clip->cache->moviecache);
1602
1603 if (clip->cache->postprocessed.ibuf) {
1604 IMB_freeImBuf(clip->cache->postprocessed.ibuf);
1605 }
1606
1607 if (clip->cache->stabilized.ibuf) {
1608 IMB_freeImBuf(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) {
1626 GPU_texture_free(tex->gputexture[i]);
1627 tex->gputexture[i] = nullptr;
1628 }
1629 }
1630 }
1631 BLI_freelistN(&clip->runtime.gputextures);
1632}
1633
1635{
1636 free_buffers(clip);
1637}
1638
1640{
1641 if (clip->cache && clip->cache->moviecache) {
1642 IMB_moviecache_cleanup(clip->cache->moviecache, moviecache_check_free_proxy, nullptr);
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{
1952 BKE_tracking_dopesheet_tag_update(&clip->tracking);
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/* -------------------------------------------------------------------- */
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]) {
2049 GPU_texture_free(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)
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
Definition BKE_idtype.hh:98
ImBufAnim * openanim(const char *filepath, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
@ LIB_ID_CREATE_NO_USER_REFCOUNT
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
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#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: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
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:72
#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_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
struct MovieClip MovieClip
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.
local_group_size(16, 16) .push_constant(Type b
FILE * file
const Depsgraph * depsgraph
#define offsetof(t, d)
draw_view in_light_buf[] float
bool IMB_saveiff(struct ImBuf *, const char *, int)
void IMB_freeImBuf(ImBuf *)
const ProjectiveReconstruction & reconstruction
Definition intersect.cc:198
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)
IDTypeInfo IDType_ID_MC
Definition movieclip.cc:287
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
Definition DNA_ID.h:413
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
MovieCache * moviecache
Definition movieclip.cc:655
struct MovieClipCache::@89 postprocessed
float nuke_k[2]
Definition movieclip.cc:668
short distortion_model
Definition movieclip.cc:671
struct MovieClipCache::@90 stabilized
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 MovieClipCache * cache
struct ImBufAnim * anim
char filepath[1024]
void * tracking_context
DrawDataList drawdata
struct MovieTracking tracking
struct bGPdata * gpd
ColorManagedColorspaceSettings colorspace_settings
MovieTrackingTrack * active_track
MovieTrackingMarker * markers
struct MovieTrackingTrack * next
MovieTrackingCamera camera
#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