android: camera_device: Move processing to CameraStream
Move the JPEG processing procedure to the individual CameraStream by augmenting the class with a CameraStream::process() method. This allows removing the CameraStream::encoder() method. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
160bb0998b
commit
9e95d5e453
4 changed files with 80 additions and 67 deletions
|
@ -23,9 +23,6 @@
|
||||||
#include "camera_metadata.h"
|
#include "camera_metadata.h"
|
||||||
#include "system/graphics.h"
|
#include "system/graphics.h"
|
||||||
|
|
||||||
#include "jpeg/encoder_libjpeg.h"
|
|
||||||
#include "jpeg/exif.h"
|
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -133,12 +130,6 @@ const std::map<int, const Camera3Format> camera3FormatsMap = {
|
||||||
|
|
||||||
LOG_DECLARE_CATEGORY(HAL);
|
LOG_DECLARE_CATEGORY(HAL);
|
||||||
|
|
||||||
class MappedCamera3Buffer : public MappedBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MappedCamera3Buffer(const buffer_handle_t camera3buffer, int flags);
|
|
||||||
};
|
|
||||||
|
|
||||||
MappedCamera3Buffer::MappedCamera3Buffer(const buffer_handle_t camera3buffer,
|
MappedCamera3Buffer::MappedCamera3Buffer(const buffer_handle_t camera3buffer,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
|
@ -1471,12 +1462,6 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
if (cameraStream->camera3Stream().format != HAL_PIXEL_FORMAT_BLOB)
|
if (cameraStream->camera3Stream().format != HAL_PIXEL_FORMAT_BLOB)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Encoder *encoder = cameraStream->encoder();
|
|
||||||
if (!encoder) {
|
|
||||||
LOG(HAL, Error) << "Failed to identify encoder";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamConfiguration *streamConfiguration = &config_->at(cameraStream->index());
|
StreamConfiguration *streamConfiguration = &config_->at(cameraStream->index());
|
||||||
Stream *stream = streamConfiguration->stream();
|
Stream *stream = streamConfiguration->stream();
|
||||||
FrameBuffer *buffer = request->findBuffer(stream);
|
FrameBuffer *buffer = request->findBuffer(stream);
|
||||||
|
@ -1497,59 +1482,12 @@ void CameraDevice::requestComplete(Request *request)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set EXIF metadata for various tags. */
|
int ret = cameraStream->process(*buffer, &mapped,
|
||||||
Exif exif;
|
resultMetadata.get());
|
||||||
/* \todo Set Make and Model from external vendor tags. */
|
if (ret) {
|
||||||
exif.setMake("libcamera");
|
|
||||||
exif.setModel("cameraModel");
|
|
||||||
exif.setOrientation(orientation_);
|
|
||||||
exif.setSize(cameraStream->size());
|
|
||||||
/*
|
|
||||||
* We set the frame's EXIF timestamp as the time of encode.
|
|
||||||
* Since the precision we need for EXIF timestamp is only one
|
|
||||||
* second, it is good enough.
|
|
||||||
*/
|
|
||||||
exif.setTimestamp(std::time(nullptr));
|
|
||||||
if (exif.generate() != 0)
|
|
||||||
LOG(HAL, Error) << "Failed to generate valid EXIF data";
|
|
||||||
|
|
||||||
int jpeg_size = encoder->encode(buffer, mapped.maps()[0], exif.data());
|
|
||||||
if (jpeg_size < 0) {
|
|
||||||
LOG(HAL, Error) << "Failed to encode stream image";
|
|
||||||
status = CAMERA3_BUFFER_STATUS_ERROR;
|
status = CAMERA3_BUFFER_STATUS_ERROR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill in the JPEG blob header.
|
|
||||||
*
|
|
||||||
* The mapped size of the buffer is being returned as
|
|
||||||
* substantially larger than the requested JPEG_MAX_SIZE
|
|
||||||
* (which is referenced from maxJpegBufferSize_). Utilise
|
|
||||||
* this static size to ensure the correct offset of the blob is
|
|
||||||
* determined.
|
|
||||||
*
|
|
||||||
* \todo Investigate if the buffer size mismatch is an issue or
|
|
||||||
* expected behaviour.
|
|
||||||
*/
|
|
||||||
uint8_t *resultPtr = mapped.maps()[0].data() +
|
|
||||||
maxJpegBufferSize_ -
|
|
||||||
sizeof(struct camera3_jpeg_blob);
|
|
||||||
auto *blob = reinterpret_cast<struct camera3_jpeg_blob *>(resultPtr);
|
|
||||||
blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
|
|
||||||
blob->jpeg_size = jpeg_size;
|
|
||||||
|
|
||||||
/* Update the JPEG result Metadata. */
|
|
||||||
resultMetadata->addEntry(ANDROID_JPEG_SIZE,
|
|
||||||
&jpeg_size, 1);
|
|
||||||
|
|
||||||
const uint32_t jpeg_quality = 95;
|
|
||||||
resultMetadata->addEntry(ANDROID_JPEG_QUALITY,
|
|
||||||
&jpeg_quality, 1);
|
|
||||||
|
|
||||||
const uint32_t jpeg_orientation = 0;
|
|
||||||
resultMetadata->addEntry(ANDROID_JPEG_ORIENTATION,
|
|
||||||
&jpeg_orientation, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare to call back the Android camera stack. */
|
/* Prepare to call back the Android camera stack. */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <libcamera/request.h>
|
#include <libcamera/request.h>
|
||||||
#include <libcamera/stream.h>
|
#include <libcamera/stream.h>
|
||||||
|
|
||||||
|
#include "libcamera/internal/buffer.h"
|
||||||
#include "libcamera/internal/log.h"
|
#include "libcamera/internal/log.h"
|
||||||
#include "libcamera/internal/message.h"
|
#include "libcamera/internal/message.h"
|
||||||
|
|
||||||
|
@ -28,6 +29,12 @@
|
||||||
|
|
||||||
class CameraMetadata;
|
class CameraMetadata;
|
||||||
|
|
||||||
|
class MappedCamera3Buffer : public libcamera::MappedBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MappedCamera3Buffer(const buffer_handle_t camera3buffer, int flags);
|
||||||
|
};
|
||||||
|
|
||||||
class CameraDevice : protected libcamera::Loggable
|
class CameraDevice : protected libcamera::Loggable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -50,6 +57,7 @@ public:
|
||||||
|
|
||||||
int facing() const { return facing_; }
|
int facing() const { return facing_; }
|
||||||
int orientation() const { return orientation_; }
|
int orientation() const { return orientation_; }
|
||||||
|
unsigned int maxJpegBufferSize() const { return maxJpegBufferSize_; }
|
||||||
|
|
||||||
void setCallbacks(const camera3_callback_ops_t *callbacks);
|
void setCallbacks(const camera3_callback_ops_t *callbacks);
|
||||||
const camera_metadata_t *getStaticMetadata();
|
const camera_metadata_t *getStaticMetadata();
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
#include "camera_stream.h"
|
#include "camera_stream.h"
|
||||||
|
|
||||||
#include "camera_device.h"
|
#include "camera_device.h"
|
||||||
|
#include "camera_metadata.h"
|
||||||
#include "jpeg/encoder.h"
|
#include "jpeg/encoder.h"
|
||||||
#include "jpeg/encoder_libjpeg.h"
|
#include "jpeg/encoder_libjpeg.h"
|
||||||
|
#include "jpeg/exif.h"
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
|
LOG_DECLARE_CATEGORY(HAL);
|
||||||
|
|
||||||
CameraStream::CameraStream(CameraDevice *cameraDevice,
|
CameraStream::CameraStream(CameraDevice *cameraDevice,
|
||||||
camera3_stream_t *camera3Stream,
|
camera3_stream_t *camera3Stream,
|
||||||
const libcamera::StreamConfiguration &cfg,
|
const libcamera::StreamConfiguration &cfg,
|
||||||
|
@ -36,3 +40,62 @@ int CameraStream::configure(const libcamera::StreamConfiguration &cfg)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CameraStream::process(const libcamera::FrameBuffer &source,
|
||||||
|
MappedCamera3Buffer *dest, CameraMetadata *metadata)
|
||||||
|
{
|
||||||
|
if (!encoder_)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Set EXIF metadata for various tags. */
|
||||||
|
Exif exif;
|
||||||
|
/* \todo Set Make and Model from external vendor tags. */
|
||||||
|
exif.setMake("libcamera");
|
||||||
|
exif.setModel("cameraModel");
|
||||||
|
exif.setOrientation(cameraDevice_->orientation());
|
||||||
|
exif.setSize(size_);
|
||||||
|
/*
|
||||||
|
* We set the frame's EXIF timestamp as the time of encode.
|
||||||
|
* Since the precision we need for EXIF timestamp is only one
|
||||||
|
* second, it is good enough.
|
||||||
|
*/
|
||||||
|
exif.setTimestamp(std::time(nullptr));
|
||||||
|
if (exif.generate() != 0)
|
||||||
|
LOG(HAL, Error) << "Failed to generate valid EXIF data";
|
||||||
|
|
||||||
|
int jpeg_size = encoder_->encode(&source, dest->maps()[0], exif.data());
|
||||||
|
if (jpeg_size < 0) {
|
||||||
|
LOG(HAL, Error) << "Failed to encode stream image";
|
||||||
|
return jpeg_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the JPEG blob header.
|
||||||
|
*
|
||||||
|
* The mapped size of the buffer is being returned as
|
||||||
|
* substantially larger than the requested JPEG_MAX_SIZE
|
||||||
|
* (which is referenced from maxJpegBufferSize_). Utilise
|
||||||
|
* this static size to ensure the correct offset of the blob is
|
||||||
|
* determined.
|
||||||
|
*
|
||||||
|
* \todo Investigate if the buffer size mismatch is an issue or
|
||||||
|
* expected behaviour.
|
||||||
|
*/
|
||||||
|
uint8_t *resultPtr = dest->maps()[0].data() +
|
||||||
|
cameraDevice_->maxJpegBufferSize() -
|
||||||
|
sizeof(struct camera3_jpeg_blob);
|
||||||
|
auto *blob = reinterpret_cast<struct camera3_jpeg_blob *>(resultPtr);
|
||||||
|
blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
|
||||||
|
blob->jpeg_size = jpeg_size;
|
||||||
|
|
||||||
|
/* Update the JPEG result Metadata. */
|
||||||
|
metadata->addEntry(ANDROID_JPEG_SIZE, &jpeg_size, 1);
|
||||||
|
|
||||||
|
const uint32_t jpeg_quality = 95;
|
||||||
|
metadata->addEntry(ANDROID_JPEG_QUALITY, &jpeg_quality, 1);
|
||||||
|
|
||||||
|
const uint32_t jpeg_orientation = 0;
|
||||||
|
metadata->addEntry(ANDROID_JPEG_ORIENTATION, &jpeg_orientation, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -11,12 +11,15 @@
|
||||||
|
|
||||||
#include <hardware/camera3.h>
|
#include <hardware/camera3.h>
|
||||||
|
|
||||||
|
#include <libcamera/buffer.h>
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/geometry.h>
|
#include <libcamera/geometry.h>
|
||||||
#include <libcamera/pixel_format.h>
|
#include <libcamera/pixel_format.h>
|
||||||
|
|
||||||
class CameraDevice;
|
|
||||||
class Encoder;
|
class Encoder;
|
||||||
|
class CameraDevice;
|
||||||
|
class CameraMetadata;
|
||||||
|
class MappedCamera3Buffer;
|
||||||
|
|
||||||
class CameraStream
|
class CameraStream
|
||||||
{
|
{
|
||||||
|
@ -113,9 +116,10 @@ public:
|
||||||
const libcamera::Size &size() const { return size_; }
|
const libcamera::Size &size() const { return size_; }
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
unsigned int index() const { return index_; }
|
unsigned int index() const { return index_; }
|
||||||
Encoder *encoder() const { return encoder_.get(); }
|
|
||||||
|
|
||||||
int configure(const libcamera::StreamConfiguration &cfg);
|
int configure(const libcamera::StreamConfiguration &cfg);
|
||||||
|
int process(const libcamera::FrameBuffer &source,
|
||||||
|
MappedCamera3Buffer *dest, CameraMetadata *metadata);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CameraDevice *cameraDevice_;
|
CameraDevice *cameraDevice_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue