/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. * * camera_proxy.cpp - Proxy to camera devices */ #include "camera_proxy.h" #include #include #include "log.h" #include "message.h" #include "utils.h" #include "camera_device.h" #include "thread_rpc.h" using namespace libcamera; LOG_DECLARE_CATEGORY(HAL); /* * \class CameraProxy * * The CameraProxy wraps a CameraDevice and implements the camera3_device_t * API, bridging calls received from the camera framework to the CameraDevice. * * Bridging operation calls between the framework and the CameraDevice is * required as the two run in two different threads and certain operations, * such as queueing a new capture request to the camera, shall be called in * the thread that dispatches events. Other operations do not require any * bridging and resolve to direct function calls on the CameraDevice instance * instead. */ static int hal_dev_initialize(const struct camera3_device *dev, const camera3_callback_ops_t *callback_ops) { if (!dev) return -EINVAL; CameraProxy *proxy = reinterpret_cast(dev->priv); proxy->initialize(callback_ops); return 0; } static int hal_dev_configure_streams(const struct camera3_device *dev, camera3_stream_configuration_t *stream_list) { if (!dev) return -EINVAL; CameraProxy *proxy = reinterpret_cast(dev->priv); return proxy->configureStreams(stream_list); } static const camera_metadata_t * hal_dev_construct_default_request_settings(const struct camera3_device *dev, int type) { if (!dev) return nullptr; CameraProxy *proxy = reinterpret_cast(dev->priv); return proxy->constructDefaultRequestSettings(type); } static int hal_dev_process_capture_request(const struct camera3_device *dev, camera3_capture_request_t *request) { if (!dev) return -EINVAL; CameraProxy *proxy = reinterpret_cast(dev->priv); return proxy->processCaptureRequest(request); } static void hal_dev_dump(const struct camera3_device *dev, int fd) { } static int hal_dev_flush(const struct camera3_device *dev) { return 0; } static int hal_dev_close(hw_device_t *hw_device) { if (!hw_device) return -EINVAL; camera3_device_t *dev = reinterpret_cast(hw_device); CameraProxy *proxy = reinterpret_cast(dev->priv); proxy->close(); return 0; } static camera3_device_ops hal_dev_ops = { .initialize = hal_dev_initialize, .configure_streams = hal_dev_configure_streams, .register_stream_buffers = nullptr, .construct_default_request_settings = hal_dev_construct_default_request_settings, .process_capture_request = hal_dev_process_capture_request, .get_metadata_vendor_tag_ops = nullptr, .dump = hal_dev_dump, .flush = hal_dev_flush, .reserved = { nullptr }, }; CameraProxy::CameraProxy(unsigned int id, const std::shared_ptr &camera) : id_(id) { cameraDevice_ = new CameraDevice(id, camera); } CameraProxy::~CameraProxy() { delete cameraDevice_; } int CameraProxy::open(const hw_module_t *hardwareModule) { int ret = cameraDevice_->open(); if (ret) return ret; /* Initialize the hw_device_t in the instance camera3_module_t. */ camera3Device_.common.tag = HARDWARE_DEVICE_TAG; camera3Device_.common.version = CAMERA_DEVICE_API_VERSION_3_3; camera3Device_.common.module = (hw_module_t *)hardwareModule; camera3Device_.common.close = hal_dev_close; /* * The camera device operations. These actually implement * the Android Camera HALv3 interface. */ camera3Device_.ops = &hal_dev_ops; camera3Device_.priv = this; return 0; } void CameraProxy::close() { ThreadRpc rpcRequest; rpcRequest.tag = ThreadRpc::Close; threadRpcCall(rpcRequest); } void CameraProxy::initialize(const camera3_callback_ops_t *callbacks) { cameraDevice_->setCallbacks(callbacks); } const camera_metadata_t *CameraProxy::getStaticMetadata() { return cameraDevice_->getStaticMetadata(); } const camera_metadata_t *CameraProxy::constructDefaultRequestSettings(int type) { return cameraDevice_->constructDefaultRequestSettings(type); } int CameraProxy::configureStreams(camera3_stream_configuration_t *stream_list) { return cameraDevice_->configureStreams(stream_list); } int CameraProxy::processCaptureRequest(camera3_capture_request_t *request) { ThreadRpc rpcRequest; rpcRequest.tag = ThreadRpc::ProcessCaptureRequest; rpcRequest.request = request; threadRpcCall(rpcRequest); return 0; } void CameraProxy::threadRpcCall(ThreadRpc &rpcRequest) { cameraDevice_->invokeMethod(&CameraDevice::call, &rpcRequest); rpcRequest.waitDelivery(); }