Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_clip/clip_editor.c')
-rw-r--r--source/blender/editors/space_clip/clip_editor.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 36375ad1ef3..2da13646a8b 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -67,6 +67,8 @@
#include "clip_intern.h" /* own include */
+#include "PIL_time.h"
+
/* -------------------------------------------------------------------- */
/** \name Operator Poll Functions
* \{ */
@@ -651,7 +653,16 @@ void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
* \{ */
typedef struct PrefetchJob {
+ /* Clip into which cache the frames will be prefetched into. */
MovieClip *clip;
+
+ /* Local copy of the clip which is used to decouple reading in a way which does not require
+ * threading lock which might "conflict" with the main thread,
+ *
+ * Used, for example, for animation prefetching (`clip->anim` can not be used from multiple
+ * threads and main thread might need it). */
+ MovieClip *clip_local;
+
int start_frame, current_frame, end_frame;
short render_size, render_flag;
} PrefetchJob;
@@ -903,11 +914,15 @@ static void start_prefetch_threads(MovieClip *clip,
BLI_spin_end(&queue.spin);
}
-static bool prefetch_movie_frame(
- MovieClip *clip, int frame, short render_size, short render_flag, short *stop)
+/* NOTE: Reading happens from `clip_local` into `clip->cache`. */
+static bool prefetch_movie_frame(MovieClip *clip,
+ MovieClip *clip_local,
+ int frame,
+ short render_size,
+ short render_flag,
+ short *stop)
{
MovieClipUser user = {0};
- ImBuf *ibuf;
if (check_prefetch_break() || *stop) {
return false;
@@ -918,7 +933,7 @@ static bool prefetch_movie_frame(
user.render_flag = render_flag;
if (!BKE_movieclip_has_cached_frame(clip, &user)) {
- ibuf = BKE_movieclip_anim_ibuf_for_frame(clip, &user);
+ ImBuf *ibuf = BKE_movieclip_anim_ibuf_for_frame_no_lock(clip_local, &user);
if (ibuf) {
int result;
@@ -942,6 +957,7 @@ static bool prefetch_movie_frame(
}
static void do_prefetch_movie(MovieClip *clip,
+ MovieClip *clip_local,
int start_frame,
int current_frame,
int end_frame,
@@ -956,7 +972,7 @@ static void do_prefetch_movie(MovieClip *clip,
/* read frames starting from current frame up to scene end frame */
for (frame = current_frame; frame <= end_frame; frame++) {
- if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop)) {
+ if (!prefetch_movie_frame(clip, clip_local, frame, render_size, render_flag, stop)) {
return;
}
@@ -968,7 +984,7 @@ static void do_prefetch_movie(MovieClip *clip,
/* read frames starting from current frame up to scene start frame */
for (frame = current_frame; frame >= start_frame; frame--) {
- if (!prefetch_movie_frame(clip, frame, render_size, render_flag, stop)) {
+ if (!prefetch_movie_frame(clip, clip_local, frame, render_size, render_flag, stop)) {
return;
}
@@ -998,6 +1014,7 @@ static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *p
else if (pj->clip->source == MCLIP_SRC_MOVIE) {
/* read movie in a single thread */
do_prefetch_movie(pj->clip,
+ pj->clip_local,
pj->start_frame,
pj->current_frame,
pj->end_frame,
@@ -1016,6 +1033,13 @@ static void prefetch_freejob(void *pjv)
{
PrefetchJob *pj = pjv;
+ MovieClip *clip_local = pj->clip_local;
+ if (clip_local != NULL) {
+ BKE_libblock_free_datablock(&clip_local->id, 0);
+ BKE_libblock_free_data(&clip_local->id, false);
+ MEM_freeN(clip_local);
+ }
+
MEM_freeN(pj);
}
@@ -1103,6 +1127,12 @@ void clip_start_prefetch_job(const bContext *C)
pj->render_size = sc->user.render_size;
pj->render_flag = sc->user.render_flag;
+ /* Create a local copy of the clip, so that video file (clip->anim) access can happen without
+ * acquiring the lock which will interfere with the main thread. */
+ if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ BKE_id_copy_ex(NULL, (ID *)&pj->clip->id, (ID **)&pj->clip_local, LIB_ID_COPY_LOCALIZE);
+ }
+
WM_jobs_customdata_set(wm_job, pj, prefetch_freejob);
WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0);
WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL);