[Bf-blender-cvs] [810c372fd9c] temp-vse-downscale-preview: VSE: Render in size nearest to preview image

Richard Antalik noreply at git.blender.org
Tue Feb 2 13:08:22 CET 2021


Commit: 810c372fd9c6204fd452ea3920f1f70ce17b5a81
Author: Richard Antalik
Date:   Tue Feb 2 13:03:14 2021 +0100
Branches: temp-vse-downscale-preview
https://developer.blender.org/rB810c372fd9c6204fd452ea3920f1f70ce17b5a81

VSE: Render in size nearest to preview image

Calculate nearest power of two render size based on image size in
preview area when "Proxy Render Size" is set to "Automatic".

Downscaling is implemented for movies on IO level - see `IMB_Downscale`
and `IMB_anim_absolute()`. Movies are also downscaled by factor which
is power of two. Currently up to 32x - `IMB_DOWNSCALE_32X`

This means that with smaller preview sizes optimal image sizes are used
resulting in lower memory usage and higher performance.

Demo 8K video preview performance + debug info how it works internally:
{F9422536}

Differential Revision: https://developer.blender.org/D9414

===================================================================

M	source/blender/blenkernel/intern/image.c
M	source/blender/blenkernel/intern/movieclip.c
M	source/blender/editors/space_sequencer/sequencer_draw.c
M	source/blender/editors/space_sequencer/space_sequencer.c
M	source/blender/imbuf/IMB_imbuf.h
M	source/blender/imbuf/intern/IMB_anim.h
M	source/blender/imbuf/intern/anim_movie.c
M	source/blender/imbuf/intern/indexer.c
M	source/blender/imbuf/intern/thumbs.c
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesrna/intern/rna_space.c
M	source/blender/sequencer/SEQ_render.h
M	source/blender/sequencer/intern/effects.c
M	source/blender/sequencer/intern/image_cache.c
M	source/blender/sequencer/intern/image_cache.h
M	source/blender/sequencer/intern/prefetch.c
M	source/blender/sequencer/intern/proxy.c
M	source/blender/sequencer/intern/render.c
M	source/blender/sequencer/intern/render.h
M	source/blender/windowmanager/intern/wm_playanim.c

===================================================================

diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 10f15519ea4..aedd47c3092 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -3090,7 +3090,7 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
     return NULL;
   }
 
-  ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
+  ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE, IMB_DOWNSCALE_NONE);
   if (ibuf == NULL) {
     if (BLI_exists(name)) {
       printf("not an anim: %s\n", name);
@@ -4303,7 +4303,8 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
     if (fra > (dur - 1)) {
       fra = dur - 1;
     }
-    ibuf = IMB_makeSingleUser(IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE));
+    ibuf = IMB_makeSingleUser(
+        IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE, IMB_DOWNSCALE_NONE));
 
     if (ibuf) {
       image_init_after_load(ima, iuser, ibuf);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 175caf85b49..d6ec81ff879 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -646,7 +646,7 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip,
   if (clip->anim) {
     int fra = framenr - clip->start_frame + clip->frame_offset;
 
-    ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy);
+    ibuf = IMB_anim_absolute(clip->anim, fra, tc, proxy, IMB_DOWNSCALE_NONE);
   }
 
   return ibuf;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 201df1ceed6..6f5823f2396 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1272,6 +1272,25 @@ void ED_sequencer_special_preview_clear(void)
   sequencer_special_update_set(NULL);
 }
 
+static void sequencer_render_data_downscale_set(SeqRenderData *context,
+                                                const SpaceSeq *sseq,
+                                                const View2D *v2d)
+{
+  if (sseq->render_size != SEQ_RENDER_SIZE_AUTOMATIC) {
+    return;
+  }
+
+  const Scene *scene = context->scene;
+  rcti rect_tot;
+  UI_view2d_view_to_region_rcti(v2d, &v2d->tot, &rect_tot);
+  const int viewport_image_width = BLI_rcti_size_x(&rect_tot);
+  const float viewport_downscale_factor = (float)scene->r.xsch / (float)viewport_image_width;
+  context->downscale_factor = IMB_downscale_index_to_downscale_factor(
+      IMB_downscale_factor_to_downscale_index(viewport_downscale_factor));
+  context->rectx = scene->r.xsch / context->downscale_factor;
+  context->recty = scene->r.ysch / context->downscale_factor;
+}
+
 /**
  * Rendering using opengl will change the current viewport/context.
  * This is why we need the \a region, to set back the render area.
@@ -1311,6 +1330,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain,
   SEQ_render_new_render_data(
       bmain, depsgraph, scene, rectx, recty, sseq->render_size, false, &context);
   context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+  sequencer_render_data_downscale_set(&context, sseq, &region->v2d);
 
   /* Sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
    * by Escape pressed somewhere in the past. */
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 51c2d3ebdf1..6aa5a289d58 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -690,6 +690,7 @@ static void sequencer_preview_region_layout(const bContext *C, ARegion *region)
   if (sseq->flag & SEQ_ZOOM_TO_FIT) {
     View2D *v2d = &region->v2d;
     v2d->cur = v2d->tot;
+    UI_view2d_curRect_validate(v2d);
   }
 }
 
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 58ddc918f61..012937cff5f 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -323,6 +323,18 @@ typedef enum IMB_Proxy_Size {
   IMB_PROXY_MAX_SLOT = 4,
 } IMB_Proxy_Size;
 
