blob: fc50d412670ea55c54c0ac1b308b87a0844a9b71 [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2020, Google Inc.
*
* camera_stream.h - Camera HAL stream
*/
#pragma once
#include <memory>
#include <queue>
#include <vector>
#include <hardware/camera3.h>
#include <libcamera/base/mutex.h>
#include <libcamera/base/thread.h>
#include <libcamera/camera.h>
#include <libcamera/framebuffer.h>
#include <libcamera/geometry.h>
#include <libcamera/pixel_format.h>
#include "camera_request.h"
#include "post_processor.h"
class CameraDevice;
class PlatformFrameBufferAllocator;
class CameraStream
{
public:
/*
* Enumeration of CameraStream types.
*
* A camera stream associates an Android stream to a libcamera stream.
* This enumeration describes how the two streams are associated and how
* and where data produced from libcamera are delivered to the
* Android framework.
*
* Direct:
*
* The Android stream is directly mapped onto a libcamera stream: frames
* are delivered by the library directly in the memory location
* specified by the Android stream (buffer_handle_t->data) and provided
* to the framework as they are. The Android stream characteristics are
* directly translated to the libcamera stream configuration.
*
* +-----+ +-----+
* | A | | L |
* +-----+ +-----+
* | |
* V V
* +-----+ +------+
* | B |<---------------| FB |
* +-----+ +------+
*
*
* Internal:
*
* Data for the Android stream is produced by processing a libcamera
* stream created by the HAL for that purpose. The libcamera stream
* needs to be supplied with intermediate buffers where the library
* delivers frames to be processed and then provided to the framework.
* The libcamera stream configuration is not a direct translation of the
* Android stream characteristics, but it describes the format and size
* required for the processing procedure to produce frames in the
* Android required format.
*
* +-----+ +-----+
* | A | | L |
* +-----+ +-----+
* | |
* V V
* +-----+ +------+
* | B | | FB |
* +-----+ +------+
* ^ |
* |-------Processing------|
*
*
* Mapped:
*
* Data for the Android stream is produced by processing a libcamera
* stream associated with another CameraStream. Mapped camera streams do
* not need any memory to be reserved for them as they process data
* produced by libcamera for a different stream whose format and size
* are compatible with the processing procedure requirements to produce
* frames in the Android required format.
*
* +-----+ +-----+ +-----+
* | A | | A' | | L |
* +-----+ +-----+ +-----+
* | | |
* V V V
* +-----+ +-----+ +------+
* | B | | B' |<---------| FB |
* +-----+ +-----+ +------+
* ^ |
* |--Processing--|
*
*
* --------------------------------------------------------------------
* A = Android stream
* L = libcamera stream
* B = memory buffer
* FB = libcamera FrameBuffer
* "Processing" = Frame processing procedure (Encoding, scaling etc)
*/
enum class Type {
Direct,
Internal,
Mapped,
};
CameraStream(CameraDevice *const cameraDevice,
libcamera::CameraConfiguration *config, Type type,
camera3_stream_t *camera3Stream,
CameraStream *const sourceStream,
unsigned int index);
CameraStream(CameraStream &&other);
~CameraStream();
Type type() const { return type_; }
camera3_stream_t *camera3Stream() const { return camera3Stream_; }
const libcamera::StreamConfiguration &configuration() const;
libcamera::Stream *stream() const;
CameraStream *sourceStream() const { return sourceStream_; }
bool isJpegStream() const
{
return camera3Stream_->format == HAL_PIXEL_FORMAT_BLOB;
}
int configure();
int process(StreamBuffer *streamBuffer);
libcamera::FrameBuffer *getBuffer();
void putBuffer(libcamera::FrameBuffer *buffer);
void flush();
private:
class PostProcessorWorker : public libcamera::Thread
{
public:
enum class State {
Stopped,
Running,
Flushing,
};
PostProcessorWorker(PostProcessor *postProcessor);
~PostProcessorWorker();
void start();
void queueRequest(StreamBuffer *request);
void flush();
protected:
void run() override;
private:
PostProcessor *postProcessor_;
libcamera::Mutex mutex_;
libcamera::ConditionVariable cv_;
std::queue<StreamBuffer *> requests_
LIBCAMERA_TSA_GUARDED_BY(mutex_);
State state_ LIBCAMERA_TSA_GUARDED_BY(mutex_) = State::Stopped;
};
int waitFence(int fence);
CameraDevice *const cameraDevice_;
const libcamera::CameraConfiguration *config_;
const Type type_;
camera3_stream_t *camera3Stream_;
CameraStream *const sourceStream_;
const unsigned int index_;
std::unique_ptr<PlatformFrameBufferAllocator> allocator_;
std::vector<std::unique_ptr<libcamera::FrameBuffer>> allocatedBuffers_;
std::vector<libcamera::FrameBuffer *> buffers_ LIBCAMERA_TSA_GUARDED_BY(mutex_);
/*
* The class has to be MoveConstructible as instances are stored in
* an std::vector in CameraDevice.
*/
std::unique_ptr<libcamera::Mutex> mutex_;
std::unique_ptr<PostProcessor> postProcessor_;
std::unique_ptr<PostProcessorWorker> worker_;
};