[libcamera-devel,8/8] Request StillCapture stream as default in Android adapter
diff mbox series

Message ID 20220512103258.324339-9-chenghaoyang@google.com
State Superseded
Headers show
Series
  • Use two imgus in ipu3 pipeline handler
Related show

Commit Message

Harvey Yang May 12, 2022, 10:32 a.m. UTC
If the pipeline handler accepts, the Android adapter requests to handle
the StillCapture stream separately, instead of being mapped to an
existing video/preview stream.

Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
---
 src/android/camera_device.cpp | 214 ++++++++++++++++++----------------
 src/android/camera_device.h   |  21 ++++
 2 files changed, 132 insertions(+), 103 deletions(-)

Patch
diff mbox series

diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 00d48471..b8403cc2 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -36,23 +36,6 @@  LOG_DECLARE_CATEGORY(HAL)
 
 namespace {
 
-/*
- * \struct Camera3StreamConfig
- * \brief Data to store StreamConfiguration associated with camera3_stream(s)
- * \var streams List of the pairs of a stream requested by Android HAL client
- * and CameraStream::Type associated with the stream
- * \var config StreamConfiguration for streams
- */
-struct Camera3StreamConfig {
-	struct Camera3Stream {
-		camera3_stream_t *stream;
-		CameraStream::Type type;
-	};
-
-	std::vector<Camera3Stream> streams;
-	StreamConfiguration config;
-};
-
 /*
  * Reorder the configurations so that libcamera::Camera can accept them as much
  * as possible. The sort rule is as follows.
@@ -536,16 +519,6 @@  int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
 		return -EINVAL;
 #endif
 
-	/*
-	 * Generate an empty configuration, and construct a StreamConfiguration
-	 * for each camera3_stream to add to it.
-	 */
-	std::unique_ptr<CameraConfiguration> config = camera_->generateConfiguration();
-	if (!config) {
-		LOG(HAL, Error) << "Failed to generate camera configuration";
-		return -EINVAL;
-	}
-
 	/*
 	 * Clear and remove any existing configuration from previous calls, and
 	 * ensure the required entries are available without further
@@ -614,93 +587,79 @@  int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
 		stream->usage |= GRALLOC_USAGE_HW_CAMERA_WRITE;
 	}
 
+	std::unique_ptr<CameraConfiguration> config;
+
 	/* Now handle the MJPEG streams, adding a new stream if required. */
 	if (jpegStream) {
-		CameraStream::Type type;
-		int index = -1;
-
-		/* Search for a compatible stream in the non-JPEG ones. */
-		for (size_t i = 0; i < streamConfigs.size(); ++i) {
-			Camera3StreamConfig &streamConfig = streamConfigs[i];
-			const auto &cfg = streamConfig.config;
-
-			/*
-			 * \todo The PixelFormat must also be compatible with
-			 * the encoder.
-			 */
-			if (cfg.size.width != jpegStream->width ||
-			    cfg.size.height != jpegStream->height)
-				continue;
-
-			LOG(HAL, Info)
-				<< "Android JPEG stream mapped to libcamera stream " << i;
-
-			type = CameraStream::Type::Mapped;
-			index = i;
-
-			/*
-			 * The source stream will be read by software to
-			 * produce the JPEG stream.
-			 */
-			camera3_stream_t *stream = streamConfig.streams[0].stream;
-			stream->usage |= GRALLOC_USAGE_SW_READ_OFTEN;
-			break;
-		}
+		/* Check if the JPEG stream can be produced by software. */
+		jpegStream->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
 
 		/*
-		 * Without a compatible match for JPEG encoding we must
-		 * introduce a new stream to satisfy the request requirements.
+		 * \todo The pixelFormat should be a 'best-fit' choice
+		 * and may require a validation cycle. This is not yet
+		 * handled, and should be considered as part of any
+		 * stream configuration reworks.
 		 */
-		if (index < 0) {
-			/*
-			 * \todo The pixelFormat should be a 'best-fit' choice
-			 * and may require a validation cycle. This is not yet
-			 * handled, and should be considered as part of any
-			 * stream configuration reworks.
-			 */
-			Camera3StreamConfig streamConfig;
-			streamConfig.config.size.width = jpegStream->width;
-			streamConfig.config.size.height = jpegStream->height;
-			streamConfig.config.pixelFormat = formats::NV12;
-			streamConfigs.push_back(std::move(streamConfig));
-
-			LOG(HAL, Info) << "Adding " << streamConfig.config.toString()
-				       << " for MJPEG support";
-
-			type = CameraStream::Type::Internal;
-			index = streamConfigs.size() - 1;
-		}
-
-		/* The JPEG stream will be produced by software. */
-		jpegStream->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
-
-		streamConfigs[index].streams.push_back({ jpegStream, type });
-	}
+		Camera3StreamConfig sConfig;
+		sConfig.config.streamRole = libcamera::StreamRole::StillCapture;
+		sConfig.config.size.width = jpegStream->width;
+		sConfig.config.size.height = jpegStream->height;
+		sConfig.config.pixelFormat = formats::NV12;
+
+		std::vector<Camera3StreamConfig> streamConfigsCopy(streamConfigs);
+		streamConfigsCopy.push_back(std::move(sConfig));
+
+		LOG(HAL, Info) << "Adding " << sConfig.config.toString()
+			       << " for MJPEG support";
+
+		streamConfigsCopy.back().streams.push_back({ jpegStream, CameraStream::Type::Internal });
+
+		config = tryValidation(streamConfigsCopy, jpegStream);
+		if (config) {
+			streamConfigs = streamConfigsCopy;
+		} else {
+			bool foundCompatibleStream = false;
+			/* Search for a compatible stream in the non-JPEG ones. */
+			for (size_t i = 0; i < streamConfigs.size(); ++i) {
+				Camera3StreamConfig &streamConfig = streamConfigs[i];
+				const auto &cfg = streamConfig.config;
+
+				/*
+				 * \todo The PixelFormat must also be compatible with
+				 * the encoder.
+				 */
+				if (cfg.size.width != jpegStream->width ||
+				    cfg.size.height != jpegStream->height)
+					continue;
+
+				LOG(HAL, Info)
+					<< "Android JPEG stream mapped to libcamera stream " << i;
+				foundCompatibleStream = true;
+
+				/*
+				 * The source stream will be read by software to
+				 * produce the JPEG stream.
+				 */
+				camera3_stream_t *stream = streamConfig.streams[0].stream;
+				stream->usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+				streamConfigs[i].streams.push_back({ jpegStream, CameraStream::Type::Mapped });
+				break;
+			}
 
-	sortCamera3StreamConfigs(streamConfigs, jpegStream);
-	for (const auto &streamConfig : streamConfigs) {
-		config->addConfiguration(streamConfig.config);
+			if (!foundCompatibleStream) {
+				LOG(HAL, Error)
+					<< "No compatibleStream found for jpeg";
 
-		for (auto &stream : streamConfig.streams) {
-			streams_.emplace_back(this, config.get(), stream.type,
-					      stream.stream, config->size() - 1);
-			stream.stream->priv = static_cast<void *>(&streams_.back());
+				return -EINVAL;
+			}
 		}
 	}
 
-	switch (config->validate()) {
-	case CameraConfiguration::Valid:
-		break;
-	case CameraConfiguration::Adjusted:
-		LOG(HAL, Info) << "Camera configuration adjusted";
-
-		for (const StreamConfiguration &cfg : *config)
-			LOG(HAL, Info) << " - " << cfg.toString();
+	if (!config) {
+		config = tryValidation(streamConfigs, jpegStream);
+		if (!config)
+			return -EINVAL;
 
-		return -EINVAL;
-	case CameraConfiguration::Invalid:
-		LOG(HAL, Info) << "Camera configuration invalid";
-		return -EINVAL;
 	}
 
 	/*
@@ -1527,3 +1486,52 @@  CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons
 
 	return resultMetadata;
 }
+
+std::unique_ptr<CameraConfiguration> CameraDevice::tryValidation(
+	std::vector<Camera3StreamConfig> &streamConfigs,
+	const camera3_stream_t *jpegStream)
+{
+	/*
+	 * Generate an empty configuration, and construct a StreamConfiguration
+	 * for each camera3_stream to add to it.
+	 */
+	std::unique_ptr<CameraConfiguration> config = camera_->generateConfiguration();
+	if (!config) {
+		LOG(HAL, Error) << "Failed to generate camera configuration";
+		return nullptr;
+	}
+
+	sortCamera3StreamConfigs(streamConfigs, jpegStream);
+	for (const auto &streamConfig : streamConfigs) {
+		config->addConfiguration(streamConfig.config);
+
+		for (auto &stream : streamConfig.streams) {
+			streams_.emplace_back(this, config.get(), stream.type,
+					      stream.stream, config->size() - 1);
+			stream.stream->priv = static_cast<void *>(&streams_.back());
+		}
+	}
+
+	switch (config->validate()) {
+	case CameraConfiguration::Valid:
+		break;
+	case CameraConfiguration::Adjusted:
+		LOG(HAL, Info) << "Camera configuration adjusted";
+
+		for (const StreamConfiguration &cfg : *config)
+			LOG(HAL, Info) << " - " << cfg.toString();
+
+		config.reset();
+		break;
+	case CameraConfiguration::Invalid:
+		LOG(HAL, Info) << "Camera configuration invalid";
+
+		config.reset();
+		break;
+	}
+
+	if (!config)
+		streams_.clear();
+
+	return config;
+}
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index 64050416..8540e3f5 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -34,6 +34,23 @@ 
 class Camera3RequestDescriptor;
 struct CameraConfigData;
 
+/*
+ * \struct Camera3StreamConfig
+ * \brief Data to store StreamConfiguration associated with camera3_stream(s)
+ * \var streams List of the pairs of a stream requested by Android HAL client
+ * and CameraStream::Type associated with the stream
+ * \var config StreamConfiguration for streams
+ */
+struct Camera3StreamConfig {
+	struct Camera3Stream {
+		camera3_stream_t *stream;
+		CameraStream::Type type;
+	};
+
+	std::vector<Camera3Stream> streams;
+	libcamera::StreamConfiguration config;
+};
+
 class CameraDevice : protected libcamera::Loggable
 {
 public:
@@ -101,6 +118,10 @@  private:
 	std::unique_ptr<CameraMetadata> getResultMetadata(
 		const Camera3RequestDescriptor &descriptor) const;
 
+	std::unique_ptr<libcamera::CameraConfiguration> tryValidation(
+		std::vector<Camera3StreamConfig> &streamConfigs,
+		const camera3_stream_t *jpegStream);
+
 	unsigned int id_;
 	camera3_device_t camera3Device_;