From patchwork Tue Aug 2 10:29:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cheng-Hao Yang X-Patchwork-Id: 16902 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 9F2DFC3275 for ; Tue, 2 Aug 2022 10:29:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 59D95603E7; Tue, 2 Aug 2022 12:29:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659436197; bh=8owVkMvTwYV4t1VAR7564R18ozCoPyP6Nwle53sKb3E=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=WG0EISoi6COsJ6uKuBNJMVmuHwGyG4rTxKS/hg5sXlKsCYC3bew6JcQPUkkgOK6uf z+/lM81I4XhgDvR5u6v6DuQbL4q4PJ+a0+NsWsLV7XhyM7lHC33ccFt/gLgMEJO7cV nuZWF5EqGdaFWlFwcAHKrrHqhX6BvsMpi/aQuerMWFfMPbRfvfKIabQGfl2OXv46Y0 zTcJ/xbzo5QIvPjklIXDBG5buXglppdMLdL+Se/gmEIRvY5YlURaIeknDgA3lNI24c 5ils0Wbm1BgxzjYJLj3kEQfqsavqRmwamY4YQHpz9ie6cMtPmJF5ian2PaX/l7uibd bI59jtWwwxO1Q== Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7DB63603E7 for ; Tue, 2 Aug 2022 12:29:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="QuqWowKZ"; dkim-atps=neutral Received: by mail-pj1-x1030.google.com with SMTP id b10so13264813pjq.5 for ; Tue, 02 Aug 2022 03:29:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4CKqAm0iSaW6Vegjv6AqPctRCQxnb1ayR2zOADFpnnM=; b=QuqWowKZX2UXkhUbQC2ftMvLLpqI1L+GQ0Zy66OmFfVX0pJCKvUJHewvf0Fb9g6GKD uqyqTmMCXeaND/DTaDXFxG3N86LuDr7LbfOb1NreXAz5C0gS102Hcu/HQD7pKQ215Njl wXVAJCVUHA4nCb0uP+DURWaMwpgsZF+XmJ8Bo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4CKqAm0iSaW6Vegjv6AqPctRCQxnb1ayR2zOADFpnnM=; b=oEZu+KeQfio6qHq/qB2qMmMXE+ymtfevxvKi1Nw9F/4xXKcU9UosEILyNzPG2G3A77 nwaCnIobmlpT4GaNE4dFWd2d+C5k/eDRwtkmbaJ98wLFTTRzF1pf3hOlbSU4rIN8zS1n 9v9F0rfniNp5lLsfd9x+AyuiEJvEVUIf8p7yqe2Jc2mSueeO1Sni8PJBRIzN4mfzGG1j 61XKgoTltvtz3Rs8Bu60cFi2B4xfXcDpTF9ysMcUXqTQOq8h8yBpdrai+B0W2zA/WKtZ W5Id50/zmt7xCMQ6UTj2Raovv1N6cSMhDPOv/3c4y/dJ0hZQl5r5uy9lu/wW2bg0U6M4 bHqg== X-Gm-Message-State: ACgBeo0lgF4pelWCTAiTIJ5Enud8H9KWLcyeyXm3mNcoUhXIeCROHMsY kK26jtJRBW/5jUULJi6B2cTsNN03/hnp9A== X-Google-Smtp-Source: AA6agR4gkBvVG4Vp6j4Z3BuGJeU6x8P/7W7iKPRSXDu/ZZdCOp3JLMW9JVaK5o+okfZKssK3uaiMUQ== X-Received: by 2002:a17:90b:3711:b0:1f5:179c:ad64 with SMTP id mg17-20020a17090b371100b001f5179cad64mr5400547pjb.11.1659436193295; Tue, 02 Aug 2022 03:29:53 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (231.137.80.34.bc.googleusercontent.com. [34.80.137.231]) by smtp.gmail.com with ESMTPSA id t15-20020a170902e84f00b0016db88f69a2sm1955128plg.141.2022.08.02.03.29.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Aug 2022 03:29:52 -0700 (PDT) X-Google-Original-From: Harvey Yang To: libcamera-devel@lists.libcamera.org Date: Tue, 2 Aug 2022 10:29:37 +0000 Message-Id: <20220802102943.3221109-4-chenghaoyang@google.com> X-Mailer: git-send-email 2.37.1.455.g008518b4e5-goog In-Reply-To: <20220802102943.3221109-1-chenghaoyang@google.com> References: <20220802102943.3221109-1-chenghaoyang@google.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/9] ipu3: Use imgu0 as default 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: , X-Patchwork-Original-From: Harvey Yang via libcamera-devel From: Cheng-Hao Yang Reply-To: Harvey Yang Cc: Harvey Yang Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Harvey Yang With only one camera being started, we can always use imgu0 to process frames (for video/preview). In the following patches, we'll use imgu1 for still capture if needed. Signed-off-by: Harvey Yang --- src/libcamera/pipeline/ipu3/imgu.cpp | 13 ++++ src/libcamera/pipeline/ipu3/imgu.h | 2 + src/libcamera/pipeline/ipu3/ipu3.cpp | 96 ++++++++++++++-------------- 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index e5bbc382..aa72b1ec 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -765,4 +765,17 @@ int ImgUDevice::enableLinks(bool enable) return linkSetup(name_, PAD_STAT, statName, 0, enable); } +/** + * \brief Disconnect bufferReady signals from |input_|, |param_|, |output_|, + * |viewfinder_|, and |stat_|. + */ +void ImgUDevice::disconnectSignals() +{ + input_->bufferReady.disconnect(); + param_->bufferReady.disconnect(); + output_->bufferReady.disconnect(); + viewfinder_->bufferReady.disconnect(); + stat_->bufferReady.disconnect(); +} + } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/ipu3/imgu.h b/src/libcamera/pipeline/ipu3/imgu.h index 0af4dd8a..aa88e36e 100644 --- a/src/libcamera/pipeline/ipu3/imgu.h +++ b/src/libcamera/pipeline/ipu3/imgu.h @@ -92,6 +92,8 @@ public: int enableLinks(bool enable); + void disconnectSignals(); + std::unique_ptr imgu_; std::unique_ptr input_; std::unique_ptr param_; diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 091a40e1..c3e90f22 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -64,7 +64,8 @@ public: void frameStart(uint32_t sequence); CIO2Device cio2_; - ImgUDevice *imgu_; + ImgUDevice *imgu0_; + ImgUDevice *imgu1_; Stream outStream_; Stream vfStream_; @@ -406,7 +407,7 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() /* Only compute the ImgU configuration if a YUV stream has been requested. */ if (yuvCount) { - pipeConfig_ = data_->imgu_->calculatePipeConfig(&pipe); + pipeConfig_ = data_->imgu0_->calculatePipeConfig(&pipe); if (pipeConfig_.isNull()) { LOG(IPU3, Error) << "Failed to calculate pipe configuration: " << "unsupported resolutions."; @@ -518,16 +519,12 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) Stream *outStream = &data->outStream_; Stream *vfStream = &data->vfStream_; CIO2Device *cio2 = &data->cio2_; - ImgUDevice *imgu = data->imgu_; V4L2DeviceFormat outputFormat; int ret; /* - * FIXME: enabled links in one ImgU pipe interfere with capture - * operations on the other one. This can be easily triggered by - * capturing from one camera and then trying to capture from the other - * one right after, without disabling media links on the first used - * pipe. + * Enabled links in one ImgU pipe interfere with capture + * operations on the other one. * * The tricky part here is where to disable links on the ImgU instance * which is currently not in use: @@ -543,11 +540,11 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) * configuring the device, to allow alternate the usage of the two * ImgU pipes. * - * As a consequence, a Camera using an ImgU shall be configured before - * any start()/stop() sequence. An application that wants to - * pre-configure all the camera and then start/stop them alternatively - * without going through any re-configuration (a sequence that is - * allowed by the Camera state machine) would now fail on the IPU3. + * Now that only one camera is allowed to be used at the same time, we + * don't need to handle the complicated interference between the two + * ImgU links. Therefore, an application still cannot pre-configure all + * the cameras and then start/stop them alternatively without going + * throught any re-configuration. */ ret = imguMediaDev_->disableLinks(); if (ret) @@ -560,7 +557,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) * stream which is for raw capture, in which case no buffers will * ever be queued to the ImgU. */ - ret = data->imgu_->enableLinks(true); + ret = imgu0_.enableLinks(true); if (ret) return ret; @@ -610,7 +607,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) if (imguConfig.isNull()) return 0; - ret = imgu->configure(imguConfig, &cio2Format); + ret = imgu0_.configure(imguConfig, &cio2Format); if (ret) return ret; @@ -624,12 +621,12 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) if (stream == outStream) { mainCfg = &cfg; - ret = imgu->configureOutput(cfg, &outputFormat); + ret = imgu0_.configureOutput(cfg, &outputFormat); if (ret) return ret; } else if (stream == vfStream) { vfCfg = &cfg; - ret = imgu->configureViewfinder(cfg, &outputFormat); + ret = imgu0_.configureViewfinder(cfg, &outputFormat); if (ret) return ret; } @@ -641,13 +638,13 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) * be at least one active stream in the configuration request). */ if (!vfCfg) { - ret = imgu->configureViewfinder(*mainCfg, &outputFormat); + ret = imgu0_.configureViewfinder(*mainCfg, &outputFormat); if (ret) return ret; } /* Apply the "pipe_mode" control to the ImgU subdevice. */ - ControlList ctrls(imgu->imgu_->controls()); + ControlList ctrls(imgu0_.imgu_->controls()); /* * Set the ImgU pipe mode to 'Video' unconditionally to have statistics * generated. @@ -657,7 +654,7 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) */ ctrls.set(V4L2_CID_IPU3_PIPE_MODE, static_cast(IPU3PipeModeVideo)); - ret = imgu->imgu_->setControls(&ctrls); + ret = imgu0_.imgu_->setControls(&ctrls); if (ret) { LOG(IPU3, Error) << "Unable to set pipe_mode control"; return ret; @@ -691,9 +688,9 @@ int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream, unsigned int count = stream->configuration().bufferCount; if (stream == &data->outStream_) - return data->imgu_->output_->exportBuffers(count, buffers); + return imgu0_.output_->exportBuffers(count, buffers); else if (stream == &data->vfStream_) - return data->imgu_->viewfinder_->exportBuffers(count, buffers); + return imgu0_.viewfinder_->exportBuffers(count, buffers); else if (stream == &data->rawStream_) return data->cio2_.exportBuffers(count, buffers); @@ -711,7 +708,6 @@ int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream, int PipelineHandlerIPU3::allocateBuffers(Camera *camera) { IPU3CameraData *data = cameraData(camera); - ImgUDevice *imgu = data->imgu_; unsigned int bufferCount; int ret; @@ -721,26 +717,26 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera) data->rawStream_.configuration().bufferCount, }); - ret = imgu->allocateBuffers(bufferCount); + ret = imgu0_.allocateBuffers(bufferCount); if (ret < 0) return ret; /* Map buffers to the IPA. */ unsigned int ipaBufferId = 1; - for (const std::unique_ptr &buffer : imgu->paramBuffers_) { + for (const std::unique_ptr &buffer : imgu0_.paramBuffers_) { buffer->setCookie(ipaBufferId++); ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes()); } - for (const std::unique_ptr &buffer : imgu->statBuffers_) { + for (const std::unique_ptr &buffer : imgu0_.statBuffers_) { buffer->setCookie(ipaBufferId++); ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes()); } data->ipa_->mapBuffers(ipaBuffers_); - data->frameInfos_.init(imgu->paramBuffers_, imgu->statBuffers_); + data->frameInfos_.init(imgu0_.paramBuffers_, imgu0_.statBuffers_); data->frameInfos_.bufferAvailable.connect( data, &IPU3CameraData::queuePendingRequests); @@ -760,7 +756,7 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera) data->ipa_->unmapBuffers(ids); ipaBuffers_.clear(); - data->imgu_->freeBuffers(); + imgu0_.freeBuffers(); return 0; } @@ -785,9 +781,18 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlLis IPU3CameraData *data = cameraData(camera); CIO2Device *cio2 = &data->cio2_; - ImgUDevice *imgu = data->imgu_; int ret; + imgu0_.input_->bufferReady.connect(&data->cio2_, + &CIO2Device::tryReturnBuffer); + imgu0_.output_->bufferReady.connect(data, + &IPU3CameraData::imguOutputBufferReady); + imgu0_.viewfinder_->bufferReady.connect(data, + &IPU3CameraData::imguOutputBufferReady); + imgu0_.param_->bufferReady.connect(data, + &IPU3CameraData::paramBufferReady); + imgu0_.stat_->bufferReady.connect(data, + &IPU3CameraData::statBufferReady); /* Disable test pattern mode on the sensor, if any. */ ret = cio2->sensor()->setTestPatternMode( controls::draft::TestPatternModeEnum::TestPatternModeOff); @@ -813,19 +818,21 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlLis if (ret) goto error; - ret = imgu->start(); + ret = imgu0_.start(); if (ret) goto error; return 0; error: - imgu->stop(); + imgu0_.stop(); cio2->stop(); data->ipa_->stop(); freeBuffers(camera); LOG(IPU3, Error) << "Failed to start camera " << camera->id(); + imgu0_.disconnectSignals(); + return ret; } @@ -838,12 +845,14 @@ void PipelineHandlerIPU3::stopDevice(Camera *camera) data->ipa_->stop(); - ret |= data->imgu_->stop(); + ret |= imgu0_.stop(); ret |= data->cio2_.stop(); if (ret) LOG(IPU3, Warning) << "Failed to stop camera " << camera->id(); freeBuffers(camera); + + imgu0_.disconnectSignals(); } void IPU3CameraData::cancelPendingRequests() @@ -1186,7 +1195,8 @@ int PipelineHandlerIPU3::registerCameras() * only, and assign imgu0 to the first one and imgu1 to the * second. */ - data->imgu_ = numCameras ? &imgu1_ : &imgu0_; + data->imgu0_ = &imgu0_; + data->imgu1_ = &imgu1_; /* * Connect video devices' 'bufferReady' signals to their @@ -1200,16 +1210,6 @@ int PipelineHandlerIPU3::registerCameras() &IPU3CameraData::cio2BufferReady); data->cio2_.bufferAvailable.connect( data.get(), &IPU3CameraData::queuePendingRequests); - data->imgu_->input_->bufferReady.connect(&data->cio2_, - &CIO2Device::tryReturnBuffer); - data->imgu_->output_->bufferReady.connect(data.get(), - &IPU3CameraData::imguOutputBufferReady); - data->imgu_->viewfinder_->bufferReady.connect(data.get(), - &IPU3CameraData::imguOutputBufferReady); - data->imgu_->param_->bufferReady.connect(data.get(), - &IPU3CameraData::paramBufferReady); - data->imgu_->stat_->bufferReady.connect(data.get(), - &IPU3CameraData::statBufferReady); /* Create and register the Camera instance. */ const std::string &cameraId = cio2->sensor()->id(); @@ -1302,14 +1302,14 @@ void IPU3CameraData::paramsBufferReady(unsigned int id) FrameBuffer *outbuffer = it.second; if (stream == &outStream_) - imgu_->output_->queueBuffer(outbuffer); + imgu0_->output_->queueBuffer(outbuffer); else if (stream == &vfStream_) - imgu_->viewfinder_->queueBuffer(outbuffer); + imgu0_->viewfinder_->queueBuffer(outbuffer); } - imgu_->param_->queueBuffer(info->paramBuffer); - imgu_->stat_->queueBuffer(info->statBuffer); - imgu_->input_->queueBuffer(info->rawBuffer); + imgu0_->param_->queueBuffer(info->paramBuffer); + imgu0_->stat_->queueBuffer(info->statBuffer); + imgu0_->input_->queueBuffer(info->rawBuffer); } void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)