+/* Apply pre-defined scale on ImBuf after it was read from source but before it is returned to
+ * caller code. Effectively, can think of downscale as run-time proxy system. */
+typedef enum IMB_Downscale {
+  IMB_DOWNSCALE_NONE = 0,
+  IMB_DOWNSCALE_2X = 1,
+  IMB_DOWNSCALE_4X = 2,
+  IMB_DOWNSCALE_8X = 3,
+  IMB_DOWNSCALE_16X = 4,
+  IMB_DOWNSCALE_32X = 5,
+  IMB_DOWNSCALE_MAX_SLOT = 6,
+} IMB_Downscale;
+
 /* Defaults to BL_proxy within the directory of the animation. */
 void IMB_anim_set_index_dir(struct anim *anim, const char *dir);
 void IMB_anim_get_fname(struct anim *anim, char *file, int size);
@@ -384,6 +396,8 @@ void IMB_anim_set_preseek(struct anim *anim, int preseek);
 int IMB_anim_get_preseek(struct anim *anim);
 int IMB_anim_get_image_width(struct anim *anim);
 int IMB_anim_get_image_height(struct anim *anim);
+IMB_Downscale IMB_downscale_factor_to_downscale_index(const float downscale_factor);
+int IMB_downscale_index_to_downscale_factor(const IMB_Downscale downscale_index);
 
 /**
  *
@@ -393,7 +407,8 @@ int IMB_anim_get_image_height(struct anim *anim);
 struct ImBuf *IMB_anim_absolute(struct anim *anim,
                                 int position,
                                 IMB_Timecode_Type tc /* = 1 = IMB_TC_RECORD_RUN */,
-                                IMB_Proxy_Size preview_size /* = 0 = IMB_PROXY_NONE */);
+                                IMB_Proxy_Size preview_size /* = 0 = IMB_PROXY_NONE */,
+                                IMB_Downscale scale_factor);
 
 /**
  *
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 1239d3881de..77356e937d0 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -129,10 +129,11 @@ struct anim {
   int pFrameComplete;
   AVFrame *pFrameRGB;
   AVFrame *pFrameDeinterlaced;
-  struct SwsContext *img_convert_ctx;
+  struct SwsContext *img_convert_ctx[IMB_DOWNSCALE_MAX_SLOT];
   int videoStream;
 
   struct ImBuf *last_frame;
+  IMB_Downscale last_downscale_index;
   int64_t last_pts;
   int64_t next_pts;
   AVPacket next_packet;
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index c40e65b1c5c..20431f8944f 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -505,6 +505,101 @@ BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim)
   return (anim->x & 31) != 0;
 }
 
+IMB_Downscale IMB_downscale_factor_to_downscale_index(const float downscale_factor)
+{
+  if (downscale_factor > 32.0f) {
+    return IMB_DOWNSCALE_32X;
+  }
+
+  if (downscale_factor <= 1.0f) {
+    return IMB_DOWNSCALE_NONE;
+  }
+
+  return round_fl_to_int(log2(downscale_factor));
+}
+
+int IMB_downscale_index_to_downscale_factor(const IMB_Downscale downscale_index)
+{
+  switch (downscale_index) {
+    case IMB_DOWNSCALE_2X:
+      return 2;
+    case IMB_DOWNSCALE_4X:
+      return 4;
+    case IMB_DOWNSCALE_8X:
+      return 8;
+    case IMB_DOWNSCALE_16X:
+      return 16;
+    case IMB_DOWNSCALE_32X:
+      return 32;
+    default:
+      return 1;
+  }
+}
+
+static int ffmpeg_sws_context_alloc(struct anim *anim, const IMB_Downscale downscale_index)
+{
+  const int scale_factor = IMB_downscale_index_to_downscale_factor(downscale_index);
+  anim->img_convert_ctx[downscale_index] = sws_getContext(anim->x,
+                                                          anim->y,
+                                                          anim->pCodecCtx->pix_fmt,
+                                                          anim->x / scale_factor,
+                                                          anim->y / scale_factor,
+                                                          AV_PIX_FMT_RGBA,
+                                                          SWS_FAST_BILINEAR | SWS_PRINT_INFO |
+                                                              SWS_FULL_CHR_H_INT,
+                                                          NULL,
+                                                          NULL,
+                                                          NULL);
+
+  if (!anim->img_convert_ctx[downscale_index]) {
+    fprintf(stderr, "Can't transform color space??? Bailing out...\n");
+    avcodec_close(anim->pCodecCtx);
+    avformat_close_input(&anim->pFormatCtx);
+    av_frame_free(&anim->pFrameRGB);
+    av_frame_free(&anim->pFrameDeinterlaced);
+    av_frame_free(&anim->pFrame);
+    anim->pCodecCtx = NULL;
+    return -1;
+  }
+
+#  ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
+
+  /* The following for color space determination */
+  int srcRange, dstRange, brightness, contrast, saturation;
+  int *table;
+  const int *inv_table;
+
+  /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */
+  if (!sws_getColorspaceDetails(anim->img_convert_ctx[downscale_index],
+                                (int **)&inv_table,
+                                &srcRange,
+                                &table,
+                                &dstRange,
+                                &brightness,
+                                &contrast,
+                                &saturation)) {
+    srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG;
+    inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace);
+
+    if (sws_setColorspaceDetails(anim->img_convert_ctx[downscale_index],
+                                 (int *)inv_table,
+                                 srcRange,
+                                 table,
+                                 dstRange,
+                                 brightness,
+                                 contrast,
+                                 saturation)) {
+      fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n");
+    }
+  }
+  else {
+    fprintf(stderr, "Warning: Could no

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list