From patchwork Thu Apr 18 16:46:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1066 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AD945600F9 for ; Thu, 18 Apr 2019 18:45:52 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 3DA631C0005; Thu, 18 Apr 2019 16:45:52 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:33 +0200 Message-Id: <20190418164638.400-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 1/6] libcamera: ipu3: Create camera with 2 streams X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:52 -0000 Sub-class the Stream class with an IPU3-specific implementation and create each IPU3 camera with two streams: 'output' and 'viewfinder' which represents the video stream from main and secondary ImgU output respectively. Re-work stream configuration to handle the two video streams 'output' and 'viewfinder' separately. As the IPU3 driver requires viewfinder and stat video nodes to be started not to stall ImgU processing, configure 'output', 'viewfinder' and 'stat' regardless of the user-requested active streams. Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 182 +++++++++++++++++++-------- 1 file changed, 130 insertions(+), 52 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 64b4210b4ce3..b9eb872fd5b2 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -62,7 +62,7 @@ public: } int init(MediaDevice *media, unsigned int index); - int configureInput(const StreamConfiguration &config, + int configureInput(const Size &size, V4L2DeviceFormat *inputFormat); int configureOutput(ImgUOutput *output, const StreamConfiguration &config); @@ -112,7 +112,7 @@ public: } int init(const MediaDevice *media, unsigned int index); - int configure(const StreamConfiguration &config, + int configure(const Size &size, V4L2DeviceFormat *outputFormat); BufferPool *exportBuffers(); @@ -130,6 +130,19 @@ public: BufferPool pool_; }; +class IPU3Stream : public Stream +{ +public: + IPU3Stream() + : device_(nullptr), cfg_(nullptr) + { + } + + std::string name_; + ImgUDevice::ImgUOutput *device_; + const StreamConfiguration *cfg_; +}; + class PipelineHandlerIPU3 : public PipelineHandler { public: @@ -170,7 +183,8 @@ private: CIO2Device cio2_; ImgUDevice *imgu_; - Stream stream_; + IPU3Stream outStream_; + IPU3Stream vfStream_; }; static constexpr unsigned int IPU3_BUFFER_COUNT = 4; @@ -209,7 +223,7 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera, { CameraConfiguration configs; IPU3CameraData *data = cameraData(camera); - StreamConfiguration *config = &configs[&data->stream_]; + StreamConfiguration config = {}; /* * FIXME: Soraka: the maximum resolution reported by both sensors @@ -219,15 +233,24 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera, * * \todo Clarify ImgU alignement requirements. */ - config->width = 2560; - config->height = 1920; - config->pixelFormat = V4L2_PIX_FMT_NV12; - config->bufferCount = IPU3_BUFFER_COUNT; + config.width = 2560; + config.height = 1920; + config.pixelFormat = V4L2_PIX_FMT_NV12; + config.bufferCount = IPU3_BUFFER_COUNT; + + configs[&data->outStream_] = config; + LOG(IPU3, Debug) + << "Stream '" << data->outStream_.name_ << "' set to " + << config.width << "x" << config.height << "-0x" + << std::hex << std::setfill('0') << std::setw(8) + << config.pixelFormat; + configs[&data->vfStream_] = config; LOG(IPU3, Debug) - << "Stream format set to " << config->width << "x" - << config->height << "-0x" << std::hex << std::setfill('0') - << std::setw(8) << config->pixelFormat; + << "Stream '" << data->vfStream_.name_ << "' set to " + << config.width << "x" << config.height << "-0x" + << std::hex << std::setfill('0') << std::setw(8) + << config.pixelFormat; return configs; } @@ -236,30 +259,50 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera, const CameraConfiguration &config) { IPU3CameraData *data = cameraData(camera); - const StreamConfiguration &cfg = config[&data->stream_]; + IPU3Stream *outStream = &data->outStream_; + IPU3Stream *vfStream = &data->vfStream_; CIO2Device *cio2 = &data->cio2_; ImgUDevice *imgu = data->imgu_; + Size sensorSize = {}; int ret; - /* - * Verify that the requested size respects the IPU3 alignement - * requirements (the image width shall be a multiple of 8 pixels and - * its height a multiple of 4 pixels) and the camera maximum sizes. - * - * \todo: consider the BDS scaling factor requirements: - * "the downscaling factor must be an integer value multiple of 1/32" - */ - if (cfg.width % 8 || cfg.height % 4) { - LOG(IPU3, Error) << "Invalid stream size: bad alignment"; - return -EINVAL; - } + for (Stream *s : config) { + IPU3Stream *stream = static_cast(s); + const StreamConfiguration &cfg = config[stream]; - const Size &resolution = cio2->sensor_->resolution(); - if (cfg.width > resolution.width || - cfg.height > resolution.height) { - LOG(IPU3, Error) - << "Invalid stream size: larger than sensor resolution"; - return -EINVAL; + /* + * Verify that the requested size respects the IPU3 alignment + * requirements (the image width shall be a multiple of 8 + * pixels and its height a multiple of 4 pixels) and the camera + * maximum sizes. + * + * \todo: Consider the BDS scaling factor requirements: "the + * downscaling factor must be an integer value multiple of 1/32" + */ + if (cfg.width % 8 || cfg.height % 4) { + LOG(IPU3, Error) + << "Invalid stream size: bad alignment"; + return -EINVAL; + } + + const Size &resolution = cio2->sensor_->resolution(); + if (cfg.width > resolution.width || + cfg.height > resolution.height) { + LOG(IPU3, Error) + << "Invalid stream size: larger than sensor resolution"; + return -EINVAL; + } + + /* + * Collect the maximum width and height: IPU3 can downscale + * only. + */ + if (cfg.width > sensorSize.width) + sensorSize.width = cfg.width; + if (cfg.height > sensorSize.height) + sensorSize.height = cfg.height; + + stream->cfg_ = &cfg; } /* @@ -275,24 +318,51 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera, * adjusted format to be propagated to the ImgU output devices. */ V4L2DeviceFormat cio2Format = {}; - ret = cio2->configure(cfg, &cio2Format); + ret = cio2->configure(sensorSize, &cio2Format); if (ret) return ret; - ret = imgu->configureInput(cfg, &cio2Format); + ret = imgu->configureInput(sensorSize, &cio2Format); if (ret) return ret; - /* Apply the format to the ImgU output, viewfinder and stat. */ - ret = imgu->configureOutput(&imgu->output_, cfg); - if (ret) - return ret; + /* Apply the format to the configured streams output devices. */ + for (Stream *s : config) { + IPU3Stream *stream = static_cast(s); - ret = imgu->configureOutput(&imgu->viewfinder_, cfg); - if (ret) - return ret; + ret = imgu->configureOutput(stream->device_, *stream->cfg_); + if (ret) + return ret; + } - ret = imgu->configureOutput(&imgu->stat_, cfg); + /* + * As we need to set format also on the non-active streams, use + * the configuration of the active one for that purpose (there should + * be at least one active stream in the configuration request). + */ + if (!outStream->cfg_) { + ret = imgu->configureOutput(outStream->device_, + *vfStream->cfg_); + if (ret) + return ret; + } + + if (!vfStream->cfg_) { + ret = imgu->configureOutput(vfStream->device_, + *outStream->cfg_); + if (ret) + return ret; + } + + /* + * Apply the largest available format to the stat node. + * \todo Revise this when we'll actually use the stat node. + */ + StreamConfiguration statConfig = {}; + statConfig.width = cio2Format.width; + statConfig.height = cio2Format.height; + + ret = imgu->configureOutput(&imgu->stat_, statConfig); if (ret) return ret; @@ -407,7 +477,7 @@ int PipelineHandlerIPU3::queueRequest(Camera *camera, Request *request) { IPU3CameraData *data = cameraData(camera); V4L2Device *output = data->imgu_->output_.dev; - Stream *stream = &data->stream_; + IPU3Stream *stream = &data->outStream_; /* Queue a buffer to the ImgU output for capture. */ Buffer *buffer = request->findBuffer(stream); @@ -558,7 +628,10 @@ int PipelineHandlerIPU3::registerCameras() for (unsigned int id = 0; id < 4 && numCameras < 2; ++id) { std::unique_ptr data = utils::make_unique(this); - std::set streams{ &data->stream_ }; + std::set streams = { + &data->outStream_, + &data->vfStream_, + }; CIO2Device *cio2 = &data->cio2_; ret = cio2->init(cio2MediaDev_.get(), id); @@ -566,11 +639,16 @@ int PipelineHandlerIPU3::registerCameras() continue; /** - * \todo Dynamically assign ImgU devices; as of now, limit - * support to two cameras only, and assign imgu0 to the first - * one and imgu1 to the second. + * \todo Dynamically assign ImgU and output devices to each + * stream and camera; as of now, limit support to two cameras + * only, and assign imgu0 to the first one and imgu1 to the + * second. */ data->imgu_ = numCameras ? &imgu1_ : &imgu0_; + data->outStream_.device_ = &data->imgu_->output_; + data->outStream_.name_ = "output"; + data->vfStream_.device_ = &data->imgu_->viewfinder_; + data->vfStream_.name_ = "viewfinder"; /* * Connect video devices' 'bufferReady' signals to their @@ -721,12 +799,12 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index) /** * \brief Configure the ImgU unit input - * \param[in] config The requested stream configuration + * \param[in] size The ImgU input frame size * \param[in] inputFormat The format to be applied to ImgU input * * \return 0 on success or a negative error code otherwise */ -int ImgUDevice::configureInput(const StreamConfiguration &config, +int ImgUDevice::configureInput(const Size &size, V4L2DeviceFormat *inputFormat) { /* Configure the ImgU input video device with the requested sizes. */ @@ -764,8 +842,8 @@ int ImgUDevice::configureInput(const StreamConfiguration &config, << rect.toString(); V4L2SubdeviceFormat imguFormat = {}; - imguFormat.width = config.width; - imguFormat.height = config.height; + imguFormat.width = size.width; + imguFormat.height = size.height; imguFormat.mbus_code = MEDIA_BUS_FMT_FIXED; ret = imgu_->setFormat(PAD_INPUT, &imguFormat); @@ -1080,12 +1158,12 @@ int CIO2Device::init(const MediaDevice *media, unsigned int index) /** * \brief Configure the CIO2 unit - * \param[in] config The requested configuration + * \param[in] size The requested CIO2 output frame size * \param[out] outputFormat The CIO2 unit output image format * * \return 0 on success or a negative error code otherwise */ -int CIO2Device::configure(const StreamConfiguration &config, +int CIO2Device::configure(const Size &size, V4L2DeviceFormat *outputFormat) { V4L2SubdeviceFormat sensorFormat; @@ -1099,7 +1177,7 @@ int CIO2Device::configure(const StreamConfiguration &config, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10 }, - Size(config.width, config.height)); + size); ret = sensor_->setFormat(&sensorFormat); if (ret) return ret; From patchwork Thu Apr 18 16:46:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1067 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4F18E60DC0 for ; Thu, 18 Apr 2019 18:45:53 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id D732D1C0005; Thu, 18 Apr 2019 16:45:52 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:34 +0200 Message-Id: <20190418164638.400-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 2/6] libcamera: ipu3: Use roles in stream configuration X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:53 -0000 Use and inspect the stream roles provided by the application to streamConfiguration() to assign streams to their intended roles and return a default configuration associated with them. Support a limited number of usages, as the viewfinder stream can optionally be used for capturing still images, but the main output stream cannot be used as viewfinder or for video recording purposes. Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 99 +++++++++++++++++++--------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index b9eb872fd5b2..8c2504499f33 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -221,38 +221,77 @@ CameraConfiguration PipelineHandlerIPU3::streamConfiguration(Camera *camera, const std::vector &usages) { - CameraConfiguration configs; IPU3CameraData *data = cameraData(camera); - StreamConfiguration config = {}; + CameraConfiguration cameraConfig; + std::set streams = { + &data->outStream_, + &data->vfStream_, + }; - /* - * FIXME: Soraka: the maximum resolution reported by both sensors - * (2592x1944 for ov5670 and 4224x3136 for ov13858) are returned as - * default configurations but they're not correctly processed by the - * ImgU. Resolutions up tp 2560x1920 have been validated. - * - * \todo Clarify ImgU alignement requirements. - */ - config.width = 2560; - config.height = 1920; - config.pixelFormat = V4L2_PIX_FMT_NV12; - config.bufferCount = IPU3_BUFFER_COUNT; - - configs[&data->outStream_] = config; - LOG(IPU3, Debug) - << "Stream '" << data->outStream_.name_ << "' set to " - << config.width << "x" << config.height << "-0x" - << std::hex << std::setfill('0') << std::setw(8) - << config.pixelFormat; - - configs[&data->vfStream_] = config; - LOG(IPU3, Debug) - << "Stream '" << data->vfStream_.name_ << "' set to " - << config.width << "x" << config.height << "-0x" - << std::hex << std::setfill('0') << std::setw(8) - << config.pixelFormat; - - return configs; + for (const StreamUsage &usage : usages) { + std::vector::iterator found; + StreamUsage::Role role = usage.role(); + StreamConfiguration streamConfig = {}; + IPU3Stream *stream = nullptr; + + if (role == StreamUsage::Role::StillCapture) { + /* + * We can use the viewfinder stream in case the + * 'StillCapture' usage is required multiple times. + */ + if (streams.find(&data->outStream_) != streams.end()) + stream = &data->outStream_; + else if (streams.find(&data->vfStream_) != streams.end()) + stream = &data->vfStream_; + else + goto error; + + /* + * FIXME: Soraka: the maximum resolution reported by + * both sensors (2592x1944 for ov5670 and 4224x3136 for + * ov13858) are returned as default configurations but + * they're not correctly processed by the ImgU. + * Resolutions up tp 2560x1920 have been validated. + * + * \todo Clarify ImgU alignment requirements. + */ + streamConfig.width = 2560; + streamConfig.height = 1920; + } else if (role == StreamUsage::Role::Viewfinder || + role == StreamUsage::Role::VideoRecording) { + /* + * We can't use the 'output' stream for viewfinder or + * video capture usages. + */ + if (streams.find(&data->vfStream_) == streams.end()) + goto error; + + stream = &data->vfStream_; + + streamConfig.width = usage.size().width; + streamConfig.height = usage.size().height; + } + + streams.erase(stream); + + streamConfig.pixelFormat = V4L2_PIX_FMT_NV12; + streamConfig.bufferCount = IPU3_BUFFER_COUNT; + + cameraConfig[stream] = streamConfig; + + LOG(IPU3, Debug) + << "Stream '" << stream->name_ << "' format set to " + << streamConfig.width << "x" << streamConfig.height + << "-0x" << std::hex << std::setfill('0') + << std::setw(8) << streamConfig.pixelFormat; + } + + return cameraConfig; + +error: + LOG(IPU3, Error) << "Requested stream roles not supported"; + + return CameraConfiguration{}; } int PipelineHandlerIPU3::configureStreams(Camera *camera, From patchwork Thu Apr 18 16:46:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1068 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 587D060DC9 for ; Thu, 18 Apr 2019 18:45:54 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id B2E601C000B; Thu, 18 Apr 2019 16:45:53 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:35 +0200 Message-Id: <20190418164638.400-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 3/6] libcamera: ipu3: Add multiple stream memory management X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:55 -0000 Perform allocation and setup of memory sharing between the CIO2 output and the ImgU input and allocate memory for each active stream. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 64 +++++++++++++++++++++------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 8c2504499f33..d14ba47e1c2c 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -92,6 +92,7 @@ public: BufferPool vfPool_; BufferPool statPool_; + BufferPool outPool_; }; class CIO2Device @@ -408,11 +409,20 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera, return 0; } +/** + * \todo Clarify if 'viewfinder' and 'stat' nodes have to be set up and + * started even if not in use. As of now, if not properly configured and + * enabled, the ImgU processing pipeline stalls. + * + * In order to be able to start the 'viewfinder' and 'stat' nodes, we need + * memory to be reserved. + */ int PipelineHandlerIPU3::allocateBuffers(Camera *camera, const std::set &streams) { IPU3CameraData *data = cameraData(camera); - Stream *stream = *streams.begin(); + IPU3Stream *outStream = &data->outStream_; + IPU3Stream *vfStream = &data->vfStream_; CIO2Device *cio2 = &data->cio2_; ImgUDevice *imgu = data->imgu_; unsigned int bufferCount; @@ -427,28 +437,49 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera, if (ret) goto error; - /* Export ImgU output buffers to the stream's pool. */ - ret = imgu->exportBuffers(&imgu->output_, &stream->bufferPool()); - if (ret) - goto error; - /* - * Reserve memory in viewfinder and stat output devices. Use the - * same number of buffers as the ones requested for the output - * stream. + * Use for the stat's internal pool the same number of buffer as + * for the input pool. + * \todo To be revised when we'll actually use the stat node. */ - bufferCount = stream->bufferPool().count(); - - imgu->viewfinder_.pool->createBuffers(bufferCount); - ret = imgu->exportBuffers(&imgu->viewfinder_, imgu->viewfinder_.pool); - if (ret) - goto error; - + bufferCount = pool->count(); imgu->stat_.pool->createBuffers(bufferCount); ret = imgu->exportBuffers(&imgu->stat_, imgu->stat_.pool); if (ret) goto error; + /* Allocate buffers for each active stream. */ + for (Stream *s : streams) { + IPU3Stream *stream = static_cast(s); + ImgUDevice::ImgUOutput *dev = stream->device_; + + ret = imgu->exportBuffers(dev, &stream->bufferPool()); + if (ret) + goto error; + } + + /* + * Allocate buffers also on non-active outputs; use the same number + * of buffers as the active ones. + */ + if (!outStream->cfg_) { + bufferCount = vfStream->bufferPool().count(); + outStream->device_->pool->createBuffers(bufferCount); + ret = imgu->exportBuffers(outStream->device_, + outStream->device_->pool); + if (ret) + goto error; + } + + if (!vfStream->cfg_) { + bufferCount = outStream->bufferPool().count(); + vfStream->device_->pool->createBuffers(bufferCount); + ret = imgu->exportBuffers(vfStream->device_, + vfStream->device_->pool); + if (ret) + goto error; + } + return 0; error: @@ -813,6 +844,7 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index) output_.pad = PAD_OUTPUT; output_.name = "output"; + output_.pool = &outPool_; viewfinder_.dev = V4L2Device::fromEntityName(media, name_ + " viewfinder"); From patchwork Thu Apr 18 16:46:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1069 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2A07560DB4 for ; Thu, 18 Apr 2019 18:45:55 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 803631C000D; Thu, 18 Apr 2019 16:45:54 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:36 +0200 Message-Id: <20190418164638.400-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 4/6] libcamera: ipu3: Queue requests for multiple streams X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:55 -0000 Add support for queueing requests for multiple streams in the IPU3 pipeline handler class. The output video node should be queued with buffers even if not part of the requested streams. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/ipu3.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index d14ba47e1c2c..8353272642bd 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -545,25 +545,20 @@ void PipelineHandlerIPU3::stop(Camera *camera) int PipelineHandlerIPU3::queueRequest(Camera *camera, Request *request) { - IPU3CameraData *data = cameraData(camera); - V4L2Device *output = data->imgu_->output_.dev; - IPU3Stream *stream = &data->outStream_; + int ret = 0; - /* Queue a buffer to the ImgU output for capture. */ - Buffer *buffer = request->findBuffer(stream); - if (!buffer) { - LOG(IPU3, Error) - << "Attempt to queue request with invalid stream"; - return -ENOENT; - } + for (auto it : request->buffers()) { + IPU3Stream *stream = static_cast(it.first); + Buffer *buffer = it.second; - int ret = output->queueBuffer(buffer); - if (ret < 0) - return ret; + int status = stream->device_->dev->queueBuffer(buffer); + if (status < 0) + ret = status; + } PipelineHandler::queueRequest(camera, request); - return 0; + return ret; } bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) From patchwork Thu Apr 18 16:46:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1070 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BD59B60DB4 for ; Thu, 18 Apr 2019 18:45:55 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 4FA4B1C0009; Thu, 18 Apr 2019 16:45:55 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:37 +0200 Message-Id: <20190418164638.400-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 5/6] libcamera: ipu3: Connect viewfinder's BufferReady signal X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:55 -0000 The viewfinder and main output require identical logic for buffer and request completion. Connect the viewfinder bufferReady signal to the slot and handle requests for both main output and viewfinder there. Update the slot logic to ignore internal buffers that are not part of the request, and to complete the request only when the last buffer completes. Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 32 +++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 8353272642bd..647b4f4f365f 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -729,6 +729,8 @@ int PipelineHandlerIPU3::registerCameras() &IPU3CameraData::imguInputBufferReady); data->imgu_->output_.dev->bufferReady.connect(data.get(), &IPU3CameraData::imguOutputBufferReady); + data->imgu_->viewfinder_.dev->bufferReady.connect(data.get(), + &IPU3CameraData::imguOutputBufferReady); /* Create and register the Camera instance. */ std::string cameraName = cio2->sensor_->entity()->name() + " " @@ -774,10 +776,34 @@ void PipelineHandlerIPU3::IPU3CameraData::imguInputBufferReady(Buffer *buffer) */ void PipelineHandlerIPU3::IPU3CameraData::imguOutputBufferReady(Buffer *buffer) { - Request *request = queuedRequests_.front(); + Request *request = buffer->request(); + if (!request) + /* Completed buffers not part of a request are ignored. */ + return; + + if (!pipe_->completeBuffer(camera_, request, buffer)) + /* Request not completed yet, return here. */ + return; + + /* + * Complete requests in queuing order: if some other request is + * pending, post-pone completion. + */ + Request *front = queuedRequests_.front(); + if (front != request) + return; - pipe_->completeBuffer(camera_, request, buffer); - pipe_->completeRequest(camera_, request); + /* + * Complete the current request, and all the other pending ones, + * in queuing order. + */ + while (1) { + if (front->hasPendingBuffers()) + break; + + pipe_->completeRequest(camera_, front); + front = queuedRequests_.front(); + } } /** From patchwork Thu Apr 18 16:46:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1071 Return-Path: Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5A24060DD3 for ; Thu, 18 Apr 2019 18:45:56 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id E02471C0009; Thu, 18 Apr 2019 16:45:55 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 18 Apr 2019 18:46:38 +0200 Message-Id: <20190418164638.400-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190418164638.400-1-jacopo@jmondi.org> References: <20190418164638.400-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 6/6] [HACK] still capture every 10 frames X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Apr 2019 16:45:57 -0000 Not for inclusion, just to demonstrate how an application could track its streams to their assigned usages. Signed-off-by: Jacopo Mondi --- src/cam/main.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/cam/main.cpp b/src/cam/main.cpp index 46aba728393c..fce694bf26d5 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -28,6 +28,11 @@ std::map streamInfo; EventLoop *loop; BufferWriter *writer; +unsigned int streamCount = 0; +unsigned int outBuf = 0; +std::map streamMap; +CameraConfiguration config; + enum { OptCamera = 'c', OptCapture = 'C', @@ -129,6 +134,11 @@ static int prepareCameraConfig(CameraConfiguration *config) return -EINVAL; } + /* Associate each stream returned by the Camera with its role. */ + unsigned int i = 0; + for (auto *stream : *config) + streamMap[stream] = roles[i++].role(); + /* Apply configuration explicitly requested. */ CameraConfiguration::iterator it = config->begin(); for (auto const &value : streamOptions) { @@ -158,6 +168,7 @@ static int prepareCameraConfig(CameraConfiguration *config) static void requestComplete(Request *request, const std::map &buffers) { + std::map map; static uint64_t now, last = 0; double fps = 0.0; @@ -196,13 +207,37 @@ static void requestComplete(Request *request, const std::map return; } - request->setBuffers(buffers); + /* Viewfinder in every request. */ + for (auto &b : buffers) { + Stream *s = b.first; + if (streamMap[s] != StreamUsage::Role::Viewfinder) + continue; + + map[s] = b.second; + } + + /* Still capture every ten requests. */ + streamCount++; + if (!(streamCount % 10)) { + streamCount = 0; + for (Stream *stream : config) { + if (streamMap[stream] != StreamUsage::Role::StillCapture) + continue; + + map[stream] = + &stream->bufferPool().buffers()[outBuf]; + outBuf = (outBuf + 1) % + stream->bufferPool().count(); + break; + } + } + + request->setBuffers(map); camera->queueRequest(request); } static int capture() { - CameraConfiguration config; int ret; ret = prepareCameraConfig(&config); @@ -246,8 +281,13 @@ static int capture() } std::map map; - for (Stream *stream : config) + for (Stream *stream : config) { + if (streamMap[stream] != StreamUsage::Role::Viewfinder) + continue; + + /* Only require the viewfinder to begin with. */ map[stream] = &stream->bufferPool().buffers()[i]; + } ret = request->setBuffers(map); if (ret < 0) {