Compare commits

...

87 Commits

Author SHA1 Message Date
6f908dffe2 V2D navigating flag by Richard Antalik 2021-09-13 18:27:05 +05:30
f3d3e125b7 Small fix of using defined constant instead of immediate value 2021-09-03 14:53:29 +05:30
14d7721836 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-09-02 22:06:56 +05:30
6b8a5e78de Add changes requested in D12266 2021-09-02 21:58:33 +05:30
f9094bbc40 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-09-01 14:41:09 +05:30
e600fc482f Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-30 15:07:49 +05:30
bec129af27 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-22 20:49:41 +05:30
a68cdab213 Merge branch 'soc-2021-vse-strip-thumbnails' of git.blender.org:blender into soc-2021-vse-strip-thumbnails 2021-08-22 20:49:29 +05:30
9cb616d8aa VSE strip thumbnails
The goal is to provide thumbnails in the rectangle coloured strips. Works for
movie clips and image sequences. The thumbnails are loaded from source
using separate thread and stores them in cache. The drawing is called inside the
drawing for each strip, and takes images from cache. Drawing is below the
handles from one end of strip to other, inside view only. The job for caching
is called when images are not available, or there is view change.

All strip operations are valid, and overlap of strip adds transparency to the
image. Images are shown only when strip size is wide enough for clear
visibility of images, and the thumbnails represent source footage clearly.

Cache is limited to 5000 thumbnails and performs cleanup of non visible images
when limit crossed.

Related Task : T89143

Differential Revision: https://developer.blender.org/D12266
2021-08-19 15:36:02 +05:30
5d43ea0155 Fix limits on additional thumbs rendered. 2021-08-19 14:56:47 +05:30
95162f2aa9 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-19 13:34:00 +05:30
427265785d Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-19 11:55:55 +05:30
0973ec24a5 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-17 23:22:21 +05:30
1ed0d1971c Fix : Last thumb with error in crop values 2021-08-17 23:20:18 +05:30
8edbbf2221 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-16 23:26:58 +05:30
95ca2cd634 Fix : Switching off overlay now turns off thumbnails also 2021-08-16 19:50:06 +05:30
ee78603b35 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-16 10:18:37 +05:30
bf97bfb0ea Cleanup : C/C++ code style format 2021-08-15 19:02:42 +05:30
a224bcbcfc Correct Fix for pixel errors in the first thumbanail for each strip. 2021-08-15 15:24:43 +05:30
b20e00bda7 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-14 23:47:24 +05:30
3de92e5f21 Fix pixel errors when drawing first thumb 2021-08-14 23:42:39 +05:30
e66dc4beca Remove progress bar. Make transparent images on overlap during Transform 2021-08-14 00:21:23 +05:30
faf1210c0b Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-12 17:39:57 +05:30
15f33b0439 Add toggle button in overlay menu for thumbnail drawing toggle 2021-08-10 00:06:49 +05:30
9b08f523ec Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-09 18:11:06 +05:30
f9367f9399 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-06 16:02:14 +05:30
a31ebb5213 Fix limit on timeline_frame, remove global hash 2021-08-05 00:11:01 +05:30
68e5a340b5 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-08-03 16:30:09 +05:30
58677609ee Fix error on proxy building with thumbnail job and improve performance 2021-08-02 22:38:01 +05:30
4243f7fb7b Fix crash on adding new strip 2021-08-02 21:30:03 +05:30
e6c83f4cc0 Change conditions when to start caching. 2021-08-02 00:02:44 +05:30
a5b4f928fe Bug fixes - start frame value and IMB_crop assert failures 2021-08-01 00:11:14 +05:30
fea8bcc25c Testing global hash table to resuse duplciated seq
Should be replaced with storing hash in editing->runtime
2021-07-31 21:38:08 +05:30
57c79e07ce Fix conflicts in space_sequencer.c 2021-07-30 19:49:29 +05:30
433de045b7 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-30 19:29:04 +05:30
f96490446f Revert "Remove static variable usage. Increase extra images cached"
This reverts commit 72550b8dc7.
2021-07-30 19:28:43 +05:30
72550b8dc7 Remove static variable usage. Increase extra images cached 2021-07-27 23:45:09 +05:30
8d9f03e002 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-27 18:43:50 +05:30
8d5e49bdea Fixed memory free error 2021-07-25 01:17:21 +05:30
00efb3d18b Small fixes
Fixed the error in calculating the value of start_frame and shifted call to
add strips for caching job to new function. Memory free errors still remain.
Much Faster and better response if thumb not cached.
2021-07-25 00:57:07 +05:30
0ae42c6e74 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-25 00:56:43 +05:30
dd25a095ac Fast Multiple Strip THumbnail caching job - V2 plus cleanup
Cleaned up code. Much faster caching of thumbnails. Changed old thumbnail
cache limit checking code. Shift some operations to separate functions
2021-07-24 00:27:54 +05:30
11b9e782df Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-24 00:26:51 +05:30
a16ac64ea7 Faster Multiple strip support for Thumbnail drawing - V1
Multiple strips are added to hash and one thread can now do the rendering
work iterating over the strips. Still buggy and needs sorting out. Some
cases could lead to loop in thread.
2021-07-22 00:26:41 +05:30
cfcee229d2 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-21 18:49:03 +05:30
96d8b1eb7a Fix conditions to start Thumbnail Job
Jobs started when view changes or images not loading. Multiple strips now
work without error but slow. In the order of strips thumbs are loaded.
2021-07-18 17:00:54 +05:30
b0e5a377ae Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-18 17:00:02 +05:30
9e6127ac25 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-17 15:12:56 +05:30
58c8d7377b Fixed issue with strip slip 2021-07-14 13:59:20 +05:30
b72584e3dd Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-14 13:15:30 +05:30
825006e202 Fixed Refresh cache and strip slide error 2021-07-13 14:14:02 +05:30
fa003454fc Merge branch 'soc-2021-vse-strip-thumbnails' of git.blender.org:blender into soc-2021-vse-strip-thumbnails 2021-07-13 12:41:19 +05:30
3e51039ce6 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-13 12:40:30 +05:30
a75b089b58 Thumbnail Caching Job T89799
Differential Revision: https://developer.blender.org/D11885
2021-07-12 00:19:32 +05:30
73a819ad20 Fixed memory block free error 2021-07-12 00:12:35 +05:30
b3862fea0b Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-12 00:11:26 +05:30
688f5a0fe0 Thumbnail Job - Version 1
The current code has been tested and three areas it breaks.
1) refreshing a bunch of times
2) strip slide
3) multiple strips.
Multiple strip support is being worked on now. Other points are bugs.
2021-07-10 20:09:46 +05:30
f28759541f Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-10 18:12:11 +05:30
7d2f7886c7 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-08 17:59:03 +05:30
114b9ef9cd Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-07 13:50:53 +05:30
caf2ee76c0 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-07-01 17:30:03 +05:30
91c4e3e2a5 Changed ordering of drawing function in draw_seq_strip 2021-06-29 17:22:03 +05:30
a28c412b46 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-29 14:15:18 +05:30
d07dc28e0c Added changes specified in comments - D11718 2021-06-28 18:59:15 +05:30
3eb694dd3d Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-28 18:57:14 +05:30
c8c42d132a Merge branch 'soc-2021-vse-strip-thumbnails' of git.blender.org:blender into soc-2021-vse-strip-thumbnails 2021-06-28 18:55:01 +05:30
21a3dd756a Combined caching and thumbnail drawing code
Involves modification to the image rendering, caching and drawing. The
thumbs are fixed to 256 max size, the caching is limited in number
and the overall look of the thumbnails is proper (no incorrect clipping).

