[PATCH v2 08/18] libcamera: software_isp: Add SwStatsCpu class

Hans de Goede hdegoede at redhat.com
Mon Feb 12 16:48:01 CET 2024


Hi,

On 1/23/24 21:04, Milan Zamazal wrote:
> Hans de Goede <hdegoede at redhat.com> writes:

<snip>

>> +static const unsigned int RED_Y_MUL = 77; /* 0.30 * 256 */
>> +static const unsigned int GREEN_Y_MUL = 150; /* 0.59 * 256 */
>> +static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */
> 
> The last two lines comments don't match the given values.
> They should be 0.587 * 256 and 0.114 * 256 to equal.

I've fixed the comment to use the usual 0.299, 0.587, 0, 114 values
now, thanks.

>> +#define SWISP_LINARO_START_LINE_STATS(pixel_t) \
>> +	pixel_t r, g, g2, b;                   \
>> +	unsigned int y_val;                    \
>> +                                               \
>> +	unsigned int sumR = 0;                 \
>> +	unsigned int sumG = 0;                 \
>> +	unsigned int sumB = 0;
>> +
>> +#define SWISP_LINARO_ACCUMULATE_LINE_STATS(div) \
>> +	sumR += r;                              \
>> +	sumG += g;                              \
>> +	sumB += b;                              \
>> +                                                \
>> +	y_val = r * RED_Y_MUL;                  \
>> +	y_val += g * GREEN_Y_MUL;               \
>> +	y_val += b * BLUE_Y_MUL;                \
>> +	stats_.y_histogram[y_val / (256 * 16 * (div))]++;
> 
> As the size of y_histogram (16) is used in multiple places, it should be a named constant.

Ack, fixed.

>> +#define SWISP_LINARO_FINISH_LINE_STATS() \
>> +	stats_.sumR_ += sumR;            \
>> +	stats_.sumG_ += sumG;            \
>> +	stats_.sumB_ += sumB;
>> +
>> +static inline __attribute__((always_inline)) void
>> +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, SwIspStats &stats_)
>> +{
>> +	const int width_in_bytes = width * 5 / 4;
>> +
>> +	SWISP_LINARO_START_LINE_STATS(uint8_t)
>> +
>> +	for (int x = 0; x < width_in_bytes; x += 5) {
>> +		if (bggr) {
>> +			/* BGGR */
>> +			b = src0[x];
>> +			g = src0[x + 1];
>> +			g2 = src1[x];
>> +			r = src1[x + 1];
>> +		} else {
>> +			/* GBRG */
>> +			g = src0[x];
>> +			b = src0[x + 1];
>> +			r = src1[x];
>> +			g2 = src1[x + 1];
>> +		}
>> +		g = (g + g2) / 2;
>> +
>> +		SWISP_LINARO_ACCUMULATE_LINE_STATS(1)
>> +	}
> 
> Does this loop process only every other pixel?  If yes, probably nothing wrong
> with it for stats, but it deserves a comment.

Yes it processes only every other pixel I've added a comment for this.

> 
>> +	SWISP_LINARO_FINISH_LINE_STATS()
>> +}
>> +
>> +void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
>> +{
>> +	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
>> +	const uint8_t *src1 = src[2] + window_.x * 5 / 4;
> 
> This is difficult to understand: why src[1], src[2] and not src[0], src[1]?

I have added the following comment to the statsProcessFn:

        /**
         * \brief Called when there is data to get statistics from.
         * \param[in] src The input data
         *
         * These functions take an array of (patternSize_.height + 1) src
         * pointers each pointing to a line in the source image. 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).
         *
         * See the documentation of DebayerCpu::debayerFn for more details.
         */
        typedef void (SwStatsCpu::*statsProcessFn)(const uint8_t *src[]);

And the following comment to DebayerCpu::debayerFn:

	/**
	 * \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 then
	 * 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 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 then 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.
	 */
	typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src[]);

Regards,

Hans



More information about the libcamera-devel mailing list