diff options
Diffstat (limited to 'src/android/camera_stream.cpp')
-rw-r--r-- | src/android/camera_stream.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp new file mode 100644 index 00000000..bf4a7b41 --- /dev/null +++ b/src/android/camera_stream.cpp @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * camera_stream.cpp - Camera HAL stream + */ + +#include "camera_stream.h" + +#include "camera_buffer.h" +#include "camera_device.h" +#include "camera_metadata.h" +#include "jpeg/post_processor_jpeg.h" + +#include <libcamera/formats.h> + +using namespace libcamera; + +LOG_DECLARE_CATEGORY(HAL) + +/* + * \class CameraStream + * \brief Map a camera3_stream_t to a StreamConfiguration + * + * The CameraStream class maps a camera3_stream_t provided by Android + * camera framework to a libcamera::StreamConfiguration. + * + * The StreamConfiguration is represented by its index as recorded in the + * CameraConfiguration and not by pointer as StreamConfiguration is subject to + * relocation. + * + * A single StreamConfiguration may be used to deliver one or more streams to + * the Android framework. The mapping type between a camera3 stream to a + * StreamConfiguration is described by the CameraStream::Type. + * + * CameraStream handles all the aspects of producing a stream with the size + * and format requested by the camera3 stream from the data produced by + * the associated libcamera::Stream, including the creation of the encoder + * and buffer allocation. + */ + +CameraStream::CameraStream(CameraDevice *const cameraDevice, + CameraConfiguration *config, Type type, + camera3_stream_t *camera3Stream, unsigned int index) + : cameraDevice_(cameraDevice), config_(config), type_(type), + camera3Stream_(camera3Stream), index_(index) +{ + if (type_ == Type::Internal || type_ == Type::Mapped) { + /* + * \todo There might be multiple post-processors. The logic + * which should be instantiated here, is deferred for the + * future. For now, we only have PostProcessorJpeg and that + * is what we instantiate here. + */ + postProcessor_ = std::make_unique<PostProcessorJpeg>(cameraDevice_); + } + + if (type == Type::Internal) { + allocator_ = std::make_unique<FrameBufferAllocator>(cameraDevice_->camera()); + mutex_ = std::make_unique<std::mutex>(); + } +} + +const StreamConfiguration &CameraStream::configuration() const +{ + return config_->at(index_); +} + +Stream *CameraStream::stream() const +{ + return configuration().stream(); +} + +int CameraStream::configure() +{ + if (postProcessor_) { + StreamConfiguration output = configuration(); + output.pixelFormat = formats::MJPEG; + int ret = postProcessor_->configure(configuration(), output); + if (ret) + return ret; + } + + if (allocator_) { + int ret = allocator_->allocate(stream()); + if (ret < 0) + return ret; + + /* Save a pointer to the reserved frame buffers */ + for (const auto &frameBuffer : allocator_->buffers(stream())) + buffers_.push_back(frameBuffer.get()); + } + + camera3Stream_->max_buffers = configuration().bufferCount; + + return 0; +} + +int CameraStream::process(const libcamera::FrameBuffer &source, + buffer_handle_t camera3Dest, + const CameraMetadata &requestMetadata, + CameraMetadata *resultMetadata) +{ + if (!postProcessor_) + return 0; + + /* + * \todo Buffer mapping and processing should be moved to a + * separate thread. + */ + CameraBuffer dest(camera3Dest, PROT_READ | PROT_WRITE); + if (!dest.isValid()) { + LOG(HAL, Error) << "Failed to map android blob buffer"; + return -EINVAL; + } + + return postProcessor_->process(source, &dest, requestMetadata, resultMetadata); +} + +FrameBuffer *CameraStream::getBuffer() +{ + if (!allocator_) + return nullptr; + + std::lock_guard<std::mutex> locker(*mutex_); + + if (buffers_.empty()) { + LOG(HAL, Error) << "Buffer underrun"; + return nullptr; + } + + FrameBuffer *buffer = buffers_.back(); + buffers_.pop_back(); + + return buffer; +} + +void CameraStream::putBuffer(libcamera::FrameBuffer *buffer) +{ + if (!allocator_) + return; + + std::lock_guard<std::mutex> locker(*mutex_); + + buffers_.push_back(buffer); +} |