Maniphest task : T89143

Differential Revision: https://developer.blender.org/D11718
2021-06-27 19:31:14 +05:30
bad23a721f Thumbnail Code Cleanup
Improved from the hacky way of cropping using the same process for scaling
to thumb size to using dedicated IMB_rect_crop method. Cleaned up
unnecessary code and variables.
2021-06-27 18:39:06 +05:30
9f5d9c1629 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-27 10:14:36 +05:30
d2c95bd7e4 Strip thumbnail drawing Fix : Thumbnails crop to exact width of strip
The end thumbnails crop to the exact left and right edges of the strip.
The previous version had poor clipping of thumbnails.
2021-06-26 23:51:15 +05:30
d3df935741 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-26 23:50:24 +05:30
d802bf30b4 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-25 00:00:19 +05:30
0374114aca Cache limit : Set a limit of 1000 thumbs that can be cached giving around
160MB of memory for thumbs. Once the limit is reached, all cached thumbs
before and after the current view x limits are removed.
2021-06-24 23:56:16 +05:30
2696fca1a0 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-23 17:53:23 +05:30
ebe7abb677 Pushed all thumbnail rendering and caching code to new function. Cleaned up
all conditions using context->is_thumb.
2021-06-22 23:13:18 +05:30
c32ddae847 Cleanup : Fixed the thumbnail size to max 256 for any dimension. Removed
scaling and cropping from UI - hard scale to match result dimensions and
no crop. Removed any further preprocessing as the thumbnails should represent
original source footage. any rotation or tranform could confuse users as to
what the strip original footage was.
2021-06-22 18:07:54 +05:30
fbae0d75bc Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-22 15:21:15 +05:30
df579a3b6d Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-20 20:01:29 +05:30
4b03995ce5 Thumbnail Cache fix : thumbs get loaded and not cleared when preview on 2021-06-20 20:00:20 +05:30
c2b0164b6e Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-19 22:52:32 +05:30
df171bf8bc Thumbnail Caching
The caching code is updated to allow for separate thumbnail storage. The size
is taken as 0.25*render size as of now. flag set up to control when to store
thumbs. Image scaling done in preprocess stage using already present code for
crop and transform.
2021-06-19 22:47:00 +05:30
92d06984e4 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-18 17:28:52 +05:30
dc2dc9ffaf Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-17 18:05:31 +05:30
09c28f9b16 VSE strip thumbnail improvements
The left handle now slides over the thumbs when moving and updates the thumb
under the left handle to represent seq->startdisp. Strip slip offset has fixed
thumbs and they don't update images as they move but rather move along with the
strip itself. Helps to make the strip feel like it is a container for the movie
and the handle areas cut the movie to the strip size. Better UX.
2021-06-16 23:43:30 +05:30
96c50ae2ba VSE strip thumbnail drawing function
Thumbnail Drawing Function Improvements T89144

The previous version drew the thumbnails but didn't take into consideration
The visible range where the thumbs should be seen and tried to draw till
end of strip. This version considers only those thumbails which can be seen
and leads to large performance gain. Multiple strips can be used smoothly.
Drawing logic was change to keep same thumbs when strip slide operation was
performed.

Differential Revision: https://developer.blender.org/D11616
2021-06-16 00:25:29 +05:30
e169120c81 Merge branch 'master' into soc-2021-vse-strip-thumbnails 2021-06-15 15:03:07 +05:30
b18373ef6a VSE strip thumbnail drawing function 2021-06-14 00:38:38 +05:30
19 changed files with 678 additions and 13 deletions

View File

@@ -250,7 +250,8 @@ class SEQUENCER_PT_sequencer_overlay(Panel):
layout.prop(st, "show_strip_offset", text="Offsets")
layout.prop(st, "show_fcurves", text="F-Curves")
layout.prop(st, "show_grid", text="Grid")
layout.prop(st, "show_thumbnails", text="Thumbnails")
layout.separator()
layout.prop_menu_enum(st, "waveform_display_type")

