[libcamera-devel,v4,20/31] libcamera: ipu3: Add multiple stream memory management

Message ID 20190320163055.22056-21-jacopo@jmondi.org
State Accepted
Headers show
Series
  • libcamera: ipu3: Add ImgU support + multiple streams
Related show

Commit Message

Jacopo Mondi March 20, 2019, 4:30 p.m. UTC
Add support for allocating and freeing memory for multiple streams.
---
 src/libcamera/pipeline/ipu3/ipu3.cpp | 140 ++++++++++++++++++---------
 1 file changed, 96 insertions(+), 44 deletions(-)

Patch

diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 4ed8c1fec1e3..0507fc380e68 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -70,6 +70,7 @@  public:
 
 	BufferPool vfPool;
 	BufferPool statPool;
+	BufferPool outputPool;
 };
 
 struct CIO2Device {
@@ -458,42 +459,70 @@  int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream)
 	V4L2Device *input = data->imgu->input;
 	V4L2Device *cio2 = data->cio2.output;
 	V4L2Device *stat = data->imgu->stat;
+	ImgUDevice *imgu = data->imgu;
 	int ret;
 
-	/* Share buffers between CIO2 output and ImgU input. */
-	data->cio2.pool.createBuffers(IPU3_CIO2_BUFFER_COUNT);
-	ret = cio2->exportBuffers(&data->cio2.pool);
-	if (ret) {
-		LOG(IPU3, Error) << "Failed to reserve CIO2 memory";
-		return ret;
-	}
+	if (data->cio2.pool.count() == 0) {
+		/* Share buffers between CIO2 output and ImgU input. */
+		data->cio2.pool.createBuffers(IPU3_CIO2_BUFFER_COUNT);
+		ret = cio2->exportBuffers(&data->cio2.pool);
+		if (ret) {
+			LOG(IPU3, Error) << "Failed to reserve CIO2 memory";
+			return ret;
+		}
 
-	ret = input->importBuffers(&data->cio2.pool);
-	if (ret) {
-		LOG(IPU3, Error) << "Failed to import ImgU memory";
-		return ret;
-	}
+		ret = input->importBuffers(&data->cio2.pool);
+		if (ret) {
+			LOG(IPU3, Error) << "Failed to import ImgU memory";
+			return ret;
+		}
 
-	/* Prepare the buffer pools for viewfinder and stat. */
-	data->imgu->vfPool.createBuffers(IPU3_IMGU_BUFFER_COUNT);
-	ret = viewfinder->exportBuffers(&data->imgu->vfPool);
-	if (ret) {
-		LOG(IPU3, Error) << "Failed to reserve ImgU viewfinder memory";
-		return ret;
+		imgu->statPool.createBuffers(IPU3_IMGU_BUFFER_COUNT);
+		ret = stat->exportBuffers(&imgu->statPool);
+		if (ret) {
+			LOG(IPU3, Error) << "Failed to reserve ImgU stat memory";
+			return ret;
+		}
 	}
 
-	data->imgu->statPool.createBuffers(IPU3_IMGU_BUFFER_COUNT);
-	ret = stat->exportBuffers(&data->imgu->statPool);
-	if (ret) {
-		LOG(IPU3, Error) << "Failed to reserve ImgU stat memory";
-		return ret;
-	}
+	if (isOutput(data, stream)) {
+		/* Export ImgU output buffers to the stream's pool. */
+		ret = output->exportBuffers(&stream->bufferPool());
+		if (ret) {
+			LOG(IPU3, Error)
+				<< "Failed to reserve ImgU output memory";
+			return ret;
+		}
 
-	/* Export ImgU output buffers to the stream's pool. */
-	ret = output->exportBuffers(&stream->bufferPool());
-	if (ret) {
-		LOG(IPU3, Error) << "Failed to reserve ImgU output memory";
-		return ret;
+		if (!isViewfinderActive(data)) {
+			/* Internally allocate buffers for viewfinder. */
+			imgu->vfPool.createBuffers(IPU3_IMGU_BUFFER_COUNT);
+			ret = viewfinder->exportBuffers(&imgu->vfPool);
+			if (ret) {
+				LOG(IPU3, Error)
+					<< "Failed to reserve ImgU viewfinder memory";
+				return ret;
+			}
+		}
+	} else if (isViewfinder(data, stream)) {
+		/* Export ImgU viewfinder buffers to the stream's pool. */
+		ret = viewfinder->exportBuffers(&stream->bufferPool());
+		if (ret) {
+			LOG(IPU3, Error)
+				<< "Failed to reserve ImgU viewfinder memory";
+			return ret;
+		}
+
+		if (!isOutputActive(data)) {
+			/* Internally allocate buffers for output. */
+			imgu->outputPool.createBuffers(IPU3_IMGU_BUFFER_COUNT);
+			ret = output->exportBuffers(&imgu->outputPool);
+			if (ret) {
+				LOG(IPU3, Error)
+					<< "Failed to reserve ImgU output memory";
+				return ret;
+			}
+		}
 	}
 
 	return 0;
@@ -509,25 +538,48 @@  int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream)
 	V4L2Device *stat = data->imgu->stat;
 	int ret;
 
-	ret = output->releaseBuffers();
-	if (ret)
-		LOG(IPU3, Error) << "Failed to release ImgU output memory";
+	if (data->cio2.pool.count()) {
+		ret = input->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error) << "Failed to release ImgU input memory";
 
-	ret = stat->releaseBuffers();
-	if (ret)
-		LOG(IPU3, Error) << "Failed to release ImgU stat memory";
+		ret = cio2->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error) << "Failed to release CIO2 memory";
 
-	ret = viewfinder->releaseBuffers();
-	if (ret)
-		LOG(IPU3, Error) << "Failed to release ImgU viewfinder memory";
+		ret = stat->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error) << "Failed to release ImgU stat memory";
 
-	ret = input->releaseBuffers();
-	if (ret)
-		LOG(IPU3, Error) << "Failed to release ImgU input memory";
+	}
 
-	ret = cio2->releaseBuffers();
-	if (ret)
-		LOG(IPU3, Error) << "Failed to release CIO2 memory";
+	if (isOutput(data, stream)) {
+		ret = output->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error)
+				<< "Failed to release ImgU output memory";
+
+		if (isViewfinderActive(data))
+			return 0;
+
+		ret = viewfinder->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error)
+				<< "Failed to release ImgU viewfinder memory";
+	} else if (isViewfinder(data, stream)) {
+		ret = viewfinder->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error)
+				<< "Failed to release ImgU viewfinder memory";
+
+		if (isOutputActive(data))
+			return 0;
+
+		ret = output->releaseBuffers();
+		if (ret)
+			LOG(IPU3, Error)
+				<< "Failed to release ImgU output memory";
+	}
 
 	return 0;
 }