/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019, Raspberry Pi Ltd * * image sensor metadata parser interface */ #pragma once #include #include #include #include #include /* * 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; /* * 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 buffer, RegisterMap ®isters) = 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 registerList); MdParser::Status parse(libcamera::Span buffer, RegisterMap ®isters) override; private: /* Maps register address to offset in the buffer. */ using OffsetMap = std::map>; /* * 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 buffer); OffsetMap offsets_; }; } /* namespace RPi */ ef='#n16'>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
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * camera_device.h - libcamera Android Camera Device
 */
#ifndef __ANDROID_CAMERA_DEVICE_H__
#define __ANDROID_CAMERA_DEVICE_H__

#include <map>
#include <memory>
#include <mutex>
#include <queue>
#include <vector>

#include <hardware/camera3.h>

#include <libcamera/base/class.h>
#include <libcamera/base/log.h>
#include <libcamera/base/message.h>
#include <libcamera/base/thread.h>

#include <libcamera/camera.h>
#include <libcamera/framebuffer.h>
#include <libcamera/geometry.h>
#include <libcamera/pixel_format.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>

#include "camera_capabilities.h"
#include "camera_metadata.h"
#include "camera_stream.h"
#include "camera_worker.h"
#include "jpeg/encoder.h"

struct CameraConfigData;
class CameraDevice : protected libcamera::Loggable
{
public:
	static std::unique_ptr<CameraDevice> create(unsigned int id,
						    std::shared_ptr<libcamera::Camera> cam);
	~CameraDevice();

	int initialize(const CameraConfigData *cameraConfigData);

	int open(const hw_module_t *hardwareModule);
	void close();
	void flush();

	unsigned int id() const { return id_; }
	camera3_device_t *camera3Device() { return &camera3Device_; }
	const CameraCapabilities *capabilities() const { return &capabilities_; }
	const std::shared_ptr<libcamera::Camera> &camera() const { return camera_; }

	const std::string &maker() const { return maker_; }
	const std::string &model() const { return model_; }
	int facing() const { return facing_; }
	int orientation() const { return orientation_; }
	unsigned int maxJpegBufferSize() const;

	void setCallbacks(const camera3_callback_ops_t *callbacks);
	const camera_metadata_t *getStaticMetadata();
	const camera_metadata_t *constructDefaultRequestSettings(int type);
	int configureStreams(camera3_stream_configuration_t *stream_list);
	int processCaptureRequest(camera3_capture_request_t *request);
	void requestComplete(libcamera::Request *request);

protected:
	std::string logPrefix() const override;

private:
	LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraDevice)

	CameraDevice(unsigned int id, std::shared_ptr<libcamera::Camera> camera);

	struct Camera3RequestDescriptor {
		enum class Status {
			Pending,
			Success,
			Error,
		};

		Camera3RequestDescriptor() = default;
		~Camera3RequestDescriptor() = default;
		Camera3RequestDescriptor(libcamera::Camera *camera,
					 const camera3_capture_request_t *camera3Request);
		Camera3RequestDescriptor &operator=(Camera3RequestDescriptor &&) = default;

		bool isPending() const { return status_ == Status::Pending; }

		uint32_t frameNumber_ = 0;
		std::vector<camera3_stream_buffer_t> buffers_;
		std::vector<std::unique_ptr<libcamera::FrameBuffer>> frameBuffers_;
		CameraMetadata settings_;
		std::unique_ptr<CaptureRequest> request_;

		camera3_capture_result_t captureResult_ = {};
		Status status_ = Status::Pending;
	};

	enum class State {
		Stopped,
		Flushing,
		Running,
	};

	void stop();

	std::unique_ptr<libcamera::FrameBuffer>
	createFrameBuffer(const buffer_handle_t camera3buffer,
			  libcamera::PixelFormat pixelFormat,
			  const libcamera::Size &size);
	void abortRequest(Camera3RequestDescriptor *descriptor) const;
	bool isValidRequest(camera3_capture_request_t *request) const;
	void notifyShutter(uint32_t frameNumber, uint64_t timestamp);
	void notifyError(uint32_t frameNumber, camera3_stream_t *stream,
			 camera3_error_msg_code code) const;
	int processControls(Camera3RequestDescriptor *descriptor);
	void sendCaptureResults();
	std::unique_ptr<CameraMetadata> getResultMetadata(
		const Camera3RequestDescriptor &descriptor) const;

	unsigned int id_;
	camera3_device_t camera3Device_;

	CameraWorker worker_;

	libcamera::Mutex stateMutex_; /* Protects access to the camera state. */
	State state_;

	std::shared_ptr<libcamera::Camera> camera_;
	std::unique_ptr<libcamera::CameraConfiguration> config_;
	CameraCapabilities capabilities_;

	std::map<unsigned int, std::unique_ptr<CameraMetadata>> requestTemplates_;
	const camera3_callback_ops_t *callbacks_;

	std::vector<CameraStream> streams_;

	libcamera::Mutex descriptorsMutex_; /* Protects descriptors_. */
	std::queue<std::unique_ptr<Camera3RequestDescriptor>> descriptors_;

	std::string maker_;
	std::string model_;

	int facing_;
	int orientation_;

	CameraMetadata lastSettings_;
};

#endif /* __ANDROID_CAMERA_DEVICE_H__ */