summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/md_parser.hpp
blob: 298d518112563fdb6157957fbe40df46f5e63fb1 (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
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * md_parser.hpp - image sensor metadata parser interface
 */
#pragma once

#include <initializer_list>
#include <map>
#include <optional>
#include <stdint.h>

#include <libcamera/base/span.h>

/*
 * Camera metadata parser class. Usage as shown below.
 *
 * Setup:
 *
 * Usually the metadata parser will be made as part of the CamHelper class so
 * application code doesn't have to worry which kind to instantiate. But for
 * the sake of example let's suppose we're parsing imx219 metadata.
 *
 * MdParser *parser = new MdParserSmia({ expHiReg, expLoReg, gainReg });
 * parser->SetBitsPerPixel(bpp);
 * parser->SetLineLengthBytes(pitch);
 * parser->SetNumLines(2);
 *
 * Note 1: if you don't know how many lines there are, the size of the input
 * buffer is used as a limit instead.
 *
 * Note 2: if you don't know the line length, you can leave the line length unset
 * (or set to zero) and the parser will hunt for the line start instead.
 *
 * Then on every frame:
 *
 * RegisterMap registers;
 * if (parser->Parse(buffer, registers) != MdParser::OK)
 *     much badness;
 * Metadata metadata;
 * CamHelper::PopulateMetadata(registers, metadata);
 *
 * (Note that the CamHelper class converts to/from exposure lines and time,
 * and gain_code / actual gain.)
 *
 * If you suspect your embedded data may have changed its layout, change any line
 * lengths, number of lines, bits per pixel etc. that are different, and
 * then:
 *
 * parser->Reset();
 *
 * before calling Parse again.
 */

namespace RPiController {

/* Abstract base class from which other metadata parsers are derived. */

class MdParser
{
public:
	using RegisterMap = std::map<uint32_t, uint32_t>;

	/*
	 * Parser status codes:
	 * OK       - success
	 * NOTFOUND - value such as exposure or gain was not found
	 * ERROR    - all other errors
	 */
	enum Status {
		OK = 0,
		NOTFOUND = 1,
		ERROR = 2
	};

	MdParser()
		: reset_(true), bitsPerPixel_(0), numLines_(0), lineLengthBytes_(0)
	{
	}

	virtual ~MdParser() = default;

	void reset()
	{
		reset_ = true;
	}

	void setBitsPerPixel(int bpp)
	{
		bitsPerPixel_ = bpp;
	}

	void setNumLines(unsigned int numLines)
	{
		numLines_ = numLines;
	}

	void setLineLengthBytes(unsigned int numBytes)
	{
		lineLengthBytes_ = numBytes;
	}

	virtual Status parse(libcamera::Span<const uint8_t> buffer,
			     RegisterMap &registers) = 0;

protected:
	bool reset_;
	int bitsPerPixel_;
	unsigned int numLines_;
	unsigned int lineLengthBytes_;
};

/*
 * This isn't a full implementation of a metadata parser for SMIA sensors,
 * however, it does provide the findRegs function which will prove useful and
 * make it easier to implement parsers for other SMIA-like sensors (see
 * md_parser_imx219.cpp for an example).
 */

class MdParserSmia final : public MdParser
{
public:
	MdParserSmia(std::initializer_list<uint32_t> registerList);

	MdParser::Status parse(libcamera::Span<const uint8_t> buffer,
			       RegisterMap &registers) override;

private:
	/* Maps register address to offset in the buffer. */
	using OffsetMap = std::map<uint32_t, std::optional<uint32_t>>;

	/*
	 * Note that error codes > 0 are regarded as non-fatal; codes < 0
	 * indicate a bad data buffer. Status codes are:
	 * ParseOk     - found all registers, much happiness
	 * MissingRegs - some registers found; should this be a hard error?
	 * The remaining codes are all hard errors.
	 */
	enum ParseStatus {
		ParseOk      =  0,
		MissingRegs  =  1,
		NoLineStart  = -1,
		IllegalTag   = -2,
		BadDummy     = -3,
		BadLineEnd   = -4,
		BadPadding   = -5
	};

	ParseStatus findRegs(libcamera::Span<const uint8_t> buffer);

	OffsetMap offsets_;
};

} // namespace RPi