View File

@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 20
#define BLENDER_FILE_SUBVERSION 21
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@@ -1111,6 +1111,32 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 20)) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_SEQ) {
SpaceSeq *sseq = (SpaceSeq *)sl;
sseq->flag |= SEQ_SHOW_THUMBNAILS;
}
}
}
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 21)) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_SEQ) {
SpaceSeq *sseq = (SpaceSeq *)sl;
sseq->flag |= SEQ_SHOW_THUMBNAILS;
}
}
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@@ -157,7 +157,7 @@ static void blo_update_defaults_screen(bScreen *screen,
SpaceSeq *seq = area->spacedata.first;
seq->flag |= SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES | SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY |
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_NAME | SEQ_SHOW_STRIP_DURATION |
SEQ_SHOW_GRID;
SEQ_SHOW_GRID | SEQ_SHOW_THUMBNAILS;
seq->render_size = SEQ_RENDER_SIZE_PROXY_100;
seq->flag |= SEQ_USE_PROXIES;

View File

@@ -5823,6 +5823,11 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
icon = ICON_SEQUENCE;
break;
}
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL)) {
handle_event = B_STOPSEQ;
icon = ICON_SEQUENCE;
break;
}
if (WM_jobs_test(wm, scene, WM_JOB_TYPE_CLIP_BUILD_PROXY)) {
handle_event = B_STOPCLIP;
icon = ICON_TRACKER;

View File

@@ -147,6 +147,8 @@ static void view_pan_init(bContext *C, wmOperator *op)
const float winy = (float)(BLI_rcti_size_y(&vpd->region->winrct) + 1);
vpd->facx = (BLI_rctf_size_x(&vpd->v2d->cur)) / winx;
vpd->facy = (BLI_rctf_size_y(&vpd->v2d->cur)) / winy;
vpd->v2d->flag |= V2D_IS_NAVIGATING;
}
/* apply transform to view (i.e. adjust 'cur' rect) */
@@ -190,6 +192,8 @@ static void view_pan_apply(bContext *C, wmOperator *op)
/* Cleanup temp custom-data. */
static void view_pan_exit(wmOperator *op)
{
v2dViewPanData *vpd = op->customdata;
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
MEM_SAFE_FREE(op->customdata);
}
@@ -305,7 +309,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
static void view_pan_cancel(bContext *UNUSED(C), wmOperator *op)
static void view_pan_cancel(bContext *C, wmOperator *op)
{
view_pan_exit(op);
}
@@ -358,6 +362,7 @@ static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event
View2DEdgePanData *vpd = op->customdata;
if (event->val == KM_RELEASE || event->type == EVT_ESCKEY) {
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
MEM_SAFE_FREE(op->customdata);
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
@@ -371,6 +376,8 @@ static int view_edge_pan_modal(bContext *C, wmOperator *op, const wmEvent *event
static void view_edge_pan_cancel(bContext *UNUSED(C), wmOperator *op)
{
v2dViewPanData *vpd = op->customdata;
vpd->v2d->flag &= ~V2D_IS_NAVIGATING;
MEM_SAFE_FREE(op->customdata);
}
@@ -680,6 +687,8 @@ static void view_zoomdrag_init(bContext *C, wmOperator *op)
vzd->v2d = &vzd->region->v2d;
/* False by default. Interactive callbacks (ie invoke()) can set it to true. */
vzd->zoom_to_mouse_pos = false;
vzd->v2d->flag |= V2D_IS_NAVIGATING;
}
/* apply transform to view (i.e. adjust 'cur' rect) */
@@ -809,7 +818,8 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
static void view_zoomstep_exit(wmOperator *op)
{
UI_view2d_zoom_cache_reset();
v2dViewZoomData *vzd = op->customdata;
vzd->v2d->flag &= ~V2D_IS_NAVIGATING;
MEM_SAFE_FREE(op->customdata);
}
@@ -1041,6 +1051,7 @@ static void view_zoomdrag_exit(bContext *C, wmOperator *op)
if (op->customdata) {
v2dViewZoomData *vzd = op->customdata;
vzd->v2d->flag &= ~V2D_IS_NAVIGATING;
if (vzd->timer) {
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer);

View File

@@ -25,6 +25,7 @@
#include <string.h>
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@@ -1277,6 +1278,391 @@ static void draw_seq_fcurve_overlay(
}
}
typedef struct ThumbnailDrawJob {
SeqRenderData context;
GHash *sequences_ghash;
Scene *scene;
rctf *view_area;
float pixelx;
float pixely;
} ThumbnailDrawJob;
typedef struct ThumbDataItem {
Sequence *seq_dupli;
Scene *scene;
} ThumbDataItem;
static void thumbnail_hash_data_free(void *val)
{
ThumbDataItem *item = val;
SEQ_sequence_free(item->scene, item->seq_dupli, 0);
MEM_freeN(val);
}
static void thumbnail_freejob(void *data)
{
ThumbnailDrawJob *tj = data;
BLI_ghash_free(tj->sequences_ghash, NULL, thumbnail_hash_data_free);
MEM_freeN(tj->view_area);
MEM_freeN(tj);
}
static void thumbnail_endjob(void *data)
{
ThumbnailDrawJob *tj = data;
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene);
}
static bool check_seq_need_thumbnails(Sequence *seq, rctf *view_area)
{
if (seq->type != SEQ_TYPE_MOVIE && seq->type != SEQ_TYPE_IMAGE) {
return false;
}
if (min_ii(seq->startdisp, seq->start) > view_area->xmax) {
return false;
}
else if (max_ii(seq->enddisp, seq->start + seq->len) < view_area->xmin) {
return false;
}
else if (seq->machine + 1.0f < view_area->ymin) {
return false;
}
else if (seq->machine > view_area->ymax) {
return false;
}
return true;
}
static void seq_get_thumb_image_dimensions(Sequence *seq,
float pixelx,
float pixely,
float *r_thumb_width,
float *r_thumb_height,
float *r_image_width,
float *r_image_height)
{
float image_width = seq->strip->stripdata->orig_width;
float image_height = seq->strip->stripdata->orig_height;
/* Fix the dimensions to be max SEQ_RENDER_THUMB_SIZE (256) for x or y. */
float aspect_ratio = (float)image_width / image_height;
if (image_width > image_height) {
image_width = SEQ_RENDER_THUMB_SIZE;
image_height = round_fl_to_int(image_width / aspect_ratio);
}
else {
image_height = SEQ_RENDER_THUMB_SIZE;
image_width = round_fl_to_int(image_height * aspect_ratio);
}
/* Calculate thumb dimensions. */
float thumb_height = (SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM) - (20 * U.dpi_fac * pixely);
aspect_ratio = ((float)image_width) / image_height;
float thumb_h_px = thumb_height / pixely;
float thumb_width = aspect_ratio * thumb_h_px * pixelx;
if (r_thumb_height == NULL) {
*r_thumb_width = thumb_width;
return;
}
*r_thumb_height = thumb_height;
*r_image_width = image_width;
*r_image_height = image_height;
*r_thumb_width = thumb_width;
}
static float seq_thumbnail_get_start_frame(Sequence *seq, float frame_step, rctf *view_area)
{
if (seq->start > view_area->xmin) {
return seq->start;
}
/* Drawing and caching both check to see if stristart_framep is in view area or not before
* calling this function so assuming strip/part of strip in view. */
int no_invisible_thumbs = (view_area->xmin - seq->start) / frame_step;
return ((no_invisible_thumbs - 1) * frame_step) + seq->start;
}
static void thumbnail_start_job(void *data, short *stop, short *do_update, float *progress)
{
ThumbnailDrawJob *tj = data;
float start_frame, frame_step;
GHashIterator gh_iter;
BLI_ghashIterator_init(&gh_iter, tj->sequences_ghash);
while (!BLI_ghashIterator_done(&gh_iter) & !*stop) {
Sequence *seq_orig = BLI_ghashIterator_getKey(&gh_iter);
ThumbDataItem *val = BLI_ghash_lookup(tj->sequences_ghash, seq_orig);
if (check_seq_need_thumbnails(seq_orig, tj->view_area)) {
seq_get_thumb_image_dimensions(
val->seq_dupli, tj->pixelx, tj->pixely, &frame_step, NULL, NULL, NULL);
start_frame = seq_thumbnail_get_start_frame(seq_orig, frame_step, tj->view_area);
SEQ_render_thumbnails(
&tj->context, val->seq_dupli, seq_orig, start_frame, frame_step, tj->view_area, stop);
}
BLI_ghashIterator_step(&gh_iter);
}
UNUSED_VARS(do_update, progress);
}
static SeqRenderData sequencer_thumbnail_context_init(const bContext *C)
{
struct Main *bmain = CTX_data_main(C);
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
SpaceSeq *sseq = CTX_wm_space_seq(C);
SeqRenderData context = {0};
/* Taking rectx and recty as 0 as dimensions not known here, and context is used to calculate
* hash key but not necessary as other variables of SeqRenderData are unique enough. */
SEQ_render_new_render_data(bmain, depsgraph, scene, 0, 0, sseq->render_size, false, &context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, STEREO_LEFT_NAME);
context.use_proxies = false;
return context;
}
static GHash *sequencer_thumbnail_ghash_init(const bContext *C, View2D *v2d, Editing *ed)
{
Scene *scene = CTX_data_scene(C);
/* Set the data for thumbnail caching job. */
GHash *thumb_data_hash = BLI_ghash_ptr_new("seq_duplicates_and_origs");
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
ThumbDataItem *val_need_update = BLI_ghash_lookup(thumb_data_hash, seq);
if (val_need_update == NULL && check_seq_need_thumbnails(seq, &v2d->cur)) {
ThumbDataItem *val = MEM_callocN(sizeof(ThumbDataItem), "Thumbnail Hash Values");
val->seq_dupli = SEQ_sequence_dupli_recursive(scene, scene, NULL, seq, 0);
val->scene = scene;
BLI_ghash_insert(thumb_data_hash, seq, val);
}
else {
if (val_need_update != NULL) {
val_need_update->seq_dupli->start = seq->start;
val_need_update->seq_dupli->startdisp = seq->startdisp;
}
}
}
return thumb_data_hash;
}
static void sequencer_thumbnail_init_job(const bContext *C, View2D *v2d, Editing *ed)
{
wmJob *wm_job;
ThumbnailDrawJob *tj = NULL;
ScrArea *area = CTX_wm_area(C);
wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
CTX_data_scene(C),
"Draw Thumbnails",
0,
WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL);
/* Get the thumbnail job if it exists. */
tj = WM_jobs_customdata_get(wm_job);
if (!tj) {
tj = MEM_callocN(sizeof(ThumbnailDrawJob), "Thumbnail cache job");
/* Duplicate value of v2d->cur and v2d->tot to have module separation. */
rctf *view_area = MEM_callocN(sizeof(struct rctf), "viewport area");
view_area->xmax = v2d->cur.xmax;
view_area->xmin = v2d->cur.xmin;
view_area->ymax = v2d->cur.ymax;
view_area->ymin = v2d->cur.ymin;
tj->scene = CTX_data_scene(C);
tj->view_area = view_area;
tj->context = sequencer_thumbnail_context_init(C);
tj->sequences_ghash = sequencer_thumbnail_ghash_init(C, v2d, ed);
tj->pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
tj->pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
WM_jobs_customdata_set(wm_job, tj, thumbnail_freejob);
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
WM_jobs_callbacks(wm_job, thumbnail_start_job, NULL, NULL, thumbnail_endjob);
}
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
else {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
}
ED_area_tag_redraw(area);
}
static void sequencer_thumbnail_start_job_if_necessary(const bContext *C,
Editing *ed,
View2D *v2d,
bool thumbnail_is_missing)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
if ((v2d->flag & V2D_IS_NAVIGATING) != 0) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
return;
}
/* Leftover is set to true if missing image in strip. False when normal call to all strips done.
*/
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax || thumbnail_is_missing) {
/* Stop the job first as view has changed. Pointless to continue old job. */
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax) {
WM_jobs_stop(CTX_wm_manager(C), NULL, thumbnail_start_job);
}
sequencer_thumbnail_init_job(C, v2d, ed);
sseq->runtime.last_thumbnail_area = v2d->cur;
}
}
/* Don't display thumbnails only when zooming. Panning doesn't cause issues. */
static bool sequencer_thumbnail_v2d_is_navigating(const bContext *C)
{
ARegion *region = CTX_wm_region(C);
View2D *v2d = &region->v2d;
SpaceSeq *sseq = CTX_wm_space_seq(C);
if ((v2d->flag & V2D_IS_NAVIGATING) == 0) {
return false;
}
double x_diff = fabs(BLI_rctf_size_x(&sseq->runtime.last_thumbnail_area) -
BLI_rctf_size_x(&v2d->cur));
double y_diff = fabs(BLI_rctf_size_y(&sseq->runtime.last_thumbnail_area) -
BLI_rctf_size_y(&v2d->cur));
return x_diff > 0.01 || y_diff > 0.01;
}
static void draw_seq_strip_thumbnail(View2D *v2d,
const bContext *C,
Scene *scene,
Sequence *seq,
float y1,
float y2,
float pixelx,
float pixely)
{
bool clipped = false;
float image_height, image_width, thumb_width, thumb_height;
rcti crop;
/* If width of the strip too small ignore drawing thumbnails. */
if ((y2 - y1) / pixely <= 40 * U.dpi_fac)
return;
if (sequencer_thumbnail_v2d_is_navigating(C)) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
return;
}
SeqRenderData context = sequencer_thumbnail_context_init(C);
seq_get_thumb_image_dimensions(
seq, pixelx, pixely, &thumb_width, &thumb_height, &image_width, &image_height);
float thumb_y_end = y1 + thumb_height - pixely;
float thumb_x_start = seq->start;
float cut_off = 0;
float upper_thumb_bound = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
if (seq->type == SEQ_TYPE_IMAGE) {
upper_thumb_bound = seq->enddisp;
}
/* Start drawing. */
thumb_x_start = seq_thumbnail_get_start_frame(seq, thumb_width, &v2d->cur);
float thumb_x_end;
while (thumb_x_start < upper_thumb_bound) {
thumb_x_end = thumb_x_start + thumb_width;
clipped = false;
/* Checks to make sure that thumbs are loaded only when in view and within the confines of the
* strip. Some may not be required but better to have conditions for safety as x1 here is
* point to start caching from and not drawing. */
if (thumb_x_start > v2d->cur.xmax)
break;
if (thumb_x_end < v2d->cur.xmin) {
thumb_x_start = thumb_x_end;
continue;
}
/* Ignore thumbs to the left of strip. */
if (thumb_x_end < seq->startdisp) {
thumb_x_start = thumb_x_end;
continue;
}
/* Set the clipping bound to show the left handle moving over thumbs and not shift thumbs. */
if (IN_RANGE_INCL(seq->startdisp, thumb_x_start, thumb_x_end)) {
cut_off = seq->startdisp - thumb_x_start;
clipped = true;
}
/* Clip if full thumbnail cannot be displayed. */
if (thumb_x_end > (upper_thumb_bound)) {
thumb_x_end = upper_thumb_bound;
clipped = true;
if (thumb_x_end - thumb_x_start < 1)
break;
}
float zoom_x = thumb_width / image_width;
float zoom_y = thumb_height / image_height;
float cropx_min = (cut_off / pixelx) / (zoom_y / pixely);
float cropx_max = ((thumb_x_end - thumb_x_start) / pixelx) / (zoom_y / pixely);
if (cropx_max == (thumb_x_end - thumb_x_start)) {
cropx_max = cropx_max + 1;
}
BLI_rcti_init(&crop, (int)(cropx_min), (int)cropx_max, 0, (int)(image_height)-1);
/* Get the image. */
ImBuf *ibuf = SEQ_get_thumbnail(&context, seq, roundf(thumb_x_start), &crop, clipped);
if (!ibuf) {
sequencer_thumbnail_start_job_if_necessary(C, scene->ed, v2d, true);
break;
}
/* Transparency on overlap. */
if (seq->flag & SEQ_OVERLAP) {
GPU_blend(GPU_BLEND_ALPHA);
unsigned char *buf = (unsigned char *)ibuf->rect;
for (int pixel = ibuf->x * ibuf->y; pixel--; buf += 4) {
buf[3] = OVERLAP_ALPHA;
}
}
ED_draw_imbuf_ctx_clipping(C,
ibuf,
thumb_x_start + cut_off,
y1,
true,
thumb_x_start + cut_off,
y1,
thumb_x_end,
thumb_y_end,
zoom_x,
zoom_y);
IMB_freeImBuf(ibuf);
GPU_blend(GPU_BLEND_NONE);
cut_off = 0;
thumb_x_start = thumb_x_end;
}
}
/* Draw visible strips. Bounds check are already made. */
static void draw_seq_strip(const bContext *C,
SpaceSeq *sseq,
@@ -1348,6 +1734,11 @@ static void draw_seq_strip(const bContext *C,
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_THUMBNAILS) &&
(seq->type == SEQ_TYPE_MOVIE || seq->type == SEQ_TYPE_IMAGE)) {
draw_seq_strip_thumbnail(v2d, C, scene, seq, y1, y2, pixelx, pixely);
}
if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY) && (sseq->flag & SEQ_SHOW_FCURVES)) {
draw_seq_fcurve_overlay(scene, v2d, seq, x1, y1, x2, y2, pixelx);
}
@@ -2194,6 +2585,8 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *region)
int sel = 0, j;
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
sequencer_thumbnail_start_job_if_necessary(C, ed, v2d, false);
/* Loop through twice, first unselected, then selected. */
for (j = 0; j < 2; j++) {
Sequence *seq;

View File

@@ -579,7 +579,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
{
/* Only data types supported for now. */
Editing *ed = SEQ_editing_get(scene);
bool changed = false;
/* Iterate in reverse so meta-strips are iterated after their children. */
@@ -633,7 +632,10 @@ static bool sequencer_slip_recursively(Scene *scene, SlipData *data, int offset)
}
}
if (changed) {
SEQ_relations_free_imbuf(scene, &ed->seqbase, false);
for (int i = data->num_seq - 1; i >= 0; i--) {
Sequence *seq = data->seq_array[i];
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
}
return changed;
}

