summaryrefslogtreecommitdiff
AgeCommit message (Expand)Author
2020-07-10libcamera: V4L2VideoDevice: Add tryFormatPaul Elder
2020-07-10libcamera: formats: Add fields to info to ease calculating stridePaul Elder
2020-07-10libcamera: formats: Add NV24 and NV42, and reorder NV formatsPaul Elder
2020-07-09libcamera: ipu3: cio2: Make use of utils::map_keys() helperNiklas Söderlund
2020-07-09libcamera: utils: Add map_keys() functionLaurent Pinchart
2020-07-08libcamera: Use Size::isNull()Laurent Pinchart
2020-07-07android: camera_device: Remove single buffer restriction.Kieran Bingham
2020-07-07android: camera_device: Add buffers for each stream to RequestsKieran Bingham
2020-07-06android: camera_device: Maintain a vector of CameraStreamKieran Bingham
2020-07-06android: camera_device: Create the Request and Camera3RequestDescriptor togetherKieran Bingham
2020-07-06android: camera_device: Simplify FrameBuffer construction from a buffer_handle_tKieran Bingham
2020-07-06android: camera_device: Support multiple stream configurationsKieran Bingham
2020-07-06android: camera_device: Provide a toPixelFormat helperKieran Bingham
2020-07-06libcamera: camera: Allow unspecified roles for generateConfigurationKieran Bingham
2020-07-06libcamera: ipa: raspberrypi: Populate focus FoM from the ISP statisticsNaushir Patuck
2020-07-06ipa: raspberrypi: Populate libcamera metadata after controller processNaushir Patuck
2020-07-06libcamera: controls: Add focus Figure of Merit (FoM) controlNaushir Patuck
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Add newline at end of outputLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Avoid spaces at end of linesLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Collapse newlinesLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Fix indentation handlingLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Add character write methodLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Skip all spacesLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Make test output to stdoutLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Make output file a class memberLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Turn printer into a classLaurent Pinchart
2020-07-03utils: raspberrypi: ctt: json_pretty_print: Fix printer testLaurent Pinchart
2020-07-03ipa: raspberrypi: Enable focus measure without recompileDavid Plowman
2020-07-03libcamera: ipu3: cio2: Do not proxy signalNiklas Söderlund
2020-07-03libcamera: ipu3: Make it easier to read when a request may be completedNiklas Söderlund
2020-07-03libcamera: raspberrypi: Document vc_sm_cma pointer sharing with IPANiklas Söderlund
2020-07-01ipa/pipeline: rkisp1: Fix spellingAndrej Shadura
2020-06-29utils: raspberrypi: ctt: Fix pycodestyle W605Laurent Pinchart
2020-06-29libcamera: ipu3: cio2: Use Size::isNull()Niklas Söderlund
2020-06-29libcamera: geometry: Add isNull() function to Size classLaurent Pinchart
2020-06-29libcamera: raspberrypi: Fail on unsupported stream roleJacopo Mondi
2020-06-29libcamera: raspberrypi: Refuse invalid roles configurationJacopo Mondi
2020-06-29libcamera: ipu3: Fix wrong indentationJacopo Mondi
2020-06-29libcamera: ipu3: Accept an empty roles listJacopo Mondi
2020-06-29libcamera: ipu3: Improve error on multiple raw streams requestJacopo Mondi
2020-06-28libcamera: ipu3: imgu: Use unique_ptr for video and subdevicesNiklas Söderlund
2020-06-28libcamera: ipu3: imgu: Remove ImgUOutputNiklas Söderlund
2020-06-28libcamera: ipu3: Remove IPU3StreamNiklas Söderlund
2020-06-28libcamera: ipu3: Remove the active flag from IPU3StreamNiklas Söderlund
2020-06-28libcamera: ipu3: Do not duplicate data in IPU3StreamNiklas Söderlund
2020-06-28libcamera: ipu3: imgu: Use specific functions to configure each sinkNiklas Söderlund
2020-06-28libcamera: ipu3: imgu: Mark things that are internal as privateNiklas Söderlund
2020-06-28libcamera: ipu3: imgu: Do not cache indexNiklas Söderlund
2020-06-28libcamera: ipu3: imgu: Move the ImgUDevice class to separate filesNiklas Söderlund
2020-06-28libcamera: ipu3: Remove usage of IPU3CameraData from ImgUDeviceNiklas Söderlund
n371' href='#n371'>371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * awb.cpp - AWB control algorithm
 */

#include <libcamera/base/log.h>

#include "../lux_status.h"

#include "awb.hpp"

using namespace RPiController;
using namespace libcamera;

LOG_DEFINE_CATEGORY(RPiAwb)

#define NAME "rpi.awb"

