[libcamera-devel] [RFC PATCH] android: camera_device: Reorder configurations given by a HAL client
Hirokazu Honda
hiroh at chromium.org
Wed Oct 28 11:01:34 CET 2020
Reorder configurations given by a HAL client in configureStreams()
so that CameraDevice and pipeline handlers can accept them as much
as possible.
Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
src/android/camera_device.cpp | 108 +++++++++++++++++++++++++++++++++-
src/android/camera_device.h | 3 +-
2 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index ca60f51..eee7248 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -9,6 +9,7 @@
#include "camera_ops.h"
#include "post_processor.h"
+#include <string.h>
#include <sys/mman.h>
#include <tuple>
#include <vector>
@@ -132,6 +133,16 @@ const std::map<int, const Camera3Format> camera3FormatsMap = {
LOG_DECLARE_CATEGORY(HAL)
+void printStreamList(const camera3_stream_configuration_t& streamList) {
+ LOG(HAL, Error) << "num_streams=" << streamList.num_streams;
+ for (unsigned int i = 0; i < streamList.num_streams; i++) {
+ const auto* stream = streamList.streams[i];
+ LOG(HAL, Error) << i << ": width=" << stream->width
+ << ", height=" << stream->height
+ << ", format=" << stream->format;
+ }
+}
+
MappedCamera3Buffer::MappedCamera3Buffer(const buffer_handle_t camera3buffer,
int flags)
{
@@ -1188,7 +1199,7 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)
return requestTemplate->get();
}
-PixelFormat CameraDevice::toPixelFormat(int format)
+PixelFormat CameraDevice::toPixelFormat(int format) const
{
/* Translate Android format code to libcamera pixel format. */
auto it = formatsMap_.find(format);
@@ -1201,6 +1212,97 @@ PixelFormat CameraDevice::toPixelFormat(int format)
return it->second;
}
+int CameraDevice::sortStreamConfig(camera3_stream_configuration_t* streamList) const
+{
+ std::map<uint32_t, std::vector<const camera3_stream_t*>> streamMap;
+ for (unsigned int i = 0; i < streamList->num_streams; ++i) {
+ const camera3_stream_t* stream = streamList->streams[i];
+ PixelFormat format = toPixelFormat(stream->format);
+ if (!format.isValid())
+ return -EINVAL;
+ streamMap[format.fourcc()].push_back(stream);
+ }
+ std::vector<uint32_t> formats;
+ for (auto& s: streamMap) {
+ formats.push_back(s.first);
+ auto& streams = s.second;
+ /* Sorted by resolution. Smaller is put first. */
+ std::sort(streams.begin(), streams.end(),
+ [](const camera3_stream_t* streamA,
+ const camera3_stream_t* streamB) {
+ if (streamA->width != streamB->width)
+ return streamA->width < streamB->width;
+ return streamA->height < streamB->height;
+ });
+ }
+
+ if (streamMap.find(formats::MJPEG) != streamMap.end() &&
+ streamMap[formats::MJPEG].size() > 1) {
+ LOG(HAL, Error) << "Multiple JPEG streams are not supported";
+ return -EINVAL;
+ }
+
+ std::vector<const camera3_stream_t*> sortedStreams;
+ /*
+ * NV12 is the most prioritized format. Put the configuration with NV12
+ * and the largest resolution first.
+ */
+ auto nv12StreamsIt = streamMap.find(formats::NV12);
+ if (nv12StreamsIt != streamMap.end()) {
+ auto& nv12Streams = nv12StreamsIt->second;
+ const camera3_stream_t* nv12Stream = nv12Streams.back();
+ sortedStreams.push_back(nv12Stream);
+ nv12Streams.pop_back();
+ }
+
+ /*
+ * If JPEG is there, then put the JPEG configuration second and a
+ * configuration whose specified stream the JPEG is encoded from third
+ * if there is.
+ */
+ auto jpegStreamsIt = streamMap.find(formats::MJPEG);
+ if (jpegStreamsIt != streamMap.end()) {
+ auto& jpegStreams = jpegStreamsIt->second;
+ const camera3_stream_t* jpegStream = jpegStreams[0];
+ sortedStreams.push_back(jpegStream);
+ streamMap.erase(jpegStreamsIt);
+ if (nv12StreamsIt != streamMap.end()) {
+ auto& nv12Streams = nv12StreamsIt->second;
+ auto nv12StreamForJpegIt =
+ std::find_if(nv12Streams.begin(),
+ nv12Streams.end(),
+ [&jpegStream](const auto* nv12Stream) {
+ return nv12Stream->width == jpegStream->width && nv12Stream->height == jpegStream->height;
+ });
+ if (nv12StreamForJpegIt != nv12Streams.end()) {
+ sortedStreams.push_back(*nv12StreamForJpegIt);
+ nv12Streams.erase(nv12StreamForJpegIt);
+ }
+ }
+ }
+
+ /*
+ * Put configurations with different formats and larger resolutions
+ * earlier.
+ */
+ while (!streamMap.empty()) {
+ for (auto it = streamMap.begin(); it != streamMap.end();) {
+ auto& streams = it->second;
+ if (streams.empty()) {
+ it = streamMap.erase(it);
+ continue;
+ }
+ sortedStreams.push_back(streams.back());
+ streams.pop_back();
+ }
+ }
+
+ assert(sortedStreams.size() == streamList->num_streams);
+ memcpy(streamList->streams, sortedStreams.data(),
+ sizeof(camera3_stream_t*) * streamList->num_streams);
+ return 0;
+}
+
/*
* Inspect the stream_list to produce a list of StreamConfiguration to
* be use to configure the Camera.
@@ -1225,6 +1327,10 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
streams_.clear();
streams_.reserve(stream_list->num_streams);
+ printStreamList(*stream_list);
+ sortStreamConfig(stream_list);
+ printStreamList(*stream_list);
+
/* First handle all non-MJPEG streams. */
camera3_stream_t *jpegStream = nullptr;
for (unsigned int i = 0; i < stream_list->num_streams; ++i) {
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index fd08738..f8dc28b 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -104,7 +104,8 @@ private:
void notifyShutter(uint32_t frameNumber, uint64_t timestamp);
void notifyError(uint32_t frameNumber, camera3_stream_t *stream);
CameraMetadata *requestTemplatePreview();
- libcamera::PixelFormat toPixelFormat(int format);
+ libcamera::PixelFormat toPixelFormat(int format) const;
+ int sortStreamConfig(camera3_stream_configuration_t* streamList) const;
std::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,
int64_t timestamp);
--
2.29.0.rc2.309.g374f81d7ae-goog
More information about the libcamera-devel
mailing list