View File

@@ -100,8 +100,11 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS | SEQ_SHOW_FCURVES |
SEQ_ZOOM_TO_FIT | SEQ_SHOW_STRIP_OVERLAY | SEQ_SHOW_STRIP_NAME |
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION | SEQ_SHOW_GRID;
SEQ_SHOW_STRIP_SOURCE | SEQ_SHOW_STRIP_DURATION | SEQ_SHOW_GRID |
SEQ_SHOW_THUMBNAILS;
struct rctf temp = {0, 0, 0, 0};
sseq->runtime.last_thumbnail_area = temp;
/* Tool header. */
region = MEM_callocN(sizeof(ARegion), "tool header for sequencer");

View File

@@ -722,6 +722,7 @@ enum {
SEQ_CACHE_PREFETCH_ENABLE = (1 << 10),
SEQ_CACHE_DISK_CACHE_ENABLE = (1 << 11),
SEQ_CACHE_STORE_THUMBNAIL = (1 << 12),
};
#ifdef __cplusplus

View File

@@ -576,6 +576,10 @@ typedef enum eSpaceNla_Flag {
/** \name Sequence Editor
* \{ */
typedef struct SpaceSeqRuntime {
struct rctf last_thumbnail_area;
} SpaceSeqRuntime;
/* Sequencer */
typedef struct SpaceSeq {
SpaceLink *next, *prev;
@@ -616,6 +620,10 @@ typedef struct SpaceSeq {
/** Multiview current eye - for internal use. */
char multiview_eye;
char _pad2[7];
/** Required for Thumbnail caching job call condition */
SpaceSeqRuntime runtime;
} SpaceSeq;
/* SpaceSeq.mainb */
@@ -655,6 +663,7 @@ typedef enum eSpaceSeq_Flag {
SEQ_SHOW_STRIP_DURATION = (1 << 16),
SEQ_USE_PROXIES = (1 << 17),
SEQ_SHOW_GRID = (1 << 18),
SEQ_SHOW_THUMBNAILS = (1 << 19),
} eSpaceSeq_Flag;
/* SpaceSeq.view */

View File

@@ -132,6 +132,8 @@ enum {
V2D_PIXELOFS_X = (1 << 2),
/* apply pixel offsets on y-axis when setting view matrices */
V2D_PIXELOFS_Y = (1 << 3),
/* zoom, pan or similar action is in progress */
V2D_IS_NAVIGATING = (1 << 9),
/* view settings need to be set still... */
V2D_IS_INIT = (1 << 10),
};

View File

@@ -5561,6 +5561,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GRID);
RNA_def_property_ui_text(prop, "Show Grid", "Show vertical grid lines");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
prop = RNA_def_property(srna, "show_thumbnails", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_THUMBNAILS);
RNA_def_property_ui_text(prop, "Show Thumbnails", "Show strip thumbnails");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
}
static void rna_def_space_text(BlenderRNA *brna)

