[libcamera-devel] [RFC PATCH] android: camera_device: Reorder configurations given by a HAL client
Hirokazu Honda
hiroh at chromium.org
Wed Oct 28 11:04:55 CET 2020
I would like to call for comments about adding this ad-hoc reordering
before CameraDevice configures pipeline handles.
The purpose is that a pipeline handler can produce streams from which
given configurations can be achieved.
Best Regards,
-Hiro
On Wed, Oct 28, 2020 at 7:01 PM Hirokazu Honda <hiroh at chromium.org> wrote:
>
> 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