From patchwork Mon Aug 10 12:04:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9273 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6460CBD87E for ; Mon, 10 Aug 2020 12:04:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 48CA560F72; Mon, 10 Aug 2020 14:04:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="TJMaHJ2d"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 69CE66038C for ; Mon, 10 Aug 2020 14:04:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=4S5AU31LwYsKdg3XtpmVn1HGzj2LiTc8pFtq4RaXXR4=; b=TJMaHJ2dA6e2b/CYn10bUdmDRjrfSOH7c/b9F2irvC+WbOUhZBbw5Q3G7gVsSOpAonlw 39mS61ScHV7dgl+b11gA0mIJimF12Yqo2F618oVCJ/OBKZ4DeN4gbwWDgNyEIkc10iKjgY /0UEO/tV32/euVIrLaAfKzbQmxZCiPmBs= Received: by filterdrecv-p3mdw1-7ff865655c-m68sw with SMTP id filterdrecv-p3mdw1-7ff865655c-m68sw-20-5F3137BB-94 2020-08-10 12:04:11.916873617 +0000 UTC m=+1014473.745401019 Received: from mail.uajain.com (unknown) by ismtpd0005p1maa1.sendgrid.net (SG) with ESMTP id _BTqMKDXRNmn_uxe1HbCpA for ; Mon, 10 Aug 2020 12:04:11.571 +0000 (UTC) From: Umang Jain Date: Mon, 10 Aug 2020 12:04:11 +0000 (UTC) Message-Id: <20200810120406.52654-2-email@uajain.com> In-Reply-To: <20200810120406.52654-1-email@uajain.com> References: <20200810120406.52654-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPc9vLW9W8H4bP+KZ0PPVtunxkrf1/W/GGIxTt+w0T9coG+TvKWFla874XTCVC06G0uYrHkhIxtRas0H6PgWUg0T6cUukIag/BVGRRbUiJV9R89aK7U+SUJLSeul57LTwW/3FGpcMdnGUcTz930fJIqKz7lopIJdr/eZ0jw4hB5gKlZToXN6WVvM3l5JloVGt5rWNVS6bMc0byH4KY+GO1FlQ== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v2 1/4] libcamera: pipeline: uvcvideo: Treat all UVC cameras as external X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Treat all UVC cameras as external for android framework to know that they are external. Signed-off-by: Umang Jain Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index bc892ec..ed61d12 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -500,6 +501,9 @@ int UVCCameraData::init(MediaEntity *entity) video_->bufferReady.connect(this, &UVCCameraData::bufferReady); + /* Initialise Camera Property. Treat all UVC cameras as external. */ + properties_.set(properties::Location, properties::CameraLocationExternal); + /* Initialise the supported controls. */ ControlInfoMap::Map ctrls; From patchwork Mon Aug 10 12:04:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9275 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 50088BD87D for ; Mon, 10 Aug 2020 12:04:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 02C0D60F27; Mon, 10 Aug 2020 14:04:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="im6wGym6"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E7CC06038C for ; Mon, 10 Aug 2020 14:04:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc:content-type: content-transfer-encoding; s=s1; bh=NpzXUTaK7DGo35/Hk0V3wovwomh9y0Hw9oJ5sPFR660=; b=im6wGym6pkcy0YLk7fWjOfo+3YfCzrET2rid8xC7B8oy1FH8PpmZ7N4inLGFwVoSBT9s ofYHUyDvvhmf/z4KdePrLTlkN6i0M6syKfnWgE5y2ZG3ng8gD8ZJ55WCJFGbPfUDwsOyqa XE4ADoYYLxVjM2YEfGJUEpglUlCIyk4Rs= Received: by filterdrecv-p3las1-559bd7b968-wk85c with SMTP id filterdrecv-p3las1-559bd7b968-wk85c-19-5F3137BD-D8 2020-08-10 12:04:13.788531266 +0000 UTC m=+1014484.522177987 Received: from mail.uajain.com (unknown) by ismtpd0003p1hnd1.sendgrid.net (SG) with ESMTP id vnrY0zDPRNaRyHvfEjTAKg Mon, 10 Aug 2020 12:04:13.351 +0000 (UTC) From: Umang Jain Date: Mon, 10 Aug 2020 12:04:13 +0000 (UTC) Message-Id: <20200810120406.52654-3-email@uajain.com> In-Reply-To: <20200810120406.52654-1-email@uajain.com> References: <20200810120406.52654-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcHFp8snzxo7RIC2IEYmqCh8eqmJwZ8TxXIULxuhbQ1Ep4YxhY1UUk5omtrK3PtBKbCuwDMxAmoDMyp1emDzQ3rSnQfYiu1Y058YyCiizyxQl5fXJK3uUva2/sG7VcvDReqWxBlFQ8hHAP58YKPWAPS9rks5Op8X+ifSkULbKozyL4kt69E1+RQ/I8cJt2asAjzptii+7JfH94ZjNAQV3uug== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v2 2/4] android: camera_hal_manager: Set camera module callbacks X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" camera_module_callbacks are invoked to inform the framework about the events occuring module-wide. Allow to set these callbacks in camera_hal_manager as this will be used to integration camera hotplug support via camera_module_callbacks::camera_device_status_change in subsequent commit. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- src/android/camera3_hal.cpp | 2 ++ src/android/camera_hal_manager.cpp | 5 +++++ src/android/camera_hal_manager.h | 3 +++ 3 files changed, 10 insertions(+) diff --git a/src/android/camera3_hal.cpp b/src/android/camera3_hal.cpp index 716e36c..c2cba29 100644 --- a/src/android/camera3_hal.cpp +++ b/src/android/camera3_hal.cpp @@ -34,6 +34,8 @@ static int hal_get_camera_info(int id, struct camera_info *info) static int hal_set_callbacks(const camera_module_callbacks_t *callbacks) { + cameraManager.setCallbacks(callbacks); + return 0; } diff --git a/src/android/camera_hal_manager.cpp b/src/android/camera_hal_manager.cpp index 02b6418..3d6d2b4 100644 --- a/src/android/camera_hal_manager.cpp +++ b/src/android/camera_hal_manager.cpp @@ -120,3 +120,8 @@ int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) return 0; } + +void CameraHalManager::setCallbacks(const camera_module_callbacks_t *callbacks) +{ + callbacks_ = callbacks; +} diff --git a/src/android/camera_hal_manager.h b/src/android/camera_hal_manager.h index 0619037..a582f04 100644 --- a/src/android/camera_hal_manager.h +++ b/src/android/camera_hal_manager.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -29,10 +30,12 @@ public: unsigned int numCameras() const; int getCameraInfo(unsigned int id, struct camera_info *info); + void setCallbacks(const camera_module_callbacks_t *callbacks); private: libcamera::CameraManager *cameraManager_; + const camera_module_callbacks_t *callbacks_; std::vector> cameras_; }; From patchwork Mon Aug 10 12:04:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9276 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A5599BD87E for ; Mon, 10 Aug 2020 12:04:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6186A61054; Mon, 10 Aug 2020 14:04:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="WyNfPAqW"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3228560F1D for ; Mon, 10 Aug 2020 14:04:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=M8aQgNhnE+DYpjlzQU2EkiFf6G69fJp/ilD7RDwFstU=; b=WyNfPAqW25U8xH0y5haUb2u6v9QZPzBMWxKtskQtruzfC9FQs3R0p8Pcl4Frq6R0Jqbc 02+uobvBULk15k01CjQt+OINxYy/3mc4foTq/X5n64hCRqUwHSax6w2bx/R/ZXuCh5QD0a F8VVb7CVTmcAvo0ueKDB0avxwvYs3Dthw= Received: by filterdrecv-p3las1-559bd7b968-2g29q with SMTP id filterdrecv-p3las1-559bd7b968-2g29q-19-5F3137BD-13A 2020-08-10 12:04:14.047155862 +0000 UTC m=+1014490.091964234 Received: from mail.uajain.com (unknown) by ismtpd0002p1maa1.sendgrid.net (SG) with ESMTP id qT9G6iTAThiZIB59QpMWWA for ; Mon, 10 Aug 2020 12:04:13.632 +0000 (UTC) From: Umang Jain Date: Mon, 10 Aug 2020 12:04:14 +0000 (UTC) Message-Id: <20200810120406.52654-4-email@uajain.com> In-Reply-To: <20200810120406.52654-1-email@uajain.com> References: <20200810120406.52654-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPc4om/Oij3lMEQBxKPi/30O1C7bNFrpbmMJqYozJm+2XE3DPizDXOrMbEn6An6vJDVO5OjqO0feTUot5T1cQ5l2cmgjQ0aHh508gnnWwa6Rb/kEIdNJSPjzsY7po1iTf0G552YCD00hYY5QPkxeK4qC30kJ0HDB+Dp6fM5PED+/dVU4/fEjTBEBcV7Oa37s+czIbzX14nXesKnn0t724GH/Q== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v2 3/4] android: camera_hal_manager: Support camera hotplug X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend the support for camera hotplug from libcamera's CameraManager to CameraHalManager. Use camera module callbacks to let the framework know about the hotplug events and change the status of cameras being being hotplugged or unplugged via camera_device_status_change(). Introduce a map camerasMap_ which book-keeps all cameras seen in the past by the CameraHalManager. If the camera is seen for the first time, a new id is assigned to it. If the camera has been seen before by the manager, it's old id is reused. IDs for internal cameras start with '0' and for external cameras, they start with '1000'. Note, for the current implementation, we assume all UVC cameras are external cameras. CameraDevice is now a shared object and cameras_ vector stores shared pointers to CameraDevice. This is done in order to introduce reference counting for CameraDevice objects - especially to handle hot-unplug events. Both camerasMap_ and cameras_ are protected by a mutex. Signed-off-by: Umang Jain --- src/android/camera_device.cpp | 15 +++ src/android/camera_device.h | 8 +- src/android/camera_hal_manager.cpp | 153 ++++++++++++++++++++++++----- src/android/camera_hal_manager.h | 15 ++- 4 files changed, 166 insertions(+), 25 deletions(-) diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index d918350..a79bb69 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -233,6 +233,21 @@ CameraDevice::~CameraDevice() delete it.second; } +std::shared_ptr CameraDevice::create(unsigned int id, + const std::shared_ptr &cam) +{ + struct Deleter : std::default_delete { + void operator()(CameraDevice *camera) + { + delete camera; + } + }; + + CameraDevice *camera = new CameraDevice(id, cam); + + return std::shared_ptr(camera, Deleter()); +} + /* * Initialize the camera static information. * This method is called before the camera device is opened. diff --git a/src/android/camera_device.h b/src/android/camera_device.h index 7be9e11..7f9e010 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -47,8 +47,8 @@ struct CameraStream { class CameraDevice : protected libcamera::Loggable { public: - CameraDevice(unsigned int id, const std::shared_ptr &camera); - ~CameraDevice(); + static std::shared_ptr create(unsigned int id, + const std::shared_ptr &cam); int initialize(); @@ -57,6 +57,7 @@ public: unsigned int id() const { return id_; } camera3_device_t *camera3Device() { return &camera3Device_; } + const libcamera::Camera *getCamera() { return camera_.get(); }; int facing() const { return facing_; } int orientation() const { return orientation_; } @@ -72,6 +73,9 @@ protected: std::string logPrefix() const override; private: + CameraDevice(unsigned int id, const std::shared_ptr &camera); + ~CameraDevice(); + struct Camera3RequestDescriptor { Camera3RequestDescriptor(unsigned int frameNumber, unsigned int numBuffers); diff --git a/src/android/camera_hal_manager.cpp b/src/android/camera_hal_manager.cpp index 3d6d2b4..fdde2c0 100644 --- a/src/android/camera_hal_manager.cpp +++ b/src/android/camera_hal_manager.cpp @@ -8,6 +8,7 @@ #include "camera_hal_manager.h" #include +#include #include "libcamera/internal/log.h" @@ -35,6 +36,7 @@ CameraHalManager::CameraHalManager() CameraHalManager::~CameraHalManager() { cameras_.clear(); + camerasMap_.clear(); if (cameraManager_) { cameraManager_->stop(); @@ -47,6 +49,13 @@ int CameraHalManager::init() { cameraManager_ = new CameraManager(); + /* Support camera hotplug. */ + cameraManager_->cameraAdded.connect(this, &CameraHalManager::cameraAdded); + cameraManager_->cameraRemoved.connect(this, &CameraHalManager::cameraRemoved); + + cameraCounter_ = 0; + externalCameraCounter_ = 1000; + int ret = cameraManager_->start(); if (ret) { LOG(HAL, Error) << "Failed to start camera manager: " @@ -56,35 +65,25 @@ int CameraHalManager::init() return ret; } - /* - * For each Camera registered in the system, a CameraDevice - * gets created here to wraps a libcamera Camera instance. - * - * \todo Support camera hotplug. - */ - unsigned int index = 0; - for (auto &cam : cameraManager_->cameras()) { - CameraDevice *camera = new CameraDevice(index, cam); - ret = camera->initialize(); - if (ret) - continue; - - cameras_.emplace_back(camera); - ++index; - } - return 0; } CameraDevice *CameraHalManager::open(unsigned int id, const hw_module_t *hardwareModule) { - if (id >= numCameras()) { + MutexLocker locker(mutex_); + + auto iter = std::find_if(cameras_.begin(), cameras_.end(), + [id](std::shared_ptr &cam) { + return cam->id() == id; + }); + if (iter == cameras_.end()) { LOG(HAL, Error) << "Invalid camera id '" << id << "'"; return nullptr; } - CameraDevice *camera = cameras_[id].get(); + CameraDevice *camera = iter->get(); + if (camera->open(hardwareModule)) return nullptr; @@ -93,9 +92,91 @@ CameraDevice *CameraHalManager::open(unsigned int id, return camera; } +void CameraHalManager::cameraAdded(std::shared_ptr cam) +{ + unsigned int id; + bool isCameraExternal = false; + bool isCameraNew = false; + + MutexLocker locker(mutex_); + + /* Each camera is assigned a unique integer id when it is seen for the + * first time. If the camera has been seen before, the id is reused and + * the camera is marked as CAMERA_DEVICE_STATUS_PRESENT subsequently. + * + * ID starts from '0' for internal cameras and '1000' for external cameras. + */ + auto iter = camerasMap_.find(cam->id()); + if (iter != camerasMap_.end()) { + id = iter->second; + } else { + isCameraNew = true; + + /* + * Now check if this is an external camera and assign + * its id accordingly. + */ + const ControlList &properties = cam->properties(); + if (properties.contains(properties::Location) && + properties.get(properties::Location) & + properties::CameraLocationExternal) { + isCameraExternal = true; + id = externalCameraCounter_; + } else { + id = cameraCounter_; + } + } + + /* + * For each Camera registered in the system, a CameraDevice + * gets created here to wraps a libcamera Camera instance. + */ + std::shared_ptr camera = CameraDevice::create(id, std::move(cam)); + int ret = camera->initialize(); + if (ret) { + LOG(HAL, Error) << "Failed to initialize camera: " << cam->id(); + return; + } + + if (isCameraNew) { + camerasMap_.emplace(cam->id(), id); + + if (isCameraExternal) + externalCameraCounter_++; + else + cameraCounter_++; + } + + cameras_.emplace_back(std::move(camera)); + + if (callbacks_) + callbacks_->camera_device_status_change(callbacks_, id, + CAMERA_DEVICE_STATUS_PRESENT); + LOG(HAL, Debug) << "Camera ID: " << id << " added successfully."; +} + +void CameraHalManager::cameraRemoved(std::shared_ptr cam) +{ + MutexLocker locker(mutex_); + + auto iter = std::find_if(cameras_.begin(), cameras_.end(), + [cam](std::shared_ptr &camera) { + return cam.get() == camera->getCamera(); + }); + if (iter == cameras_.end()) + return; + + unsigned int id = (*iter)->id(); + callbacks_->camera_device_status_change(callbacks_, id, + CAMERA_DEVICE_STATUS_NOT_PRESENT); + cameras_.erase(iter); + + LOG(HAL, Debug) << "Camera ID: " << id << " removed successfully."; +} + unsigned int CameraHalManager::numCameras() const { - return cameraManager_->cameras().size(); + return cameraCounter_; } int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) @@ -103,12 +184,18 @@ int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) if (!info) return -EINVAL; - if (id >= numCameras()) { + MutexLocker locker(mutex_); + + auto iter = std::find_if(cameras_.begin(), cameras_.end(), + [id](std::shared_ptr &cam) { + return cam->id() == id; + }); + if (iter == cameras_.end()) { LOG(HAL, Error) << "Invalid camera id '" << id << "'"; return -EINVAL; } - CameraDevice *camera = cameras_[id].get(); + CameraDevice *camera = iter->get(); info->facing = camera->facing(); info->orientation = camera->orientation(); @@ -124,4 +211,26 @@ int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info) void CameraHalManager::setCallbacks(const camera_module_callbacks_t *callbacks) { callbacks_ = callbacks; + + MutexLocker locker(mutex_); + /* + * Few cameras might have been hotplugged before setting callbacks_ here. + * We need to mark CAMERA_DEVICE_STATUS_PRESENT for them explicitly. + * This hold only for external cameras, as internal cameras are assumed to + * be present at module load time, by the framework. + */ + for (auto &cam : cameraManager_->cameras()) { + auto iter = camerasMap_.find(cam->id()); + if (iter == camerasMap_.end()) + continue; + + unsigned int id = iter->second; + const ControlList &properties = cam->properties(); + if (properties.contains(properties::Location) && + properties.get(properties::Location) & + properties::CameraLocationExternal) { + callbacks_->camera_device_status_change(callbacks_, id, + CAMERA_DEVICE_STATUS_PRESENT); + } + } } diff --git a/src/android/camera_hal_manager.h b/src/android/camera_hal_manager.h index a582f04..7c481d4 100644 --- a/src/android/camera_hal_manager.h +++ b/src/android/camera_hal_manager.h @@ -7,6 +7,8 @@ #ifndef __ANDROID_CAMERA_MANAGER_H__ #define __ANDROID_CAMERA_MANAGER_H__ +#include +#include #include #include @@ -18,6 +20,9 @@ class CameraDevice; +using Mutex = std::mutex; +using MutexLocker = std::unique_lock; + class CameraHalManager { public: @@ -33,10 +38,18 @@ public: void setCallbacks(const camera_module_callbacks_t *callbacks); private: + void cameraAdded(std::shared_ptr cam); + void cameraRemoved(std::shared_ptr cam); + libcamera::CameraManager *cameraManager_; const camera_module_callbacks_t *callbacks_; - std::vector> cameras_; + std::vector> cameras_; + std::map camerasMap_; + Mutex mutex_; + + unsigned int externalCameraCounter_; + unsigned int cameraCounter_; }; #endif /* __ANDROID_CAMERA_MANAGER_H__ */ From patchwork Mon Aug 10 12:04:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9274 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D481FBD87D for ; Mon, 10 Aug 2020 12:04:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A0BD460DCA; Mon, 10 Aug 2020 14:04:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="vrY0woxL"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0657460E89 for ; Mon, 10 Aug 2020 14:04:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=hRI3QrkrdUUb2GfoxLz6TSSt2ZtkOZOlo3hKcH4mQIo=; b=vrY0woxLq8rOya3FVh71M+t4LJFEB/c1S23IRDyOuNnQAIgLu09dfzRDjV5PB4YMSL6D uTCoBZWh9GMeXZhKMCxHpeOsx18aK2O8qsLevxricFT9EdwV07MoEiFFj3ftBwtMybGRH+ /4kjo7h6j49g7sjc7yeq29ykSS0AgIkXQ= Received: by filterdrecv-p3mdw1-7ff865655c-8dgl4 with SMTP id filterdrecv-p3mdw1-7ff865655c-8dgl4-17-5F3137BE-AA 2020-08-10 12:04:14.852928121 +0000 UTC m=+1014484.473196805 Received: from mail.uajain.com (unknown) by ismtpd0006p1maa1.sendgrid.net (SG) with ESMTP id dv0XAPOxRNKcg96xkeHjSQ for ; Mon, 10 Aug 2020 12:04:14.467 +0000 (UTC) From: Umang Jain Date: Mon, 10 Aug 2020 12:04:14 +0000 (UTC) Message-Id: <20200810120406.52654-5-email@uajain.com> In-Reply-To: <20200810120406.52654-1-email@uajain.com> References: <20200810120406.52654-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcO0wIVNwfic3Culi7Uik3lzUh+gFX7nrLTXMz/5XSKoetSIgIsTB3YntnH97XAgGKc06ApYMZ7L0zlgppraeFgCulJ7sEjSlSD7S3r2YOMpV4kFprWoqsp56uD99TvWz035kuC/3/dIyAS5ASQnyKsZASegiFQN14XlruLT24FFlpD865ejz/e9CE1I3NzTRKoKPc93QVM1gNcRwzia7i5w== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v2 4/4] android: camera_hal_manager: Handle hot-unplug of currently open camera X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Maintain an extra ref for the currently open camera in CameraHalManager. This will ensure we have an graceful handling if the currently open camera is hot-unplugged. Signed-off-by: Umang Jain --- src/android/camera_device.h | 1 + src/android/camera_hal_manager.cpp | 18 +++++++++++++++--- src/android/camera_hal_manager.h | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/android/camera_device.h b/src/android/camera_device.h index 7f9e010..2dc0a20 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -61,6 +61,7 @@ public: int facing() const { return facing_; } int orientation() const { return orientation_; } + bool running() { return running_; } void setCallbacks(const camera3_callback_ops_t *callbacks); const camera_metadata_t *getStaticMetadata(); diff --git a/src/android/camera_hal_manager.cpp b/src/android/camera_hal_manager.cpp index fdde2c0..9db5954 100644 --- a/src/android/camera_hal_manager.cpp +++ b/src/android/camera_hal_manager.cpp @@ -38,6 +38,8 @@ CameraHalManager::~CameraHalManager() cameras_.clear(); camerasMap_.clear(); + cameraInUse_.reset(); + if (cameraManager_) { cameraManager_->stop(); delete cameraManager_; @@ -55,6 +57,7 @@ int CameraHalManager::init() cameraCounter_ = 0; externalCameraCounter_ = 1000; + cameraInUse_ = nullptr; int ret = cameraManager_->start(); if (ret) { @@ -82,14 +85,17 @@ CameraDevice *CameraHalManager::open(unsigned int id, return nullptr; } - CameraDevice *camera = iter->get(); + if (cameraInUse_) + cameraInUse_.reset(); + + cameraInUse_ = std::move(*iter); - if (camera->open(hardwareModule)) + if (cameraInUse_->open(hardwareModule)) return nullptr; LOG(HAL, Info) << "Open camera '" << id << "'"; - return camera; + return cameraInUse_.get(); } void CameraHalManager::cameraAdded(std::shared_ptr cam) @@ -169,6 +175,12 @@ void CameraHalManager::cameraRemoved(std::shared_ptr cam) unsigned int id = (*iter)->id(); callbacks_->camera_device_status_change(callbacks_, id, CAMERA_DEVICE_STATUS_NOT_PRESENT); + + if (*iter == cameraInUse_ && cameraInUse_->running()) { + cameraInUse_->close(); + cameraInUse_.reset(); + } + cameras_.erase(iter); LOG(HAL, Debug) << "Camera ID: " << id << " removed successfully."; diff --git a/src/android/camera_hal_manager.h b/src/android/camera_hal_manager.h index 7c481d4..974d53d 100644 --- a/src/android/camera_hal_manager.h +++ b/src/android/camera_hal_manager.h @@ -48,6 +48,8 @@ private: std::map camerasMap_; Mutex mutex_; + std::shared_ptr cameraInUse_; + unsigned int externalCameraCounter_; unsigned int cameraCounter_; };