From bde7ef3808d26c5fc0503bfacf3b2f5b3260fbd7 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 1 May 2024 10:46:27 +0100 Subject: [PATCH] backend: Allow users to set separate crops for each output For backward compatibility, we keep the existing BackEnd::SetCrop behaving the same and setting the same crop params for all outputs. Signed-off-by: Naushir Patuck --- src/libpisp/backend/backend.cpp | 11 +++++- src/libpisp/backend/backend.hpp | 3 +- src/libpisp/backend/backend_prepare.cpp | 45 +++++++++++----------- src/libpisp/backend/tiling/pisp_tiling.cpp | 11 ++++-- src/libpisp/backend/tiling/pisp_tiling.hpp | 6 +-- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/libpisp/backend/backend.cpp b/src/libpisp/backend/backend.cpp index 88851af..dc33b96 100644 --- a/src/libpisp/backend/backend.cpp +++ b/src/libpisp/backend/backend.cpp @@ -333,7 +333,16 @@ void BackEnd::GetGamma(pisp_be_gamma_config &gamma) void BackEnd::SetCrop(pisp_be_crop_config const &crop) { - be_config_extra_.crop = crop; + for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) + be_config_extra_.crop[i] = crop; + be_config_extra_.dirty_flags_extra |= PISP_BE_DIRTY_CROP; + retile_ = true; +} + +void BackEnd::SetCrop(unsigned int i, pisp_be_crop_config const &crop) +{ + PISP_ASSERT(i < variant_.BackEndNumBranches(0)); + be_config_extra_.crop[i] = crop; be_config_extra_.dirty_flags_extra |= PISP_BE_DIRTY_CROP; retile_ = true; } diff --git a/src/libpisp/backend/backend.hpp b/src/libpisp/backend/backend.hpp index 6b29213..cb5a4d2 100644 --- a/src/libpisp/backend/backend.hpp +++ b/src/libpisp/backend/backend.hpp @@ -103,6 +103,7 @@ class BackEnd final void SetGamma(pisp_be_gamma_config const &gamma); void GetGamma(pisp_be_gamma_config &gamma); void SetCrop(pisp_be_crop_config const &crop); + void SetCrop(unsigned int i, pisp_be_crop_config const &crop); void SetCsc(unsigned int i, pisp_be_ccm_config const &csc); void GetCsc(unsigned int i, pisp_be_ccm_config &csc); void SetOutputFormat(unsigned int i, pisp_be_output_format_config const &output_format); @@ -155,7 +156,7 @@ class BackEnd final pisp_be_cac_extra cac; pisp_be_downscale_extra downscale[PISP_BACK_END_NUM_OUTPUTS]; pisp_be_resample_extra resample[PISP_BACK_END_NUM_OUTPUTS]; - pisp_be_crop_config crop; + pisp_be_crop_config crop[PISP_BACK_END_NUM_OUTPUTS]; uint32_t dirty_flags_bayer; //these use pisp_be_bayer_enable uint32_t dirty_flags_rgb; //use pisp_be_rgb_enable uint32_t dirty_flags_extra; //these use pisp_be_dirty_t diff --git a/src/libpisp/backend/backend_prepare.cpp b/src/libpisp/backend/backend_prepare.cpp index a57ac78..0c6798e 100644 --- a/src/libpisp/backend/backend_prepare.cpp +++ b/src/libpisp/backend/backend_prepare.cpp @@ -488,9 +488,9 @@ void BackEnd::finaliseConfig() if (enabled) { // crop is enabled when it contains non-zero width/height - uint16_t w = be_config_extra_.crop.width ? be_config_extra_.crop.width + uint16_t w = be_config_extra_.crop[j].width ? be_config_extra_.crop[j].width : be_config_.input_format.width; - uint16_t h = be_config_extra_.crop.width ? be_config_extra_.crop.height + uint16_t h = be_config_extra_.crop[j].width ? be_config_extra_.crop[j].height : be_config_.input_format.height; if (dirty_flags_rgb & PISP_BE_RGB_ENABLE_DOWNSCALE(j)) @@ -537,18 +537,18 @@ void BackEnd::updateSmartResize() { std::string filter; - // First get the size of the input to the rescalers. The crops are zero when not in use. - uint16_t input_width = be_config_extra_.crop.width; - if (!input_width) - input_width = be_config_.input_format.width; - uint16_t input_height = be_config_extra_.crop.height; - if (!input_height) - input_height = be_config_.input_format.height; - // Look through the output branches adjusting the scaling blocks where "smart resizing" // has been requested. for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) { + // First get the size of the input to the rescalers. The crops are zero when not in use. + uint16_t input_width = be_config_extra_.crop[i].width; + if (!input_width) + input_width = be_config_.input_format.width; + uint16_t input_height = be_config_extra_.crop[i].height; + if (!input_height) + input_height = be_config_.input_format.height; + if ((smart_resize_dirty_ & (1 << i)) || (be_config_extra_.dirty_flags_extra & PISP_BE_DIRTY_CROP)) { if (smart_resize_[i].width && smart_resize_[i].height) @@ -691,15 +691,16 @@ void BackEnd::updateTiles() PISP_LOG(debug, "Input alignments are " << tiling_config.input_alignment << " pixels"); tiling_config.input_image_size = tiling::Length2(c.input_format.width, c.input_format.height); - tiling_config.crop = tiling::Interval2(tiling::Interval(ce.crop.offset_x, ce.crop.width), - tiling::Interval(ce.crop.offset_y, ce.crop.height)); - - if (tiling_config.crop.x.length == 0 || tiling_config.crop.y.length == 0) - tiling_config.crop = tiling::Interval2(tiling::Interval(0, c.input_format.width), - tiling::Interval(0, c.input_format.height)); for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) { + tiling_config.crop[i] = tiling::Interval2(tiling::Interval(ce.crop[i].offset_x, ce.crop[i].width), + tiling::Interval(ce.crop[i].offset_y, ce.crop[i].height)); + + if (tiling_config.crop[i].x.length == 0 || tiling_config.crop[i].y.length == 0) + tiling_config.crop[i] = tiling::Interval2(tiling::Interval(0, c.input_format.width), + tiling::Interval(0, c.input_format.height)); + tiling_config.output_h_mirror[i] = be_config_.output_format[i].transform & PISP_BE_TRANSFORM_HFLIP; tiling_config.downscale_factor[i] = tiling::Length2(c.downscale[i].scale_factor_h, c.downscale[i].scale_factor_v); @@ -794,7 +795,7 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config } tiling::Crop2 downscale_crop; - tiling::Interval2 resample_size = tiles[i].crop.output; + tiling::Interval2 resample_size = tiles[i].crop[j].output; resample_size.x = resample_size.x - tiles[i].resample[j].crop.x; resample_size.y = resample_size.y - tiles[i].resample[j].crop.y; @@ -802,17 +803,17 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config // next block. Also there will be no extra crop necessary for the resize operation. if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(j)) { - downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop[j].crop; // Size of the tile going into the resample block needs to be set here. resample_size = tiles[i].downscale[j].output; } else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_RESAMPLE(j)) { - downscale_crop = tiles[i].resample[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].resample[j].crop + tiles[i].crop[j].crop; } else { - downscale_crop = tiles[i].output[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].output[j].crop + tiles[i].crop[j].crop; } t.crop_x_start[j] = downscale_crop.x.start; @@ -952,8 +953,8 @@ void BackEnd::getOutputSize(int i, uint16_t *width, uint16_t *height, pisp_image *width = be_config_extra_.resample[i].scaled_width, *height = be_config_extra_.resample[i].scaled_height; else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(i)) *width = be_config_extra_.downscale[i].scaled_width, *height = be_config_extra_.downscale[i].scaled_height; - else if (be_config_extra_.crop.width) // crop width and height will be zero when crop disabled - *width = be_config_extra_.crop.width, *height = be_config_extra_.crop.height; + else if (be_config_extra_.crop[i].width) // crop width and height will be zero when crop disabled + *width = be_config_extra_.crop[i].width, *height = be_config_extra_.crop[i].height; else *width = ifmt.width, *height = ifmt.height; } diff --git a/src/libpisp/backend/tiling/pisp_tiling.cpp b/src/libpisp/backend/tiling/pisp_tiling.cpp index c66c878..cd88d2a 100644 --- a/src/libpisp/backend/tiling/pisp_tiling.cpp +++ b/src/libpisp/backend/tiling/pisp_tiling.cpp @@ -56,11 +56,9 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt Length2(PipelineAlignX, PipelineAlignY)); ContextStage context_stage("context", &input_stage, context_config, offsetof(Tile, context)); - CropStage::Config crop_config(config.crop); - CropStage crop_stage("crop", &context_stage, crop_config, offsetof(Tile, crop)); - - SplitStage split_stage("split", &crop_stage); + SplitStage split_stage("split", &context_stage); + std::unique_ptr crop_stages[NumOutputBranches]; std::unique_ptr downscale_stages[NumOutputBranches]; std::unique_ptr resample_stages[NumOutputBranches]; std::unique_ptr output_stages[NumOutputBranches]; @@ -74,6 +72,11 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt char name[32]; Stage *prev_stage = &split_stage; + sprintf(name, "crop%d", i); + crop_stages[i] = std::unique_ptr( + new CropStage(name, prev_stage, config.crop[i], offsetof(Tile, crop) + i * sizeof(Region))); + prev_stage = crop_stages[i].get(); + // There's a little awkwardness if the resize blocks (downscale and resample) are not enabled. Resize *does* change the output tile // size, even if it's doing a 1-to-1 scaling (it loses context), so we must leave it out of the tiling // calculation. diff --git a/src/libpisp/backend/tiling/pisp_tiling.hpp b/src/libpisp/backend/tiling/pisp_tiling.hpp index 9e0b71c..ad3217e 100644 --- a/src/libpisp/backend/tiling/pisp_tiling.hpp +++ b/src/libpisp/backend/tiling/pisp_tiling.hpp @@ -22,7 +22,7 @@ struct Tile tiling::Region input; tiling::Region decompress; tiling::Region context; - tiling::Region crop; + tiling::Region crop[NumOutputBranches]; tiling::Region downscale[NumOutputBranches]; tiling::Region resample[NumOutputBranches]; tiling::Region output[NumOutputBranches]; @@ -31,7 +31,7 @@ struct Tile struct TilingConfig { tiling::Length2 input_image_size; - tiling::Interval2 crop; + tiling::Interval2 crop[NumOutputBranches]; tiling::Length2 downscale_image_size[NumOutputBranches]; tiling::Length2 output_image_size[NumOutputBranches]; tiling::Length2 max_tile_size; @@ -51,9 +51,9 @@ inline std::ostream &operator<<(std::ostream &os, TilingConfig const &tc) { os << "TilingConfig:" << std::endl; os << "\tinput_image_size " << tc.input_image_size << " align " << tc.input_alignment << std::endl; - os << "\tcrop " << tc.crop << std::endl; for (int i = 0; i < NumOutputBranches; i++) { + os << "\tcrop[" << i << "] " << tc.crop[i] << std::endl; os << "\toutput_image_size[" << i << "] " << tc.output_image_size[i] << " align max " << tc.output_max_alignment[i] << " min " << tc.output_min_alignment[i] << std::endl; os << "\tdownscale_image_size " << tc.downscale_image_size[i] << " downscale_factor " << tc.downscale_factor[i]