libcamera/src/ipa/raspberrypi/controller/rpi/alsc.hpp
David Plowman 7f6b9121cc libcamera: ipa: raspberrypi: ALSC: Resample luminance table
This fixes a bug where the luminance correction table was not being
resampled according to the camera mode, in the same way as the colour
tables. This could be noticeable if any camera modes crop
aggressively.

This resampling can be done "up front" in the SwitchMode, as we have
only a single fixed luminance table. In order to protect the
recalculation of the table from the asynchronous thread (which reads
it) I've elected to wait for that thread to go idle (though I doubt it
would have mattered much). As a by-product of stopping the thread, it
no longer needs its own copy of the camera mode (async_camera_mode_).

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-08-05 17:48:55 +03:00

105 lines
3.4 KiB
C++

/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2019, Raspberry Pi (Trading) Limited
*
* alsc.hpp - ALSC (auto lens shading correction) control algorithm
*/
#pragma once
#include <mutex>
#include <condition_variable>
#include <thread>
#include "../algorithm.hpp"
#include "../alsc_status.h"
namespace RPi {
// Algorithm to generate automagic LSC (Lens Shading Correction) tables.
struct AlscCalibration {
double ct;
double table[ALSC_CELLS_X * ALSC_CELLS_Y];
};
struct AlscConfig {
// Only repeat the ALSC calculation every "this many" frames
uint16_t frame_period;
// number of initial frames for which speed taken as 1.0 (maximum)
uint16_t startup_frames;
// IIR filter speed applied to algorithm results
double speed;
double sigma_Cr;
double sigma_Cb;
double min_count;
uint16_t min_G;
double omega;
uint32_t n_iter;
double luminance_lut[ALSC_CELLS_X * ALSC_CELLS_Y];
double luminance_strength;
std::vector<AlscCalibration> calibrations_Cr;
std::vector<AlscCalibration> calibrations_Cb;
double default_ct; // colour temperature if no metadata found
double threshold; // iteration termination threshold
};
class Alsc : public Algorithm
{
public:
Alsc(Controller *controller = NULL);
~Alsc();
char const *Name() const override;
void Initialise() override;
void SwitchMode(CameraMode const &camera_mode, Metadata *metadata) override;
void Read(boost::property_tree::ptree const &params) override;
void Prepare(Metadata *image_metadata) override;
void Process(StatisticsPtr &stats, Metadata *image_metadata) override;
private:
// configuration is read-only, and available to both threads
AlscConfig config_;
bool first_time_;
CameraMode camera_mode_;
double luminance_table_[ALSC_CELLS_X * ALSC_CELLS_Y];
std::thread async_thread_;
void asyncFunc(); // asynchronous thread function
std::mutex mutex_;
// condvar for async thread to wait on
std::condition_variable async_signal_;
// condvar for synchronous thread to wait on
std::condition_variable sync_signal_;
// for sync thread to check if async thread finished (requires mutex)
bool async_finished_;
// for async thread to check if it's been told to run (requires mutex)
bool async_start_;
// for async thread to check if it's been told to quit (requires mutex)
bool async_abort_;
// The following are only for the synchronous thread to use:
// for sync thread to note its has asked async thread to run
bool async_started_;
// counts up to frame_period before restarting the async thread
int frame_phase_;
// counts up to startup_frames
int frame_count_;
// counts up to startup_frames for Process method
int frame_count2_;
double sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
double prev_sync_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
void waitForAysncThread();
// The following are for the asynchronous thread to use, though the main
// thread can set/reset them if the async thread is known to be idle:
void restartAsync(StatisticsPtr &stats, Metadata *image_metadata);
// copy out the results from the async thread so that it can be restarted
void fetchAsyncResults();
double ct_;
bcm2835_isp_stats_region statistics_[ALSC_CELLS_Y * ALSC_CELLS_X];
double async_results_[3][ALSC_CELLS_Y][ALSC_CELLS_X];
double async_lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y];
double async_lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y];
void doAlsc();
double lambda_r_[ALSC_CELLS_X * ALSC_CELLS_Y];
double lambda_b_[ALSC_CELLS_X * ALSC_CELLS_Y];
};
} // namespace RPi