summaryrefslogtreecommitdiff
path: root/src/libcamera/software_isp/debayer_cpu.h
blob: 689c10753edfa3bc8600a45b9aeff4eb7f6867c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2023, Linaro Ltd
 * Copyright (C) 2023, Red Hat Inc.
 *
 * Authors:
 * Hans de Goede <hdegoede@redhat.com>
 *
 * debayer_cpu.h - CPU based debayering header
 */

#pragma once

#include <memory>
#include <stdint.h>
#include <vector>

#include <libcamera/base/object.h>

#include "libcamera/internal/bayer_format.h"

#include "debayer.h"
#include "swstats_cpu.h"

namespace libcamera {

class DebayerCpu : public Debayer, public Object
{
public:
	DebayerCpu(std::unique_ptr<SwStatsCpu> stats);
	~DebayerCpu();

	int configure(const StreamConfiguration &inputCfg,
		      const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs);
	Size patternSize(PixelFormat inputFormat);
	std::vector<PixelFormat> formats(PixelFormat input);
	std::tuple<unsigned int, unsigned int>
	strideAndFrameSize(const PixelFormat &outputFormat, const Size &size);
	void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params);
	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize);

	/**
	 * \brief Get the file descriptor for the statistics
	 *
	 * \return the file descriptor pointing to the statistics
	 */
	const SharedFD &getStatsFD() { return stats_->getStatsFD(); }

	/**
	 * \brief Get the output frame size
	 *
	 * \return The output frame size
	 */
	unsigned int frameSize() { return outputConfig_.frameSize; }

private:
	/**
	 * \brief Called to debayer 1 line of Bayer input data to output format
	 * \param[out] dst Pointer to the start of the output line to write
	 * \param[in] src The input data
	 *
	 * Input data is an array of (patternSize_.height + 1) src
	 * pointers each pointing to a line in the Bayer source. The middle
	 * element of the array will point to the actual line being processed.
	 * Earlier element(s) will point to the previous line(s) and later
	 * element(s) to the next line(s).
	 *
	 * These functions take an array of src pointers, rather than
	 * a single src pointer + a stride for the source, so that when the src
	 * is slow uncached memory it can be copied to faster memory before
	 * debayering. Debayering a standard 2x2 Bayer pattern requires access
	 * to the previous and next src lines for interpolating the missing
	 * colors. To allow copying the src lines only once 3 temporary buffers
	 * each holding a single line are used, re-using the oldest buffer for
	 * the next line and the pointers are swizzled so that:
	 * src[0] = previous-line, src[1] = currrent-line, src[2] = next-line.
	 * This way the 3 pointers passed to the debayer functions form
	 * a sliding window over the src avoiding the need to copy each
	 * line more than once.
	 *
	 * Similarly for bayer patterns which repeat every 4 lines, 5 src
	 * pointers are passed holding: src[0] = 2-lines-up, src[1] = 1-line-up
	 * src[2] = current-line, src[3] = 1-line-down, src[4] = 2-lines-down.
	 */
	using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);

	/* 8-bit raw bayer format */
	void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
	/* unpacked 10-bit raw bayer format */
	void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
	/* unpacked 12-bit raw bayer format */
	void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
	/* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */
	void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);
	void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);

	struct DebayerInputConfig {
		Size patternSize;
		unsigned int bpp; /* Memory used per pixel, not precision */
		unsigned int stride;
		std::vector<PixelFormat> outputFormats;
	};

	struct DebayerOutputConfig {
		unsigned int bpp; /* Memory used per pixel, not precision */
		unsigned int stride;
		unsigned int frameSize;
	};

	int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
	int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
	int setupStandardBayerOrder(BayerFormat::Order order);
	int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
	void setupInputMemcpy(const uint8_t *linePointers[]);
	void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
	void memcpyNextLine(const uint8_t *linePointers[]);
	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_;
	debayerFn debayer0_;
	debayerFn debayer1_;
	debayerFn debayer2_;
	debayerFn debayer3_;
	Rectangle window_;
	DebayerInputConfig inputConfig_;
	DebayerOutputConfig outputConfig_;
	std::unique_ptr<SwStatsCpu> stats_;
	uint8_t *lineBuffers_[kMaxLineBuffers];
	unsigned int lineBufferLength_;
	unsigned int lineBufferPadding_;
	unsigned int lineBufferIndex_;
	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 */
	static constexpr unsigned int kFramesToSkip = 30;
	static constexpr unsigned int kLastFrameToMeasure = 60;
};

} /* namespace libcamera */