From patchwork Fri Apr 19 13:25:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1087 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 937F260B2E for ; Fri, 19 Apr 2019 15:24:44 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id DE15220003; Fri, 19 Apr 2019 13:24:43 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:24 +0200 Message-Id: <20190419132531.17856-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 1/8] libcamera: stream: Document protected members 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: Fri, 19 Apr 2019 13:24:44 -0000 Since commit: 4e1dc9004fca ("libcamera: stream: Make Stream inheritable") the private members of the Stream class have been turned into protected, to allows subclasses to access them. As Doxygen generates documentation for protected members (but not for private memebers), add documentation to the stream class for the 'bufferMap_' and 'configuration_' members. Fixes: 4e1dc9004fca ("libcamera: stream: Make Stream inheritable") Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/stream.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index 71dd461db33b..aeb479c57b37 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -211,4 +211,22 @@ Stream::Stream() * \return The active configuration of the stream */ +/** + * \var Stream::bufferPool_ + * \brief The pool of buffers associated with the stream + * + * The stream buffer pool is populated by the Camera class after a succesfull + * stream configuration. + */ + +/** + * \var Stream::configuration_ + * \brief The stream configuration + * + * The configuration for the stream is set by any successful call to + * Camera::configureStreams() that includes the stream, and remains valid until + * the next call to Camera::configureStreams() regardless of if it includes the + * stream. + */ + } /* namespace libcamera */ From patchwork Fri Apr 19 13:25:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1088 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5F6BE60DC7 for ; Fri, 19 Apr 2019 15:24:45 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id BB6B72000E; Fri, 19 Apr 2019 13:24:44 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:25 +0200 Message-Id: <20190419132531.17856-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 2/8] libcamera: camera: Reset basefield to decimal 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: Fri, 19 Apr 2019 13:24:46 -0000 When logging the camera configuration, the same ostringstream instance is used to assemble a message describing configuration of all the configured streams. After the first stream configuration has been assembled, the use of std::hex modifies the ostringstream basefield, causing all successive integers values inserted in the stream to be expressed as hexadecimals. Fix that by resetting the stream's basefield to decimal, before assembling a stream configuration description. Before this patch: INFO Camera camera.cpp:615 (0) 640x480-0x3231564e (1) 140xa0-0x3231564e After this patch: INFO Camera camera.cpp:616 (0) 640x480-0x3231564e (1) 320x160-0x3231564e Fixes: 9c9078133216 ("libcamera: camera: Log requested configuration in configureStreams()") Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index d7a39ca6af12..655996f26224 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -597,7 +597,7 @@ int Camera::configureStreams(const CameraConfiguration &config) return -EINVAL; const StreamConfiguration &cfg = config[stream]; - msg << " (" << index << ") " << cfg.toString(); + msg << std::dec << " (" << index << ") " << cfg.toString(); index++; } From patchwork Fri Apr 19 13:25:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1089 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0C92C60DCC for ; Fri, 19 Apr 2019 15:24:46 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 85B7220003; Fri, 19 Apr 2019 13:24:45 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:26 +0200 Message-Id: <20190419132531.17856-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 3/8] 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: Fri, 19 Apr 2019 13:24:47 -0000 Sub-class the Stream class with an IPU3-specific implementation and create each IPU3 camera with two streams: 'output' and 'viewfinder' which represent the video streams 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 Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/ipu3.cpp | 179 +++++++++++++++++++-------- 1 file changed, 129 insertions(+), 50 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 7443224d4f45..46384d88dddd 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() + : active_(false), device_(nullptr) + { + } + + bool active_; + std::string name_; + ImgUDevice::ImgUOutput *device_; +}; + 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,12 +233,20 @@ 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_ << "' format set to " + << config.toString(); - LOG(IPU3, Debug) << "Stream format set to " << config->toString(); + configs[&data->vfStream_] = config; + LOG(IPU3, Debug) + << "Stream '" << data->vfStream_.name_ << "' format set to " + << config.toString(); return configs; } @@ -233,30 +255,52 @@ 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; - } + outStream->active_ = false; + vfStream->active_ = false; + 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->active_ = true; } /* @@ -272,24 +316,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_, config[stream]); + if (ret) + return ret; + } + + /* + * 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->active_) { + ret = imgu->configureOutput(outStream->device_, + config[vfStream]); + if (ret) + return ret; + } + + if (!vfStream->active_) { + ret = imgu->configureOutput(vfStream->device_, + config[outStream]); + if (ret) + return ret; + } - ret = imgu->configureOutput(&imgu->stat_, cfg); + /* + * 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; @@ -404,7 +475,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); @@ -555,7 +626,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); @@ -563,11 +637,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 @@ -718,11 +797,11 @@ 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. */ @@ -760,8 +839,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); @@ -1074,11 +1153,11 @@ 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; @@ -1092,7 +1171,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 Fri Apr 19 13:25:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1090 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9B47260B2E for ; Fri, 19 Apr 2019 15:24:46 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 315F020003; Fri, 19 Apr 2019 13:24:46 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:27 +0200 Message-Id: <20190419132531.17856-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 4/8] 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: Fri, 19 Apr 2019 13:24:47 -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, with the viewfinder stream able to capture both continuous video streams and still images, and the main output stream supporting still images only. This is an artificial limitation until we figure out the exact capabilities of the hardware. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/libcamera/pipeline/ipu3/ipu3.cpp | 124 +++++++++++++++++++++------ 1 file changed, 98 insertions(+), 26 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 46384d88dddd..0130a83973ca 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -5,6 +5,7 @@ * ipu3.cpp - Pipeline handler for Intel IPU3 */ +#include #include #include #include @@ -221,34 +222,105 @@ 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_ << "' format set to " - << config.toString(); - - configs[&data->vfStream_] = config; - LOG(IPU3, Debug) - << "Stream '" << data->vfStream_.name_ << "' format set to " - << config.toString(); - - return configs; + for (const StreamUsage &usage : usages) { + StreamConfiguration streamConfig = {}; + StreamUsage::Role role = usage.role(); + IPU3Stream *stream = nullptr; + + switch (role) { + case StreamUsage::Role::StillCapture: + /* + * Don't allow viewfinder or video capture on the + * 'output' stream. This is an artificial limitation + * until we figure out the capabilities of the + * hardware. + */ + if (streams.find(&data->outStream_) != streams.end()) { + stream = &data->outStream_; + } else if (streams.find(&data->vfStream_) != streams.end()) { + stream = &data->vfStream_; + } else { + LOG(IPU3, Error) + << "No stream available for requested role " + << role; + break; + } + + /* + * 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; + + break; + case StreamUsage::Role::Viewfinder: + case StreamUsage::Role::VideoRecording: { + /* + * We can't use the 'output' stream for viewfinder or + * video capture usages. + * + * \todo This is an artificial limitation until we + * figure out the exact capabilities of the hardware. + */ + if (streams.find(&data->vfStream_) == streams.end()) { + LOG(IPU3, Error) + << "No stream available for requested role " + << role; + break; + } + + stream = &data->vfStream_; + + /* + * Align the requested viewfinder size to the + * maximum available sensor resolution and to the + * IPU3 alignment constraints. + */ + const Size &res = data->cio2_.sensor_->resolution(); + unsigned int width = std::min(usage.size().width, + res.width); + unsigned int height = std::min(usage.size().height, + res.height); + streamConfig.width = width & ~7; + streamConfig.height = height & ~3; + + break; + } + default: + LOG(IPU3, Error) + << "Requested stream role not supported: " << role; + break; + } + + if (!stream) + return cameraConfig; + + 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.toString(); + } + + return cameraConfig; } int PipelineHandlerIPU3::configureStreams(Camera *camera, From patchwork Fri Apr 19 13:25:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1091 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 802B460B2E for ; Fri, 19 Apr 2019 15:24:47 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id C5A0C20003; Fri, 19 Apr 2019 13:24:46 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:28 +0200 Message-Id: <20190419132531.17856-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 5/8] 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: Fri, 19 Apr 2019 13:24:47 -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 0130a83973ca..3f1f1bc8644f 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -93,6 +93,7 @@ public: BufferPool vfPool_; BufferPool statPool_; + BufferPool outPool_; }; class CIO2Device @@ -439,11 +440,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; @@ -458,28 +468,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->active_) { + bufferCount = vfStream->bufferPool().count(); + outStream->device_->pool->createBuffers(bufferCount); + ret = imgu->exportBuffers(outStream->device_, + outStream->device_->pool); + if (ret) + goto error; + } + + if (!vfStream->active_) { + bufferCount = outStream->bufferPool().count(); + vfStream->device_->pool->createBuffers(bufferCount); + ret = imgu->exportBuffers(vfStream->device_, + vfStream->device_->pool); + if (ret) + goto error; + } + return 0; error: @@ -844,6 +875,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 Fri Apr 19 13:25:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1092 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E51060B2E for ; Fri, 19 Apr 2019 15:24:48 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id A939A20007; Fri, 19 Apr 2019 13:24:47 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:29 +0200 Message-Id: <20190419132531.17856-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 6/8] 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: Fri, 19 Apr 2019 13:24:48 -0000 Add support for queueing requests for multiple streams in the IPU3 pipeline handler class. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- 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 3f1f1bc8644f..f71227c6c408 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -576,25 +576,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 error = 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 ret = stream->device_->dev->queueBuffer(buffer); + if (ret < 0) + error = ret; + } PipelineHandler::queueRequest(camera, request); - return 0; + return error; } bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) From patchwork Fri Apr 19 13:25:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1093 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4059660DCB for ; Fri, 19 Apr 2019 15:24:49 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 94AEC20004; Fri, 19 Apr 2019 13:24:48 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:30 +0200 Message-Id: <20190419132531.17856-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 7/8] 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: Fri, 19 Apr 2019 13:24:51 -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 complete the request only when the last buffer has completed, and make sure to complete requests in the same order they have been queued to the pipeline handler. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- src/libcamera/pipeline/ipu3/ipu3.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index f71227c6c408..43c28c30cfc7 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -760,6 +760,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() + " " @@ -805,10 +807,20 @@ void PipelineHandlerIPU3::IPU3CameraData::imguInputBufferReady(Buffer *buffer) */ void PipelineHandlerIPU3::IPU3CameraData::imguOutputBufferReady(Buffer *buffer) { - Request *request = queuedRequests_.front(); + Request *request = buffer->request(); + + if (!pipe_->completeBuffer(camera_, request, buffer)) + /* Request not completed yet, return here. */ + return; - pipe_->completeBuffer(camera_, request, buffer); - pipe_->completeRequest(camera_, request); + /* Complete the pending requests in queuing order. */ + while (1) { + request = queuedRequests_.front(); + if (request->hasPendingBuffers()) + break; + + pipe_->completeRequest(camera_, request); + } } /** From patchwork Fri Apr 19 13:25:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1094 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F289E60DBF for ; Fri, 19 Apr 2019 15:24:49 +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 relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 6D71020004; Fri, 19 Apr 2019 13:24:49 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 19 Apr 2019 15:25:31 +0200 Message-Id: <20190419132531.17856-9-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190419132531.17856-1-jacopo@jmondi.org> References: <20190419132531.17856-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 8/8] [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: Fri, 19 Apr 2019 13:24:51 -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) {