diff options
-rw-r--r-- | include/libcamera/camera.h | 10 | ||||
-rw-r--r-- | src/libcamera/camera.cpp | 141 | ||||
-rw-r--r-- | src/libcamera/request.cpp | 13 |
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 */ |