libcamera: software_isp: Move color mappings out of debayering
Constructing the color mapping tables is related to stats rather than debayering, where they are applied. Let's move the corresponding code to stats processing. The same applies to the auxiliary gamma table. As the gamma value is currently fixed and used in a single place, with the temporary exception mentioned below, there is no need to share it anywhere anymore. It's necessary to initialize SoftwareIsp::debayerParams_ to default values. These initial values are used for the first two frames, before they are changed based on determined stats. To avoid sharing the gamma value constant in artificial ways, we use 0.5 directly in the initialization. This all is not a particularly elegant thing to do, such a code belongs conceptually to the similar code in stats processing, but doing better is left for larger refactoring. This is a preliminary step towards building this functionality on top of libipa/algorithm.h, which should follow. Signed-off-by: Milan Zamazal <mzamazal@redhat.com> Reviewed-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
committed by
Laurent Pinchart
parent
4e13c6f55b
commit
539c62ff8e
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2023, Linaro Ltd
|
||||
* Copyright (C) 2023, Red Hat Inc.
|
||||
* Copyright (C) 2023, 2024 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Hans de Goede <hdegoede@redhat.com>
|
||||
@@ -24,29 +24,28 @@ namespace libcamera {
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var DebayerParams::gainR
|
||||
* \brief Red gain
|
||||
*
|
||||
* 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
|
||||
* \var DebayerParams::kRGBLookupSize
|
||||
* \brief Size of a color lookup table
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var DebayerParams::gainG
|
||||
* \brief Green gain
|
||||
*
|
||||
* 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
|
||||
* \typedef DebayerParams::ColorLookupTable
|
||||
* \brief Type of the lookup tables for red, green, blue values
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var DebayerParams::gainB
|
||||
* \brief Blue gain
|
||||
*
|
||||
* 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
|
||||
* \var DebayerParams::red
|
||||
* \brief Lookup table for red color, mapping input values to output values
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var DebayerParams::gamma
|
||||
* \brief Gamma correction, 1.0 is no correction
|
||||
* \var DebayerParams::green
|
||||
* \brief Lookup table for green color, mapping input values to output values
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var DebayerParams::blue
|
||||
* \brief Lookup table for blue color, mapping input values to output values
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "debayer_cpu.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -35,7 +34,7 @@ namespace libcamera {
|
||||
* \param[in] stats Pointer to the stats object to use
|
||||
*/
|
||||
DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
|
||||
: stats_(std::move(stats)), gammaCorrection_(1.0), blackLevel_(0)
|
||||
: stats_(std::move(stats))
|
||||
{
|
||||
/*
|
||||
* Reading from uncached buffers may be very slow.
|
||||
@@ -47,9 +46,9 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
|
||||
*/
|
||||
enableInputMemcpy_ = true;
|
||||
|
||||
/* Initialize gamma to 1.0 curve */
|
||||
for (unsigned int i = 0; i < kGammaLookupSize; i++)
|
||||
gamma_[i] = i / (kGammaLookupSize / kRGBLookupSize);
|
||||
/* Initialize color lookup tables */
|
||||
for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++)
|
||||
red_[i] = green_[i] = blue_[i] = i;
|
||||
|
||||
for (unsigned int i = 0; i < kMaxLineBuffers; i++)
|
||||
lineBuffers_[i] = nullptr;
|
||||
@@ -698,37 +697,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
|
||||
}
|
||||
|
||||
/* Apply DebayerParams */
|
||||
if (params.gamma != gammaCorrection_ || params.blackLevel != blackLevel_) {
|
||||
const unsigned int blackIndex =
|
||||
params.blackLevel * kGammaLookupSize / 256;
|
||||
std::fill(gamma_.begin(), gamma_.begin() + blackIndex, 0);
|
||||
const float divisor = kGammaLookupSize - blackIndex - 1.0;
|
||||
for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
|
||||
gamma_[i] = UINT8_MAX * powf((i - blackIndex) / divisor, params.gamma);
|
||||
|
||||
gammaCorrection_ = params.gamma;
|
||||
blackLevel_ = params.blackLevel;
|
||||
}
|
||||
|
||||
if (swapRedBlueGains_)
|
||||
std::swap(params.gainR, params.gainB);
|
||||
|
||||
for (unsigned int i = 0; i < kRGBLookupSize; i++) {
|
||||
constexpr unsigned int div =
|
||||
kRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize;
|
||||
unsigned int idx;
|
||||
|
||||
/* Apply gamma after gain! */
|
||||
idx = std::min({ i * params.gainR / div, (kGammaLookupSize - 1) });
|
||||
red_[i] = gamma_[idx];
|
||||
|
||||
idx = std::min({ i * params.gainG / div, (kGammaLookupSize - 1) });
|
||||
green_[i] = gamma_[idx];
|
||||
|
||||
idx = std::min({ i * params.gainB / div, (kGammaLookupSize - 1) });
|
||||
blue_[i] = gamma_[idx];
|
||||
}
|
||||
green_ = params.green;
|
||||
red_ = swapRedBlueGains_ ? params.blue : params.red;
|
||||
blue_ = swapRedBlueGains_ ? params.red : params.blue;
|
||||
|
||||
/* Copy metadata from the input buffer */
|
||||
FrameMetadata &metadata = output->_d()->metadata();
|
||||
|
||||
@@ -122,15 +122,12 @@ private:
|
||||
void process2(const uint8_t *src, uint8_t *dst);
|
||||
void process4(const uint8_t *src, uint8_t *dst);
|
||||
|
||||
static constexpr unsigned int kGammaLookupSize = 1024;
|
||||
static constexpr unsigned int kRGBLookupSize = 256;
|
||||
/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */
|
||||
static constexpr unsigned int kMaxLineBuffers = 5;
|
||||
|
||||
std::array<uint8_t, kGammaLookupSize> gamma_;
|
||||
std::array<uint8_t, kRGBLookupSize> red_;
|
||||
std::array<uint8_t, kRGBLookupSize> green_;
|
||||
std::array<uint8_t, kRGBLookupSize> blue_;
|
||||
DebayerParams::ColorLookupTable red_;
|
||||
DebayerParams::ColorLookupTable green_;
|
||||
DebayerParams::ColorLookupTable blue_;
|
||||
debayerFn debayer0_;
|
||||
debayerFn debayer1_;
|
||||
debayerFn debayer2_;
|
||||
@@ -146,8 +143,6 @@ private:
|
||||
unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
|
||||
bool enableInputMemcpy_;
|
||||
bool swapRedBlueGains_;
|
||||
float gammaCorrection_;
|
||||
unsigned int blackLevel_;
|
||||
unsigned int measuredFrames_;
|
||||
int64_t frameProcessTime_;
|
||||
/* Skip 30 frames for things to stabilize then measure 30 frames */
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "libcamera/internal/software_isp/software_isp.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -18,6 +20,7 @@
|
||||
#include "libcamera/internal/framebuffer.h"
|
||||
#include "libcamera/internal/ipa_manager.h"
|
||||
#include "libcamera/internal/mapped_framebuffer.h"
|
||||
#include "libcamera/internal/software_isp/debayer_params.h"
|
||||
|
||||
#include "debayer_cpu.h"
|
||||
|
||||
@@ -63,10 +66,25 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
|
||||
* handler
|
||||
*/
|
||||
SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor)
|
||||
: debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10,
|
||||
DebayerParams::kGain10, 0.5f, 0 },
|
||||
dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)
|
||||
: dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System)
|
||||
{
|
||||
/*
|
||||
* debayerParams_ must be initialized because the initial value is used for
|
||||
* the first two frames, i.e. until stats processing starts providing its
|
||||
* own parameters.
|
||||
*
|
||||
* \todo This should be handled in the same place as the related
|
||||
* operations, in the IPA module.
|
||||
*/
|
||||
std::array<uint8_t, 256> gammaTable;
|
||||
for (unsigned int i = 0; i < 256; i++)
|
||||
gammaTable[i] = UINT8_MAX * std::pow(i / 256.0, 0.5);
|
||||
for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
|
||||
debayerParams_.red[i] = gammaTable[i];
|
||||
debayerParams_.green[i] = gammaTable[i];
|
||||
debayerParams_.blue[i] = gammaTable[i];
|
||||
}
|
||||
|
||||
if (!dmaHeap_.isValid()) {
|
||||
LOG(SoftwareIsp, Error) << "Failed to create DmaHeap object";
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user