/* 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), bits_per_pixel_(0), num_lines_(0), line_length_bytes_(0) { } virtual ~MdParser() = default; void Reset() { reset_ = true; } void SetBitsPerPixel(int bpp) { bits_per_pixel_ = bpp; } void SetNumLines(unsigned int num_lines) { num_lines_ = num_lines; } void SetLineLengthBytes(unsigned int num_bytes) { line_length_bytes_ = num_bytes; } virtual Status Parse(libcamera::Span<const uint8_t> buffer, RegisterMap ®isters) = 0; protected: bool reset_; int bits_per_pixel_; unsigned int num_lines_; unsigned int line_length_bytes_; }; /* * 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 ®isters) 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: * PARSE_OK - found all registers, much happiness * MISSING_REGS - some registers found; should this be a hard error? * The remaining codes are all hard errors. */ enum ParseStatus { PARSE_OK = 0, MISSING_REGS = 1, NO_LINE_START = -1, ILLEGAL_TAG = -2, BAD_DUMMY = -3, BAD_LINE_END = -4, BAD_PADDING = -5 }; ParseStatus findRegs(libcamera::Span<const uint8_t> buffer); OffsetMap offsets_; }; } // namespace RPi