@@ -8,9 +8,11 @@
#include <cros-camera/cros_camera_hal.h>
#include "../camera_hal_manager.h"
+#include "../cros_mojo_token.h"
static void set_up([[maybe_unused]] cros::CameraMojoChannelManagerToken *token)
{
+ gCrosMojoToken = token;
}
static void tear_down()
new file mode 100644
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * cros_mojo_token.h - cros-specific mojo token
+ */
+
+#pragma once
+
+#include <cros-camera/cros_camera_hal.h>
+
+inline cros::CameraMojoChannelManagerToken *gCrosMojoToken = nullptr;
new file mode 100644
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * encoder_jea.cpp - JPEG encoding using CrOS JEA
+ */
+
+#include "encoder_jea.h"
+
+#include "libcamera/internal/mapped_framebuffer.h"
+
+#include <cros-camera/camera_mojo_channel_manager_token.h>
+
+#include "../cros_mojo_token.h"
+#include "../hal_framebuffer.h"
+
+EncoderJea::EncoderJea() = default;
+
+EncoderJea::~EncoderJea() = default;
+
+int EncoderJea::configure(const libcamera::StreamConfiguration &cfg)
+{
+ size_ = cfg.size;
+
+ if (jpegCompressor_)
+ return 0;
+
+ if (gCrosMojoToken == nullptr)
+ return -ENOTSUP;
+
+ jpegCompressor_ = cros::JpegCompressor::GetInstance(gCrosMojoToken);
+
+ return 0;
+}
+
+int EncoderJea::encode(Camera3RequestDescriptor::StreamBuffer *streamBuffer,
+ libcamera::Span<const uint8_t> exifData,
+ unsigned int quality)
+{
+ if (!jpegCompressor_)
+ return -ENOTSUP;
+
+ uint32_t outDataSize = 0;
+ const HALFrameBuffer *fb = dynamic_cast<const HALFrameBuffer *>(
+ streamBuffer->srcBuffer);
+
+ if (!jpegCompressor_->CompressImageFromHandle(fb->handle(),
+ *streamBuffer->camera3Buffer,
+ size_.width, size_.height,
+ quality, exifData.data(),
+ exifData.size(),
+ &outDataSize))
+ return -EBUSY;
+
+ return outDataSize;
+}
+
+int EncoderJea::generateThumbnail(const libcamera::FrameBuffer &source,
+ const libcamera::Size &targetSize,
+ unsigned int quality,
+ std::vector<unsigned char> *thumbnail)
+{
+ if (!jpegCompressor_)
+ return -ENOTSUP;
+
+ libcamera::MappedFrameBuffer frame(&source,
+ libcamera::MappedFrameBuffer::MapFlag::Read);
+
+ if (frame.planes().empty())
+ return -ENODATA;
+
+ uint32_t outDataSize = 0;
+
+ // Since the structure of the App1 segment is like:
+ // 0xFF [1 byte marker] [2 bytes size] [data]
+ // And it should not be larger than 64K.
+ const int kApp1MaxDataSize = 65532;
+ thumbnail->resize(kApp1MaxDataSize);
+
+ if (!jpegCompressor_->GenerateThumbnail(frame.planes()[0].data(),
+ size_.width, size_.height,
+ targetSize.width,
+ targetSize.height, quality,
+ thumbnail->size(),
+ thumbnail->data(),
+ &outDataSize)) {
+ thumbnail->clear();
+ return -EBUSY;
+ }
+
+ thumbnail->resize(outDataSize);
+ return outDataSize;
+}
new file mode 100644
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022, Google Inc.
+ *
+ * encoder_jea.h - JPEG encoding using CrOS JEA
+ */
+
+#pragma once
+
+#include <libcamera/geometry.h>
+
+#include <cros-camera/jpeg_compressor.h>
+
+#include "encoder.h"
+
+class EncoderJea : public Encoder
+{
+public:
+ EncoderJea();
+ ~EncoderJea();
+
+ int configure(const libcamera::StreamConfiguration &cfg) override;
+ int encode(Camera3RequestDescriptor::StreamBuffer *streamBuffer,
+ libcamera::Span<const uint8_t> exifData,
+ unsigned int quality) override;
+ int generateThumbnail(const libcamera::FrameBuffer &source,
+ const libcamera::Size &targetSize,
+ unsigned int quality,
+ std::vector<unsigned char> *thumbnail) override;
+
+private:
+ libcamera::Size size_;
+
+ std::unique_ptr<cros::JpegCompressor> jpegCompressor_;
+};
@@ -1,8 +1,16 @@
# SPDX-License-Identifier: CC0-1.0
android_hal_sources += files([
- 'encoder_libjpeg.cpp',
'exif.cpp',
'post_processor_jpeg.cpp',
- 'thumbnailer.cpp'
])
+
+platform = get_option('android_platform')
+if platform == 'generic'
+ android_hal_sources += files(['encoder_libjpeg.cpp',
+ 'thumbnailer.cpp'
+ ])
+elif platform == 'cros'
+ android_hal_sources += files(['encoder_jea.cpp'])
+ android_deps += [dependency('libcros_camera')]
+endif
@@ -12,7 +12,11 @@
#include "../camera_device.h"
#include "../camera_metadata.h"
#include "../camera_request.h"
+#if defined(OS_CHROMEOS)
+#include "encoder_jea.h"
+#else // !defined(OS_CHROMEOS)
#include "encoder_libjpeg.h"
+#endif
#include "exif.h"
#include <libcamera/base/log.h>
@@ -44,7 +48,11 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,
streamSize_ = outCfg.size;
+#if defined(OS_CHROMEOS)
+ encoder_ = std::make_unique<EncoderJea>();
+#else // !defined(OS_CHROMEOS)
encoder_ = std::make_unique<EncoderLibJpeg>();
+#endif
return encoder_->configure(inCfg);
}