#define AWB_STATS_SIZE_X DEFAULT_AWB_REGIONS_X
#define AWB_STATS_SIZE_Y DEFAULT_AWB_REGIONS_Y

// todo - the locking in this algorithm needs some tidying up as has been done
// elsewhere (ALSC and AGC).

void AwbMode::Read(boost::property_tree::ptree const &params)
{
	ct_lo = params.get<double>("lo");
	ct_hi = params.get<double>("hi");
}

void AwbPrior::Read(boost::property_tree::ptree const &params)
{
	lux = params.get<double>("lux");
	prior.Read(params.get_child("prior"));
}

static void read_ct_curve(Pwl &ct_r, Pwl &ct_b,
			  boost::property_tree::ptree const &params)
{
	int num = 0;
	for (auto it = params.begin(); it != params.end(); it++) {
		double ct = it->second.get_value<double>();
		assert(it == params.begin() || ct != ct_r.Domain().end);
		if (++it == params.end())
			throw std::runtime_error(
				"AwbConfig: incomplete CT curve entry");
		ct_r.Append(ct, it->second.get_value<double>());
		if (++it == params.end())
			throw std::runtime_error(
				"AwbConfig: incomplete CT curve entry");
		ct_b.Append(ct, it->second.get_value<double>());
		num++;
	}
	if (num < 2)
		throw std::runtime_error(
			"AwbConfig: insufficient points in CT curve");
}

void AwbConfig::Read(boost::property_tree::ptree const &params)
{
	bayes = params.get<int>("bayes", 1);
	frame_period = params.get<uint16_t>("frame_period", 10);
	startup_frames = params.get<uint16_t>("startup_frames", 10);
	convergence_frames = params.get<unsigned int>("convergence_frames", 3);
	speed = params.get<double>("speed", 0.05);
	if (params.get_child_optional("ct_curve"))
		read_ct_curve(ct_r, ct_b, params.get_child("ct_curve"));
	if (params.get_child_optional("priors")) {
		for (auto &p : params.get_child("priors")) {
			AwbPrior prior;
			prior.Read(p.second);
			if (!priors.empty() && prior.lux <= priors.back().lux)
				throw std::runtime_error(
					"AwbConfig: Prior must be ordered in increasing lux value");
			priors.push_back(prior);
		}
		if (priors.empty())
			throw std::runtime_error(
				"AwbConfig: no AWB priors configured");
	}
	if (params.get_child_optional("modes")) {
		for (auto &p : params.get_child("modes")) {
			modes[p.first].Read(p.second);
			if (default_mode == nullptr)
				default_mode = &modes[p.first];
		}
		if (default_mode == nullptr)
			throw std::runtime_error(
				"AwbConfig: no AWB modes configured");
	}
	min_pixels = params.get<double>("min_pixels", 16.0);
	min_G = params.get<uint16_t>("min_G", 32);
	min_regions = params.get<uint32_t>("min_regions", 10);
	delta_limit = params.get<double>("delta_limit", 0.2);
	coarse_step = params.get<double>("coarse_step", 0.2);
	transverse_pos = params.get<double>("transverse_pos", 0.01);
	transverse_neg = params.get<double>("transverse_neg", 0.01);
	if (transverse_pos <= 0 || transverse_neg <= 0)
		throw std::runtime_error(
			"AwbConfig: transverse_pos/neg must be > 0");
	sensitivity_r = params.get<double>("sensitivity_r", 1.0);
	sensitivity_b = params.get<double>("sensitivity_b", 1.0);
	if (bayes) {
		if (ct_r.Empty() || ct_b.Empty() || priors.empty() ||
		    default_mode == nullptr) {
			LOG(RPiAwb, Warning)
				<< "Bayesian AWB mis-configured - switch to Grey method";
			bayes = false;
		}
	}
	fast = params.get<int>(
		"fast", bayes); // default to fast for Bayesian, otherwise slow
	whitepoint_r = params.get<double>("whitepoint_r", 0.0);
	whitepoint_b = params.get<double>("whitepoint_b", 0.0);
	if (bayes == false)
		sensitivity_r = sensitivity_b =
			1.0; // nor do sensitivities make any sense
}

Awb::Awb(Controller *controller)
	: AwbAlgorithm(controller)
{
	async_abort_ = async_start_ = async_started_ = async_finished_ = false;
	mode_ = nullptr;
	manual_r_ = manual_b_ = 0.0;
	first_switch_mode_ = true;
	async_thread_ = std::thread(std::bind(&Awb::asyncFunc, this));
}

Awb::~Awb()
{
	{
		std::lock_guard<std::mutex> lock(mutex_);
		async_abort_ = true;
	}
	async_signal_.notify_one();
	async_thread_.join();
}