[libcamera-devel,6/9] libcamera: pipeline: vivid: Buffer handling and stream control

Message ID 20200713132451.2944673-7-kieran.bingham@ideasonboard.com
State Awaiting Upstream
Headers show
Series
  • Introduce a new PipelineHandler
Related show

Commit Message

Kieran Bingham July 13, 2020, 1:24 p.m. UTC
We can now add buffer management, and connect up our bufferReady signal
to a callback.

Note that we provide the ability to export buffers from our capture
device (data->video_) using the exportBuffers() functionality from the
V4L2VideoDevice which allows a FrameBufferAllocater to obtain buffers
from this device.

When buffers are obtained through the exportFrameBuffers API, they are
orphaned and left unassociated with the device, and must be reimported
at start() time anyway. This allows the same interface to be used
whether internal buffers, or external buffers are used for the stream.

When a buffer completes, we call the buffer completion handler on the
pipeline handler, and because we have only a single stream, we can also
immediately complete the request.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 src/libcamera/pipeline/vivid/vivid.cpp | 35 ++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

Comments

Kieran Bingham July 14, 2020, 2:48 p.m. UTC | #1
Hi Kieran,

On 13/07/2020 14:24, Kieran Bingham wrote:
> We can now add buffer management, and connect up our bufferReady signal
> to a callback.
> 
> Note that we provide the ability to export buffers from our capture
> device (data->video_) using the exportBuffers() functionality from the
> V4L2VideoDevice which allows a FrameBufferAllocater to obtain buffers
> from this device.
> 
> When buffers are obtained through the exportFrameBuffers API, they are
> orphaned and left unassociated with the device, and must be reimported
> at start() time anyway. This allows the same interface to be used
> whether internal buffers, or external buffers are used for the stream.
> 
> When a buffer completes, we call the buffer completion handler on the
> pipeline handler, and because we have only a single stream, we can also
> immediately complete the request.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>  src/libcamera/pipeline/vivid/vivid.cpp | 35 ++++++++++++++++++++++++--
>  1 file changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp
> index dbc19424e75a..1a945a744055 100644
> --- a/src/libcamera/pipeline/vivid/vivid.cpp
> +++ b/src/libcamera/pipeline/vivid/vivid.cpp
> @@ -32,6 +32,7 @@ public:
>  	}
>  
>  	int init();
> +	void bufferReady(FrameBuffer *buffer);
>  
>  	MediaDevice *media_;
>  	V4L2VideoDevice *video_;
> @@ -175,16 +176,36 @@ int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)
>  int PipelineHandlerVivid::exportFrameBuffers(Camera *camera, Stream *stream,
>  					     std::vector<std::unique_ptr<FrameBuffer>> *buffers)
>  {
> -	return -1;
> +	VividCameraData *data = cameraData(camera);
> +	unsigned int count = stream->configuration().bufferCount;
> +
> +	return data->video_->exportBuffers(count, buffers);
>  }
>  
>  int PipelineHandlerVivid::start(Camera *camera)
>  {
> -	return -1;
> +	VividCameraData *data = cameraData(camera);
> +	unsigned int count = data->stream_.configuration().bufferCount;
> +
> +	int ret = data->video_->importBuffers(count);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = data->video_->streamOn();
> +	if (ret < 0) {
> +		data->ipa_->stop();

As we don't have an IPA for this pipeline handler, we shouldn't stop the
IPA here ;-)

> +		data->video_->releaseBuffers();
> +		return ret;
> +	}
> +
> +	return 0;
>  }
>  
>  void PipelineHandlerVivid::stop(Camera *camera)
>  {
> +	VividCameraData *data = cameraData(camera);
> +	data->video_->streamOff();
> +	data->video_->releaseBuffers();
>  }
>  
>  int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)
> @@ -221,9 +242,19 @@ int VividCameraData::init()
>  	if (video_->open())
>  		return -ENODEV;
>  
> +	video_->bufferReady.connect(this, &VividCameraData::bufferReady);
> +
>  	return 0;
>  }
>  
> +void VividCameraData::bufferReady(FrameBuffer *buffer)
> +{
> +	Request *request = buffer->request();
> +
> +	pipe_->completeBuffer(camera_, request, buffer);
> +	pipe_->completeRequest(camera_, request);
> +}
> +
>  REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);
>  
>  } /* namespace libcamera */
>

Patch

diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp
index dbc19424e75a..1a945a744055 100644
--- a/src/libcamera/pipeline/vivid/vivid.cpp
+++ b/src/libcamera/pipeline/vivid/vivid.cpp
@@ -32,6 +32,7 @@  public:
 	}
 
 	int init();
+	void bufferReady(FrameBuffer *buffer);
 
 	MediaDevice *media_;
 	V4L2VideoDevice *video_;
@@ -175,16 +176,36 @@  int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)
 int PipelineHandlerVivid::exportFrameBuffers(Camera *camera, Stream *stream,
 					     std::vector<std::unique_ptr<FrameBuffer>> *buffers)
 {
-	return -1;
+	VividCameraData *data = cameraData(camera);
+	unsigned int count = stream->configuration().bufferCount;
+
+	return data->video_->exportBuffers(count, buffers);
 }
 
 int PipelineHandlerVivid::start(Camera *camera)
 {
-	return -1;
+	VividCameraData *data = cameraData(camera);
+	unsigned int count = data->stream_.configuration().bufferCount;
+
+	int ret = data->video_->importBuffers(count);
+	if (ret < 0)
+		return ret;
+
+	ret = data->video_->streamOn();
+	if (ret < 0) {
+		data->ipa_->stop();
+		data->video_->releaseBuffers();
+		return ret;
+	}
+
+	return 0;
 }
 
 void PipelineHandlerVivid::stop(Camera *camera)
 {
+	VividCameraData *data = cameraData(camera);
+	data->video_->streamOff();
+	data->video_->releaseBuffers();
 }
 
 int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)
@@ -221,9 +242,19 @@  int VividCameraData::init()
 	if (video_->open())
 		return -ENODEV;
 
+	video_->bufferReady.connect(this, &VividCameraData::bufferReady);
+
 	return 0;
 }
 
+void VividCameraData::bufferReady(FrameBuffer *buffer)
+{
+	Request *request = buffer->request();
+
+	pipe_->completeBuffer(camera_, request, buffer);
+	pipe_->completeRequest(camera_, request);
+}
+
 REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);
 
 } /* namespace libcamera */