summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2019-02-05 17:36:04 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2019-02-06 07:41:51 +0200
commitbd38112b7795b79c7056cfe6e9d713e80ee74586 (patch)
treeb657b03308ba685bf6982993a30bf97f9965b1d9
parent98edf29e012cce6a3c0a428e3d78490780c1a824 (diff)
libcamera: camera: Extend the interface to support capture
In order to support capture, the camera needs methods to allocate and free buffers, to start and stop the capture and to queue requests. Define those interfaces in the Camera class and implement them to call the corresponding pipeline handler methods. Once a camera is started the pipeline handler of the camera will begin processing requests queued to the camera by the application until it gets stopped. Once a request is created it can be queued to the camera and the application will be notified asynchronously once the request is completed and be able to process all the buffers involved in the request. At this point the request objects don't support controls. This will be extended in the future. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--include/libcamera/camera.h10
-rw-r--r--src/libcamera/camera.cpp141
-rw-r--r--src/libcamera/request.cpp13
3 files changed, 159 insertions, 5 deletions
diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 1c0ee07c..bf70255a 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -18,6 +18,7 @@ namespace libcamera {
class Buffer;
class PipelineHandler;
+class Request;
class Stream;
class StreamConfiguration;
@@ -44,6 +45,15 @@ public:
streamConfiguration(std::vector<Stream *> &streams);
int configureStreams(std::map<Stream *, StreamConfiguration> &config);
+ int allocateBuffers();
+ void freeBuffers();
+
+ Request *createRequest();
+ int queueRequest(Request *request);
+
+ int start();
+ int stop();
+
private:
Camera(PipelineHandler *pipe, const std::string &name);
~Camera();
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 3f7b805b..1acb399c 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -6,6 +6,7 @@
*/
#include <libcamera/camera.h>
+#include <libcamera/request.h>
#include <libcamera/stream.h>
#include "log.h"
@@ -264,11 +265,151 @@ int Camera::configureStreams(std::map<Stream *, StreamConfiguration> &config)
stream->configuration_ = cfg;
activeStreams_.push_back(stream);
+
+ /*
+ * Allocate buffer objects in the pool.
+ * Memory will be allocated and assigned later.
+ */
+ stream->bufferPool().createBuffers(cfg.bufferCount);
+ }
+
+ return 0;
+}
+
+/**
+ * \brief Allocate buffers for all configured streams
+ * \return 0 on success or a negative error code otherwise
+ */
+int Camera::allocateBuffers()
+{
+ int ret;
+
+ ret = exclusiveAccess();
+ if (ret)
+ return ret;
+
+ if (activeStreams_.empty()) {
+ LOG(Camera, Error)
+ << "Can't allocate buffers without streams";
+ return -EINVAL;
+ }
+
+ for (Stream *stream : activeStreams_) {
+ ret = pipe_->allocateBuffers(this, stream);
+ if (ret) {
+ LOG(Camera, Error) << "Failed to allocate buffers";
+ freeBuffers();
+ return ret;
+ }
}
return 0;
}
+/**
+ * \brief Release all buffers from allocated pools in each stream
+ */
+void Camera::freeBuffers()
+{
+ for (Stream *stream : activeStreams_) {
+ if (!stream->bufferPool().count())
+ continue;
+
+ pipe_->freeBuffers(this, stream);
+ stream->bufferPool().destroyBuffers();
+ }
+}
+
+/**
+ * \brief Create a request object for the camera
+ *
+ * This method creates an empty request for the application to fill with
+ * buffers and paramaters, and queue for capture.
+ *
+ * The ownership of the returned request is passed to the caller, which is
+ * responsible for either queueing the request or deleting it.
+ *
+ * \return A pointer to the newly created request, or nullptr on error
+ */
+Request *Camera::createRequest()
+{
+ if (exclusiveAccess())
+ return nullptr;
+
+ return new Request(this);
+}
+
+/**
+ * \brief Queue a request to the camera
+ * \param[in] request The request to queue to the camera
+ *
+ * This method queues a \a request allocated with createRequest() to the camera
+ * for capture. Once the request has been queued, the camera will notify its
+ * completion through the \ref requestCompleted signal.
+ *
+ * Ownership of the request is transferred to the camera. It will be deleted
+ * automatically after it completes.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+int Camera::queueRequest(Request *request)
+{
+ int ret;
+
+ ret = exclusiveAccess();
+ if (ret)
+ return ret;
+
+ ret = request->prepare();
+ if (ret) {
+ LOG(Camera, Error) << "Failed to prepare request";
+ return ret;
+ }
+
+ return pipe_->queueRequest(this, request);
+}
+
+/**
+ * \brief Start capture from camera
+ *
+ * Start the camera capture session. Once the camera is started the application
+ * can queue requests to the camera to process and return to the application
+ * until the capture session is terminated with \a stop().
+ *
+ * \return 0 on success or a negative error code on error
+ */
+int Camera::start()
+{
+ int ret = exclusiveAccess();
+ if (ret)
+ return ret;
+
+ LOG(Camera, Debug) << "Starting capture";
+
+ return pipe_->start(this);
+}
+
+/**
+ * \brief Stop capture from camera
+ *
+ * This method stops capturing and processing requests immediately. All pending
+ * requests are cancelled and complete synchronously in an error state.
+ *
+ * \return 0 on success or a negative error code on error
+ */
+int Camera::stop()
+{
+ int ret = exclusiveAccess();
+ if (ret)
+ return ret;
+
+ LOG(Camera, Debug) << "Stopping capture";
+
+ pipe_->stop(this);
+
+ return 0;
+}
+
int Camera::exclusiveAccess()
{
if (disconnected_)
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index 922682a3..d76db24d 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -104,7 +104,8 @@ int Request::prepare()
* data.
*
* The request completes when all the buffers it contains are ready to be
- * presented to the application.
+ * presented to the application. It then emits the Camera::requestCompleted
+ * signal and is automatically deleted.
*/
void Request::bufferCompleted(Buffer *buffer)
{
@@ -113,10 +114,12 @@ void Request::bufferCompleted(Buffer *buffer)
int ret = pending_.erase(buffer);
ASSERT(ret == 1);
- if (pending_.empty()) {
- std::map<Stream *, Buffer *> buffers(std::move(bufferMap_));
- camera_->requestCompleted.emit(this, buffers);
- }
+ if (!pending_.empty())
+ return;
+
+ std::map<Stream *, Buffer *> buffers(std::move(bufferMap_));
+ camera_->requestCompleted.emit(this, buffers);
+ delete this;
}
} /* namespace libcamera */