@@ -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,102 @@ 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;
- }
+ /* This stream will be produced by hardware. */
+ jpegStream->usage |= GRALLOC_USAGE_HW_CAMERA_WRITE;
/*
- * 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) {
+ 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 {
+ /* The JPEG stream will be produced by software. */
+ jpegStream->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+ 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;
+ index = i;
+ type = CameraStream::Type::Mapped;
+
+ /*
+ * 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;
+ }
+
/*
- * \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.
+ * Without a compatible match for JPEG encoding we must
+ * introduce a new stream to satisfy the request requirements.
*/
- 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 });
- }
-
- sortCamera3StreamConfigs(streamConfigs, jpegStream);
- for (const auto &streamConfig : streamConfigs) {
- config->addConfiguration(streamConfig.config);
+ 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;
+ }
- 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());
+ streamConfigs[index].streams.push_back({ jpegStream, type });
}
}
- 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 +1509,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;
+}
@@ -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_;
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 or creating a new video stream. Signed-off-by: Harvey Yang <chenghaoyang@chromium.org> --- src/android/camera_device.cpp | 235 +++++++++++++++++++--------------- src/android/camera_device.h | 21 +++ 2 files changed, 154 insertions(+), 102 deletions(-)