[libcamera-devel] [PATCH v4 24/32] libcamera: pipeline: Add FrameBuffer handlers
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Sun Jan 12 14:42:22 CET 2020
Hi Niklas,
Thank you for the patch.
On Sun, Jan 12, 2020 at 02:02:04AM +0100, Niklas Söderlund wrote:
> Extend the pipeline handlers to support the FrameBuffer API with three
> new methods to handle allocation, importing and freeing of buffers. The
> new methods will replace allocateBuffers() and freeBuffers().
>
> The FrameBuffer API will use the methods on a stream level and either
> allocate or import buffers for each active stream controlled from the
> Camera class and an upcoming FrameBufferAllocator helper. With this new
> API the implementation in pipeline handlers can be made simpler as all
> streams don't need to be handled in allocateBuffers().
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> * Changes since v3
> - Add documentation paragraph for PipelineHandler::exportFrameBuffers()
> which was lost from review of v2.
I don't see the paragraph being added below...
> * Changes since v2
> - In the subject line, s/pipelines/pipeline/
> - Rename allocateFrameBuffers() to exportFrameBuffers()
> - Rewrite of documentation, thanks Laurent!
> - Remove count argument from exportFrameBuffers() and
> importFrameBuffers() and instead get the buffer count from the stream
> configuration.
> ---
> src/libcamera/include/pipeline_handler.h | 5 ++
> src/libcamera/pipeline/ipu3/ipu3.cpp | 32 +++++++++++
> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 23 ++++++++
> src/libcamera/pipeline/uvcvideo.cpp | 29 ++++++++++
> src/libcamera/pipeline/vimc.cpp | 29 ++++++++++
> src/libcamera/pipeline_handler.cpp | 67 ++++++++++++++++++++++++
> 6 files changed, 185 insertions(+)
>
> diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
> index 067baef56278b577..560be3bad8d59b20 100644
> --- a/src/libcamera/include/pipeline_handler.h
> +++ b/src/libcamera/include/pipeline_handler.h
> @@ -70,6 +70,11 @@ public:
> const StreamRoles &roles) = 0;
> virtual int configure(Camera *camera, CameraConfiguration *config) = 0;
>
> + virtual int exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;
> + virtual int importFrameBuffers(Camera *camera, Stream *stream) = 0;
> + virtual void freeFrameBuffers(Camera *camera, Stream *stream) = 0;
> +
> virtual int allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams) = 0;
> virtual int freeBuffers(Camera *camera,
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index 7c4539d488bd2d26..b73f0f0725ee2613 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -210,6 +210,11 @@ public:
> const StreamRoles &roles) override;
> int configure(Camera *camera, CameraConfiguration *config) override;
>
> + int exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
> + int importFrameBuffers(Camera *camera, Stream *stream) override;
> + void freeFrameBuffers(Camera *camera, Stream *stream) override;
> +
> int allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams) override;
> int freeBuffers(Camera *camera,
> @@ -616,6 +621,33 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
> return 0;
> }
>
> +int PipelineHandlerIPU3::exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers)
> +{
> + IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
> + V4L2VideoDevice *video = ipu3stream->device_->dev;
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return video->exportBuffers(count, buffers);
> +}
> +
> +int PipelineHandlerIPU3::importFrameBuffers(Camera *camera, Stream *stream)
> +{
> + IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
> + V4L2VideoDevice *video = ipu3stream->device_->dev;
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return video->importBuffers(count);
> +}
> +
> +void PipelineHandlerIPU3::freeFrameBuffers(Camera *camera, Stream *stream)
> +{
> + IPU3Stream *ipu3stream = static_cast<IPU3Stream *>(stream);
> + V4L2VideoDevice *video = ipu3stream->device_->dev;
> +
> + video->releaseBuffers();
> +}
> +
> /**
> * \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
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index dbc5df801f30e76b..ba8f93e8584c97a9 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -174,6 +174,11 @@ public:
> const StreamRoles &roles) override;
> int configure(Camera *camera, CameraConfiguration *config) override;
>
> + int exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
> + int importFrameBuffers(Camera *camera, Stream *stream) override;
> + void freeFrameBuffers(Camera *camera, Stream *stream) override;
> +
> int allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams) override;
> int freeBuffers(Camera *camera,
> @@ -665,6 +670,24 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
> return 0;
> }
>
> +int PipelineHandlerRkISP1::exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers)
> +{
> + unsigned int count = stream->configuration().bufferCount;
> + return video_->exportBuffers(count, buffers);
> +}
> +
> +int PipelineHandlerRkISP1::importFrameBuffers(Camera *camera, Stream *stream)
> +{
> + unsigned int count = stream->configuration().bufferCount;
> + return video_->importBuffers(count);
> +}
> +
> +void PipelineHandlerRkISP1::freeFrameBuffers(Camera *camera, Stream *stream)
> +{
> + video_->releaseBuffers();
> +}
> +
> int PipelineHandlerRkISP1::allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams)
> {
> diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
> index ce38445d2a48ca82..b72841edee572f99 100644
> --- a/src/libcamera/pipeline/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo.cpp
> @@ -65,6 +65,11 @@ public:
> const StreamRoles &roles) override;
> int configure(Camera *camera, CameraConfiguration *config) override;
>
> + int exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
> + int importFrameBuffers(Camera *camera, Stream *stream) override;
> + void freeFrameBuffers(Camera *camera, Stream *stream) override;
> +
> int allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams) override;
> int freeBuffers(Camera *camera,
> @@ -193,6 +198,30 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)
> return 0;
> }
>
> +int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers)
> +{
> + UVCCameraData *data = cameraData(camera);
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return data->video_->exportBuffers(count, buffers);
> +}
> +
> +int PipelineHandlerUVC::importFrameBuffers(Camera *camera, Stream *stream)
> +{
> + UVCCameraData *data = cameraData(camera);
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return data->video_->importBuffers(count);
> +}
> +
> +void PipelineHandlerUVC::freeFrameBuffers(Camera *camera, Stream *stream)
> +{
> + UVCCameraData *data = cameraData(camera);
> +
> + data->video_->releaseBuffers();
> +}
> +
> int PipelineHandlerUVC::allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams)
> {
> diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
> index 292900bcf8d1b359..3fb5cacde0dab5b6 100644
> --- a/src/libcamera/pipeline/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc.cpp
> @@ -82,6 +82,11 @@ public:
> const StreamRoles &roles) override;
> int configure(Camera *camera, CameraConfiguration *config) override;
>
> + int exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
> + int importFrameBuffers(Camera *camera, Stream *stream) override;
> + void freeFrameBuffers(Camera *camera, Stream *stream) override;
> +
> int allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams) override;
> int freeBuffers(Camera *camera,
> @@ -259,6 +264,30 @@ int PipelineHandlerVimc::configure(Camera *camera, CameraConfiguration *config)
> return 0;
> }
>
> +int PipelineHandlerVimc::exportFrameBuffers(Camera *camera, Stream *stream,
> + std::vector<std::unique_ptr<FrameBuffer>> *buffers)
> +{
> + VimcCameraData *data = cameraData(camera);
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return data->video_->exportBuffers(count, buffers);
> +}
> +
> +int PipelineHandlerVimc::importFrameBuffers(Camera *camera, Stream *stream)
> +{
> + VimcCameraData *data = cameraData(camera);
> + unsigned int count = stream->configuration().bufferCount;
> +
> + return data->video_->importBuffers(count);
> +}
> +
> +void PipelineHandlerVimc::freeFrameBuffers(Camera *camera, Stream *stream)
> +{
> + VimcCameraData *data = cameraData(camera);
> +
> + data->video_->releaseBuffers();
> +}
> +
> int PipelineHandlerVimc::allocateBuffers(Camera *camera,
> const std::set<Stream *> &streams)
> {
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 698dd52560797d7c..572f751b5217eb5f 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -289,6 +289,73 @@ const ControlInfoMap &PipelineHandler::controls(Camera *camera)
> * \return 0 on success or a negative error code otherwise
> */
>
> +/**
> + * \fn PipelineHandler::exportFrameBuffers()
> + * \brief Allocate buffers for \a stream
> + * \param[in] camera The camera
> + * \param[in] stream The stream to allocate buffers for
> + * \param[out] buffers Array of buffers successfully allocated
> + *
> + * This method allocates buffers for the \a stream from the devices associated
> + * with the stream in the corresponding pipeline handler. Those buffers shall be
> + * suitable to be added to a Request for the stream, and shall be mappable to
> + * the CPU through their associated dmabufs with mmap().
> + *
> + * exportFrameBuffers() shall also allocate all other resources required by
> + * the pipeline handler for the stream to prepare for starting the Camera. This
> + * responsibility is shared with importFrameBuffers(), and one and only one of
> + * those two methods shall be called for each stream until the buffers are
> + * freed. The pipeline handler shall support all combinations of
> + * exportFrameBuffers() and importFrameBuffers() for the streams contained in
> + * any camera configuration.
> + *
> + * The only intended caller is the FrameBufferAllocator helper.
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +
> +/**
> + * \fn PipelineHandler::importFrameBuffers()
> + * \brief Prepare \a stream to use external buffers
> + * \param[in] camera The camera
> + * \param[in] stream The stream to prepare for import
> + *
> + * This method prepares the pipeline handler to use buffers provided by the
> + * application for the \a stream.
> + *
> + * The method may only be called after the Camera has been configured and before
> + * it gets started, or after it gets stopped. It shall be called only for
> + * streams that are part of the active camera configuration, and at most once
> + * per stream until buffers for the stream are freed with freeFrameBuffers().
> + *
> + * importFrameBuffers() shall also allocate all other resources required by the
> + * pipeline handler for the stream to prepare for starting the Camera. This
> + * responsibility is shared with exportFrameBuffers(), and one and only one of
> + * those two methods shall be called for each stream until the buffers are
> + * freed. The pipeline handler shall support all combinations of
> + * exportFrameBuffers() and importFrameBuffers() for the streams contained in
> + * any camera configuration.
> + *
> + * The only intended caller is Camera::start().
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +
> +/**
> + * \fn PipelineHandler::freeFrameBuffers()
> + * \brief Free buffers allocated from the stream
> + * \param[in] camera The camera
> + * \param[in] stream The stream to free buffers for
> + *
> + * This method shall free all buffers and all other resources allocated for the
> + * \a stream by exportFrameBuffers() or importFrameBuffers(). It shall be
> + * called only after a successful call to either of these two methods, and only
> + * once per stream.
> + *
> + * The only intended callers are Camera::stop() and the FrameBufferAllocator
> + * helper.
> + */
> +
> /**
> * \fn PipelineHandler::allocateBuffers()
> * \brief Allocate buffers for a stream
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list