From 2b39897d1832ba223a53be49c8afc2b7a7370ffe Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Thu, 30 Jan 2025 14:55:41 +0100 Subject: [PATCH] Fix #133799: render of VSE 10/12bpp videos broken unless source strips are float 10/12bpp movie writing code assumes that input image is properly floating point for these cases. That is always true for regular rendering, however VSE can produce 8bpp images, if there are no float/HDR strips in there. Make these convert into a float image in the render pipeline when needed. Pull Request: https://projects.blender.org/blender/blender/pulls/133802 --- source/blender/render/intern/pipeline.cc | 52 ++++++++++++++++++----- source/blender/sequencer/SEQ_render.hh | 4 +- source/blender/sequencer/intern/render.cc | 4 +- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/source/blender/render/intern/pipeline.cc b/source/blender/render/intern/pipeline.cc index 3251dccb172..d179a6c3b2b 100644 --- a/source/blender/render/intern/pipeline.cc +++ b/source/blender/render/intern/pipeline.cc @@ -1456,6 +1456,47 @@ bool RE_seq_render_active(Scene *scene, RenderData *rd) return false; } +static bool seq_result_needs_float(const ImageFormatData &im_format) +{ + return ELEM(im_format.depth, R_IMF_CHAN_DEPTH_10, R_IMF_CHAN_DEPTH_12); +} + +static ImBuf *seq_process_render_image(ImBuf *src, + const ImageFormatData &im_format, + const Scene *scene) +{ + if (src == nullptr) { + return nullptr; + } + + ImBuf *dst = nullptr; + if (seq_result_needs_float(im_format) && src->float_buffer.data == nullptr) { + /* If render output needs >8 bpp input and we only have 8pp, convert to float. */ + dst = IMB_allocImBuf(src->x, src->y, src->planes, 0); + imb_addrectfloatImBuf(dst, src->channels, false); + /* Transform from sequencer space to scene linear. */ + const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(src); + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get( + COLOR_ROLE_SCENE_LINEAR); + IMB_colormanagement_transform_from_byte_threaded(dst->float_buffer.data, + src->byte_buffer.data, + src->x, + src->y, + src->channels, + from_colorspace, + to_colorspace); + } + else { + /* Duplicate sequencer output and ensure it is in needed color space. */ + dst = IMB_dupImBuf(src); + SEQ_render_imbuf_from_sequencer_space(scene, dst); + } + IMB_metadata_copy(dst, src); + IMB_freeImBuf(src); + + return dst; +} + /* Render sequencer strips into render result. */ static void do_render_sequencer(Render *re) { @@ -1500,16 +1541,7 @@ static void do_render_sequencer(Render *re) for (view_id = 0; view_id < tot_views; view_id++) { context.view_id = view_id; out = SEQ_render_give_ibuf(&context, cfra, 0); - - if (out) { - ibuf_arr[view_id] = IMB_dupImBuf(out); - IMB_metadata_copy(ibuf_arr[view_id], out); - IMB_freeImBuf(out); - SEQ_render_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]); - } - else { - ibuf_arr[view_id] = nullptr; - } + ibuf_arr[view_id] = seq_process_render_image(out, re->r.im_format, re->pipeline_scene_eval); } rr = re->result; diff --git a/source/blender/sequencer/SEQ_render.hh b/source/blender/sequencer/SEQ_render.hh index ee9dff3fd5c..b3153b94423 100644 --- a/source/blender/sequencer/SEQ_render.hh +++ b/source/blender/sequencer/SEQ_render.hh @@ -70,8 +70,8 @@ void SEQ_render_new_render_data(Main *bmain, SeqRenderData *r_context); StripElem *SEQ_render_give_stripelem(const Scene *scene, const Strip *strip, int timeline_frame); -void SEQ_render_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf); -void SEQ_render_pixel_from_sequencer_space_v4(Scene *scene, float pixel[4]); +void SEQ_render_imbuf_from_sequencer_space(const Scene *scene, ImBuf *ibuf); +void SEQ_render_pixel_from_sequencer_space_v4(const Scene *scene, float pixel[4]); /** * Check if `strip` is muted for rendering. * This function also checks `SeqTimelineChannel` flag. diff --git a/source/blender/sequencer/intern/render.cc b/source/blender/sequencer/intern/render.cc index 264425a39a1..65348f5dde8 100644 --- a/source/blender/sequencer/intern/render.cc +++ b/source/blender/sequencer/intern/render.cc @@ -176,7 +176,7 @@ void seq_imbuf_to_sequencer_space(const Scene *scene, ImBuf *ibuf, bool make_flo seq_imbuf_assign_spaces(scene, ibuf); } -void SEQ_render_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) +void SEQ_render_imbuf_from_sequencer_space(const Scene *scene, ImBuf *ibuf) { const char *from_colorspace = scene->sequencer_colorspace_settings.name; const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get( @@ -198,7 +198,7 @@ void SEQ_render_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) } } -void SEQ_render_pixel_from_sequencer_space_v4(Scene *scene, float pixel[4]) +void SEQ_render_pixel_from_sequencer_space_v4(const Scene *scene, float pixel[4]) { const char *from_colorspace = scene->sequencer_colorspace_settings.name; const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(