Skip to content

Commit

Permalink
core: Add aspect ratio control for lores stream
Browse files Browse the repository at this point in the history
Add a new command line argument "--lores-par" that when set, preserves
the 1:1 aspect ratio of the low res stream. This is only possible on the
PiSP platform. The default behaviour is to have this switch disabled,
allowing for identical behaviour betwen VC4 and PiSP platforms. This
requires the use of the rpi::ScalerCrops vendor control.

This switch can also be triggered via the "rpicam-apps.lores.par" key
in the postprocessing JSON file.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
  • Loading branch information
naushir committed Aug 29, 2024
1 parent f58bfe1 commit 92938e9
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
7 changes: 5 additions & 2 deletions core/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,11 @@ Options::Options()
("tuning-file", value<std::string>(&tuning_file)->default_value("-"),
"Name of camera tuning file to use, omit this option for libcamera default behaviour")
("lores-width", value<unsigned int>(&lores_width)->default_value(0),
"Width of low resolution frames (use 0 to omit low resolution stream")
"Width of low resolution frames (use 0 to omit low resolution stream)")
("lores-height", value<unsigned int>(&lores_height)->default_value(0),
"Height of low resolution frames (use 0 to omit low resolution stream")
"Height of low resolution frames (use 0 to omit low resolution stream)")
("lores-par", value<bool>(&lores_par)->default_value(false)->implicit_value(true),
"Preserve the 1:1 pixel aspect ratio of the low res image (where possible) by applying a different crop on the stream.")
("mode", value<std::string>(&mode_string),
"Camera mode as W:H:bit-depth:packing, where packing is P (packed) or U (unpacked)")
("viewfinder-mode", value<std::string>(&viewfinder_mode_string),
Expand Down Expand Up @@ -695,6 +697,7 @@ void Options::Print() const
std::cerr << " tuning-file: " << (tuning_file == "-" ? "(libcamera)" : tuning_file) << std::endl;
std::cerr << " lores-width: " << lores_width << std::endl;
std::cerr << " lores-height: " << lores_height << std::endl;
std::cerr << " lores-par: " << lores_par << std::endl;
if (afMode_index != -1)
std::cerr << " autofocus-mode: " << afMode << std::endl;
if (afRange_index != -1)
Expand Down
1 change: 1 addition & 0 deletions core/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct Options
bool qt_preview;
unsigned int lores_width;
unsigned int lores_height;
bool lores_par;
unsigned int camera;
std::string mode_string;
Mode mode;
Expand Down
2 changes: 2 additions & 0 deletions core/post_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void PostProcessor::Read(std::string const &filename)

unsigned int lores_width = node.get<unsigned int>("lores.width");
unsigned int lores_height = node.get<unsigned int>("lores.height");
bool lores_par = node.get<bool>("lores.par", app_->GetOptions()->lores_par);
std::string lores_format_str = node.get<std::string>("lores.format", "yuv420");

libcamera::PixelFormat lores_format = libcamera::formats::YUV420;
Expand All @@ -132,6 +133,7 @@ void PostProcessor::Read(std::string const &filename)

app_->GetOptions()->lores_width = lores_width;
app_->GetOptions()->lores_height = lores_height;
app_->GetOptions()->lores_par = lores_par;
app_->lores_format_ = lores_format;

LOG(1, "Postprocessing requested lores: " << lores_width << "x" << lores_height << " " << lores_format);
Expand Down
38 changes: 28 additions & 10 deletions core/rpicam_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,17 +635,35 @@ void RPiCamApp::StartCamera()

// Build a list of initial controls that we must set in the camera before starting it.
// We don't overwrite anything the application may have set before calling us.
if (!controls_.get(controls::ScalerCrop) && options_->roi_width != 0 && options_->roi_height != 0)
if (!controls_.get(controls::ScalerCrop) && !controls_.get(controls::rpi::ScalerCrops))
{
Rectangle sensor_area = camera_->controls().at(&controls::ScalerCrop).max().get<Rectangle>();
int x = options_->roi_x * sensor_area.width;
int y = options_->roi_y * sensor_area.height;
int w = options_->roi_width * sensor_area.width;
int h = options_->roi_height * sensor_area.height;
Rectangle crop(x, y, w, h);
crop.translateBy(sensor_area.topLeft());
LOG(2, "Using crop " << crop.toString());
controls_.set(controls::ScalerCrop, crop);
const Rectangle sensor_area = camera_->controls().at(&controls::ScalerCrop).max().get<Rectangle>();
const Rectangle default_crop = camera_->controls().at(&controls::ScalerCrop).def().get<Rectangle>();
std::vector<Rectangle> crops;

if (options_->roi_width != 0 && options_->roi_height != 0)
{
int x = options_->roi_x * sensor_area.width;
int y = options_->roi_y * sensor_area.height;
unsigned int w = options_->roi_width * sensor_area.width;
unsigned int h = options_->roi_height * sensor_area.height;
crops.push_back({ x, y, w, h });
crops.back().translateBy(sensor_area.topLeft());
}
else
{
crops.push_back(default_crop);
}

LOG(2, "Using crop (main) " << crops.back().toString());

if (options_->lores_width != 0 && options_->lores_height != 0 && !options_->lores_par)
{
crops.push_back(crops.back());
LOG(2, "Using crop (lores) " << crops.back().toString());
}

controls_.set(controls::rpi::ScalerCrops, libcamera::Span<const Rectangle>(crops.data(), crops.size()));
}

if (!controls_.get(controls::AfWindows) && !controls_.get(controls::AfMetering) && options_->afWindow_width != 0 &&
Expand Down

0 comments on commit 92938e9

Please sign in to comment.