{"id":534,"url":"https://patchwork.libcamera.org/api/patches/534/?format=json","web_url":"https://patchwork.libcamera.org/patch/534/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20190206060818.13907-20-laurent.pinchart@ideasonboard.com>","date":"2019-02-06T06:08:10","name":"[libcamera-devel,19/27] libcamera: camera: Extend the interface to support capture","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"242a0bdffa973a788eef4e49db8ae4a45afc55ce","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/534/mbox/","series":[{"id":170,"url":"https://patchwork.libcamera.org/api/series/170/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=170","date":"2019-02-06T06:07:51","name":"Capture frames throught requests","version":1,"mbox":"https://patchwork.libcamera.org/series/170/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/534/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/534/checks/","tags":{},"headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 240986103A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  6 Feb 2019 07:08:28 +0100 (CET)","from pendragon.ideasonboard.com (d51A4137F.access.telenet.be\n\t[81.164.19.127])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BECE041\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  6 Feb 2019 07:08:27 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1549433307;\n\tbh=/HHwNwFor12mfYEAbRtgdJcRixGtPiMri6J+aFj1QpY=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=QErC2OF+ARZp7G/gcboKiWhf9rBMF5JFFF/2KRGhQhW/9vCucb8TtNZXGA6snXHQE\n\tabwVnORJPU0HyRzO59tvsYD0BStcRRDSJgA5Ub0cA9rQ8aNcWm3eXTuiR1/E9K6ihX\n\tYLldUNdWx/6+p3K9iCaQpTXwmrBBg+rUn6wMT/Hk=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Wed,  6 Feb 2019 08:08:10 +0200","Message-Id":"<20190206060818.13907-20-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.19.2","In-Reply-To":"<20190206060818.13907-1-laurent.pinchart@ideasonboard.com>","References":"<20190206060818.13907-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 19/27] libcamera: camera: Extend the\n\tinterface to support capture","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Wed, 06 Feb 2019 06:08:29 -0000"},"content":"From: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\nIn order to support capture, the camera needs methods to allocate and\nfree buffers, to start and stop the capture and to queue requests.\nDefine those interfaces in the Camera class and implement them to call\nthe corresponding pipeline handler methods.\n\nOnce a camera is started the pipeline handler of the camera will begin\nprocessing requests queued to the camera by the application until it\ngets stopped.\n\nOnce a request is created it can be queued to the camera and the\napplication will be notified asynchronously once the request is\ncompleted and be able to process all the buffers involved in the\nrequest.\n\nAt this point the request objects don't support controls. This will be\nextended in the future.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n include/libcamera/camera.h |  10 +++\n src/libcamera/camera.cpp   | 141 +++++++++++++++++++++++++++++++++++++\n src/libcamera/request.cpp  |  13 ++--\n 3 files changed, 159 insertions(+), 5 deletions(-)","diff":"diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h\nindex 1c0ee07c2a22..bf70255a6a5e 100644\n--- a/include/libcamera/camera.h\n+++ b/include/libcamera/camera.h\n@@ -18,6 +18,7 @@ namespace libcamera {\n \n class Buffer;\n class PipelineHandler;\n+class Request;\n class Stream;\n class StreamConfiguration;\n \n@@ -44,6 +45,15 @@ public:\n \tstreamConfiguration(std::vector<Stream *> &streams);\n \tint configureStreams(std::map<Stream *, StreamConfiguration> &config);\n \n+\tint allocateBuffers();\n+\tvoid freeBuffers();\n+\n+\tRequest *createRequest();\n+\tint queueRequest(Request *request);\n+\n+\tint start();\n+\tint stop();\n+\n private:\n \tCamera(PipelineHandler *pipe, const std::string &name);\n \t~Camera();\ndiff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\nindex 3f7b805b09a2..1acb399c80a6 100644\n--- a/src/libcamera/camera.cpp\n+++ b/src/libcamera/camera.cpp\n@@ -6,6 +6,7 @@\n  */\n \n #include <libcamera/camera.h>\n+#include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n #include \"log.h\"\n@@ -264,11 +265,151 @@ int Camera::configureStreams(std::map<Stream *, StreamConfiguration> &config)\n \n \t\tstream->configuration_ = cfg;\n \t\tactiveStreams_.push_back(stream);\n+\n+\t\t/*\n+\t\t * Allocate buffer objects in the pool.\n+\t\t * Memory will be allocated and assigned later.\n+\t\t */\n+\t\tstream->bufferPool().createBuffers(cfg.bufferCount);\n \t}\n \n \treturn 0;\n }\n \n+/**\n+ * \\brief Allocate buffers for all configured streams\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int Camera::allocateBuffers()\n+{\n+\tint ret;\n+\n+\tret = exclusiveAccess();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (activeStreams_.empty()) {\n+\t\tLOG(Camera, Error)\n+\t\t\t<< \"Can't allocate buffers without streams\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (Stream *stream : activeStreams_) {\n+\t\tret = pipe_->allocateBuffers(this, stream);\n+\t\tif (ret) {\n+\t\t\tLOG(Camera, Error) << \"Failed to allocate buffers\";\n+\t\t\tfreeBuffers();\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * \\brief Release all buffers from allocated pools in each stream\n+ */\n+void Camera::freeBuffers()\n+{\n+\tfor (Stream *stream : activeStreams_) {\n+\t\tif (!stream->bufferPool().count())\n+\t\t\tcontinue;\n+\n+\t\tpipe_->freeBuffers(this, stream);\n+\t\tstream->bufferPool().destroyBuffers();\n+\t}\n+}\n+\n+/**\n+ * \\brief Create a request object for the camera\n+ *\n+ * This method creates an empty request for the application to fill with\n+ * buffers and paramaters, and queue for capture.\n+ *\n+ * The ownership of the returned request is passed to the caller, which is\n+ * responsible for either queueing the request or deleting it.\n+ *\n+ * \\return A pointer to the newly created request, or nullptr on error\n+ */\n+Request *Camera::createRequest()\n+{\n+\tif (exclusiveAccess())\n+\t\treturn nullptr;\n+\n+\treturn new Request(this);\n+}\n+\n+/**\n+ * \\brief Queue a request to the camera\n+ * \\param[in] request The request to queue to the camera\n+ *\n+ * This method queues a \\a request allocated with createRequest() to the camera\n+ * for capture. Once the request has been queued, the camera will notify its\n+ * completion through the \\ref requestCompleted signal.\n+ *\n+ * Ownership of the request is transferred to the camera. It will be deleted\n+ * automatically after it completes.\n+ *\n+ * \\return 0 on success or a negative error code on error\n+ */\n+int Camera::queueRequest(Request *request)\n+{\n+\tint ret;\n+\n+\tret = exclusiveAccess();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = request->prepare();\n+\tif (ret) {\n+\t\tLOG(Camera, Error) << \"Failed to prepare request\";\n+\t\treturn ret;\n+\t}\n+\n+\treturn pipe_->queueRequest(this, request);\n+}\n+\n+/**\n+ * \\brief Start capture from camera\n+ *\n+ * Start the camera capture session. Once the camera is started the application\n+ * can queue requests to the camera to process and return to the application\n+ * until the capture session is terminated with \\a stop().\n+ *\n+ * \\return 0 on success or a negative error code on error\n+ */\n+int Camera::start()\n+{\n+\tint ret = exclusiveAccess();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(Camera, Debug) << \"Starting capture\";\n+\n+\treturn pipe_->start(this);\n+}\n+\n+/**\n+ * \\brief Stop capture from camera\n+ *\n+ * This method stops capturing and processing requests immediately. All pending\n+ * requests are cancelled and complete synchronously in an error state.\n+ *\n+ * \\return 0 on success or a negative error code on error\n+ */\n+int Camera::stop()\n+{\n+\tint ret = exclusiveAccess();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(Camera, Debug) << \"Stopping capture\";\n+\n+\tpipe_->stop(this);\n+\n+\treturn 0;\n+}\n+\n int Camera::exclusiveAccess()\n {\n \tif (disconnected_)\ndiff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\nindex 922682a32188..d76db24de0e2 100644\n--- a/src/libcamera/request.cpp\n+++ b/src/libcamera/request.cpp\n@@ -104,7 +104,8 @@ int Request::prepare()\n  * data.\n  *\n  * The request completes when all the buffers it contains are ready to be\n- * presented to the application.\n+ * presented to the application. It then emits the Camera::requestCompleted\n+ * signal and is automatically deleted.\n  */\n void Request::bufferCompleted(Buffer *buffer)\n {\n@@ -113,10 +114,12 @@ void Request::bufferCompleted(Buffer *buffer)\n \tint ret = pending_.erase(buffer);\n \tASSERT(ret == 1);\n \n-\tif (pending_.empty()) {\n-\t\tstd::map<Stream *, Buffer *> buffers(std::move(bufferMap_));\n-\t\tcamera_->requestCompleted.emit(this, buffers);\n-\t}\n+\tif (!pending_.empty())\n+\t\treturn;\n+\n+\tstd::map<Stream *, Buffer *> buffers(std::move(bufferMap_));\n+\tcamera_->requestCompleted.emit(this, buffers);\n+\tdelete this;\n }\n \n } /* namespace libcamera */\n","prefixes":["libcamera-devel","19/27"]}