[libcamera-devel] [RFC PATCH] android: camera_device: Reorder configurations given by a HAL client

Hirokazu Honda hiroh at chromium.org
Wed Oct 28 11:15:42 CET 2020


Definitely please ignore printStreamList(). I forgot removing that in
uploading the patch.

On Wed, Oct 28, 2020 at 7:04 PM Hirokazu Honda <hiroh at chromium.org> wrote:
>
> 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