View File

@@ -27,6 +27,8 @@
extern "C" {
#endif
#define SEQ_RENDER_THUMB_SIZE 256
struct ListBase;
struct Main;
struct Scene;
@@ -67,6 +69,15 @@ struct ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context,
struct ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
float timeline_frame,
struct Sequence *seq);
void SEQ_render_thumbnails(struct SeqRenderData *context,
struct Sequence *seq,
struct Sequence *seq_orig,
float start_frame,
float frame_step,
rctf *view_area,
short *stop);
struct ImBuf *SEQ_get_thumbnail(
SeqRenderData *context, struct Sequence *seq, float timeline_frame, rcti *crop, bool clipped);
void SEQ_render_init_colorspace(struct Sequence *seq);
void SEQ_render_new_render_data(struct Main *bmain,
struct Depsgraph *depsgraph,

View File

@@ -104,6 +104,7 @@
#define DCACHE_IMAGES_PER_FILE 100
#define DCACHE_CURRENT_VERSION 2
#define COLORSPACE_NAME_MAX 64 /* XXX: defined in imb intern */
#define THUMB_CACHE_LIMIT 5000
typedef struct DiskCacheHeaderEntry {
unsigned char encoding;
@@ -148,6 +149,7 @@ typedef struct SeqCache {
struct BLI_mempool *items_pool;
struct SeqCacheKey *last_key;
SeqDiskCache *disk_cache;
int thumbnail_count;
} SeqCache;
typedef struct SeqCacheItem {
@@ -776,7 +778,7 @@ static float seq_cache_timeline_frame_to_frame_index(Sequence *seq, float timeli
/* With raw images, map timeline_frame to strip input media frame range. This means that static
* images or extended frame range of movies will only generate one cache entry. No special
* treatment in converting frame index to timeline_frame is needed. */
if (type == SEQ_CACHE_STORE_RAW) {
if (type == SEQ_CACHE_STORE_RAW || type == SEQ_CACHE_STORE_THUMBNAIL) {
return seq_give_frame_index(seq, timeline_frame);
}
@@ -875,7 +877,7 @@ static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf)
if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) {
IMB_refImBuf(ibuf);
if (!key->is_temp_cache) {
if (!key->is_temp_cache || key->type != SEQ_CACHE_STORE_THUMBNAIL) {
cache->last_key = key;
}
}
@@ -1161,6 +1163,7 @@ static void seq_cache_create(Main *bmain, Scene *scene)
cache->hash = BLI_ghash_new(seq_cache_hashhash, seq_cache_hashcmp, "SeqCache hash");
cache->last_key = NULL;
cache->bmain = bmain;
cache->thumbnail_count = 0;
BLI_mutex_init(&cache->iterator_mutex);
scene->ed->cache = cache;
@@ -1217,7 +1220,7 @@ void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame)
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
if (key->is_temp_cache && key->task_id == id) {
if (key->is_temp_cache && key->task_id == id && key->type != SEQ_CACHE_STORE_THUMBNAIL) {
/* Use frame_index here to avoid freeing raw images if they are used for multiple frames. */
float frame_index = seq_cache_timeline_frame_to_frame_index(
key->seq, timeline_frame, key->type);
@@ -1278,6 +1281,7 @@ void SEQ_cache_cleanup(Scene *scene)
BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
}
cache->last_key = NULL;
cache->thumbnail_count = 0;
seq_cache_unlock(scene);
}
@@ -1345,6 +1349,39 @@ void seq_cache_cleanup_sequence(Scene *scene,
seq_cache_unlock(scene);
}
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area_safe)
{
/* Add offsets to the left and right end to keep some frames in cache. */
view_area_safe->xmax += 200;
view_area_safe->xmin -= 200;
view_area_safe->ymin -= 1;
view_area_safe->ymax += 1;
SeqCache *cache = seq_cache_get_from_scene(scene);
if (!cache) {
return;
}
GHashIterator gh_iter;
BLI_ghashIterator_init(&gh_iter, cache->hash);
while (!BLI_ghashIterator_done(&gh_iter)) {
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
if ((key->type & SEQ_CACHE_STORE_THUMBNAIL) &&
(key->timeline_frame > view_area_safe->xmax ||
key->timeline_frame < view_area_safe->xmin || key->seq->machine > view_area_safe->ymax ||
key->seq->machine < view_area_safe->ymin)) {
if (key->link_next || key->link_prev) {
seq_cache_relink_keys(key->link_next, key->link_prev);
}
cache->thumbnail_count--;
BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
}
}
cache->last_key = NULL;
}
struct ImBuf *seq_cache_get(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
@@ -1436,6 +1473,37 @@ bool seq_cache_put_if_possible(
return false;
}
void seq_cache_thumbnail_put(
const SeqRenderData *context, Sequence *seq, float timeline_frame, ImBuf *i, rctf *view_area)
{
Scene *scene = context->scene;
if (!scene->ed->cache) {
seq_cache_create(context->bmain, scene);
}
seq_cache_lock(scene);
SeqCache *cache = seq_cache_get_from_scene(scene);
SeqCacheKey *key = seq_cache_allocate_key(
cache, context, seq, timeline_frame, SEQ_CACHE_STORE_THUMBNAIL);
/* Prevent reinserting, it breaks cache key linking. */
if (BLI_ghash_haskey(cache->hash, key)) {
seq_cache_unlock(scene);
return;
}
/* Limit cache to THUMB_CACHE_LIMIT (5000) images stored. */
if (cache->thumbnail_count >= THUMB_CACHE_LIMIT) {
rctf view_area_safe = *view_area;
seq_cache_thumbnail_cleanup(scene, &view_area_safe);
}
seq_cache_put_ex(scene, key, i);
cache->thumbnail_count++;
seq_cache_unlock(scene);
}
void seq_cache_put(
const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i)
{

View File

@@ -46,6 +46,11 @@ void seq_cache_put(const struct SeqRenderData *context,
float timeline_frame,
int type,
struct ImBuf *i);
void seq_cache_thumbnail_put(const struct SeqRenderData *context,
struct Sequence *seq,
float timeline_frame,
struct ImBuf *i,
rctf *view_area);
bool seq_cache_put_if_possible(const struct SeqRenderData *context,
struct Sequence *seq,
float timeline_frame,
@@ -60,6 +65,7 @@ void seq_cache_cleanup_sequence(struct Scene *scene,
struct Sequence *seq_changed,
int invalidate_types,
bool force_seq_changed_range);
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area);
bool seq_cache_is_full(void);
#ifdef __cplusplus

View File

@@ -527,6 +527,31 @@ static void sequencer_image_crop_init(const Sequence *seq,
BLI_rctf_init(r_crop, left, in->x - right, bottom, in->y - top);
}
static void sequencer_thumbnail_transform(ImBuf *in, ImBuf *out)
{
float image_scale_factor = (float)out->x / in->x;
float transform_matrix[3][3];
/* Set to keep same loc,scale,rot but change scale to thumb size limit. */
const float scale_x = 1 * image_scale_factor;
const float scale_y = 1 * image_scale_factor;
const float image_center_offs_x = (out->x - in->x) / 2;
const float image_center_offs_y = (out->y - in->y) / 2;
const float pivot[2] = {in->x / 2, in->y / 2};
loc_rot_size_to_mat3(transform_matrix,
(const float[]){image_center_offs_x, image_center_offs_y},
0,
(const float[]){scale_x, scale_y});
transform_pivot_set_m3(transform_matrix, pivot);
invert_m3(transform_matrix);
/* No crop. */
rctf source_crop;
BLI_rctf_init(&source_crop, 0, in->x, 0, in->y);
IMB_transform(in, out, transform_matrix, &source_crop, IMB_FILTER_NEAREST);
}
static void sequencer_preprocess_transform_crop(
ImBuf *in, ImBuf *out, const SeqRenderData *context, Sequence *seq, const bool is_proxy_image)
{
@@ -1989,7 +2014,103 @@ ImBuf *SEQ_render_give_ibuf_direct(const SeqRenderData *context,
seq_render_state_init(&state);
ImBuf *ibuf = seq_render_strip(context, &state, seq, timeline_frame);
return ibuf;
}
/* Gets the direct image from source and scales to thumbnail size. */
static ImBuf *seq_get_uncached_thumbnail(SeqRenderData *context,
SeqRenderState *state,
Sequence *seq,
float timeline_frame)
{
bool is_proxy_image = false;
ImBuf *ibuf = do_render_strip_uncached(context, state, seq, timeline_frame, &is_proxy_image);
if (ibuf == NULL) {
return NULL;
}
float aspect_ratio = (float)ibuf->x / ibuf->y;
int rectx, recty;
/* Calculate new dimensions - THUMB_SIZE (256) for x or y. */
if (ibuf->x > ibuf->y) {
rectx = SEQ_RENDER_THUMB_SIZE;
recty = round_fl_to_int(rectx / aspect_ratio);
}
else {
recty = SEQ_RENDER_THUMB_SIZE;
rectx = round_fl_to_int(recty * aspect_ratio);
}
/* Scale ibuf to thumbnail size. */
ImBuf *scaled_ibuf = IMB_allocImBuf(rectx, recty, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
sequencer_thumbnail_transform(ibuf, scaled_ibuf);
seq_imbuf_assign_spaces(context->scene, scaled_ibuf);
IMB_freeImBuf(ibuf);
return scaled_ibuf;
}
/* Get cached thumbnails. */
ImBuf *SEQ_get_thumbnail(
SeqRenderData *context, Sequence *seq, float timeline_frame, rcti *crop, bool clipped)
{
ImBuf *ibuf = seq_cache_get(context, seq, roundf(timeline_frame), SEQ_CACHE_STORE_THUMBNAIL);
if (!clipped || ibuf == NULL) {
return ibuf;
}
/* Do clipping. */
ImBuf *ibuf_cropped = IMB_dupImBuf(ibuf);
if (crop->xmin < 0 || crop->ymin < 0) {
crop->xmin = 0;
crop->ymin = 0;
}
if (crop->xmax >= ibuf->x || crop->ymax >= ibuf->y) {
crop->xmax = ibuf->x - 1;
crop->ymax = ibuf->y - 1;
}
IMB_rect_crop(ibuf_cropped, crop);
IMB_freeImBuf(ibuf);
return ibuf_cropped;
}
/* Render the series of thumbnails and store in cache. */
void SEQ_render_thumbnails(SeqRenderData *context,
Sequence *seq,
Sequence *seq_orig,
float start_frame,
float frame_step,
rctf *view_area,
short *stop)
{
SeqRenderState state;
seq_render_state_init(&state);
/* Adding the hold offset value (seq->anim_startofs) to the start frame. Position of image not
* affected, but frame loaded affected. */
start_frame = start_frame - 5 * frame_step;
float upper_thumb_bound = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
upper_thumb_bound = (upper_thumb_bound > view_area->xmax) ? view_area->xmax + 5 * frame_step :
upper_thumb_bound;
while ((start_frame < upper_thumb_bound) & !*stop) {
ImBuf *ibuf = seq_cache_get(context, seq_orig, roundf(start_frame), SEQ_CACHE_STORE_THUMBNAIL);
if (ibuf) {
IMB_freeImBuf(ibuf);
start_frame += frame_step;
continue;
}
ibuf = seq_get_uncached_thumbnail(context, &state, seq, roundf(start_frame));
if (ibuf) {
seq_cache_thumbnail_put(context, seq_orig, roundf(start_frame), ibuf, view_area);
IMB_freeImBuf(ibuf);
}
start_frame += frame_step;
}
}
/** \} */

View File

@@ -781,6 +781,7 @@ enum {
WM_JOB_TYPE_QUADRIFLOW_REMESH,
WM_JOB_TYPE_TRACE_IMAGE,
WM_JOB_TYPE_LINEART,
WM_JOB_TYPE_SEQ_DRAW_THUMBNAIL,
/* add as needed, bake, seq proxy build
* if having hard coded values is a problem */
};

View File

@@ -230,7 +230,7 @@ bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) {
if (wm_job->owner == owner) {
if (ELEM(job_type, WM_JOB_TYPE_ANY, wm_job->job_type)) {
if (wm_job->running || wm_job->suspended) {
if ((wm_job->flag & WM_JOB_PROGRESS) && (wm_job->running || wm_job->suspended)) {
return true;
}
}