summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/camera_device.cpp87
-rw-r--r--src/android/camera_device.h4
-rw-r--r--src/android/camera_request.h6
-rw-r--r--src/android/camera_stream.cpp15
-rw-r--r--src/android/jpeg/post_processor_jpeg.cpp2
-rw-r--r--src/android/post_processor.h9
-rw-r--r--src/android/yuv/post_processor_yuv.cpp8
7 files changed, 106 insertions, 25 deletions
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 9155728a..fed539f3 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -926,6 +926,9 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
* Request.
*/
LOG(HAL, Debug) << ss.str() << " (mapped)";
+
+ descriptor->pendingStreamsToProcess_.insert(
+ { cameraStream, &buffer });
continue;
case CameraStream::Type::Direct:
@@ -955,6 +958,9 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
frameBuffer = cameraStream->getBuffer();
buffer.internalBuffer = frameBuffer;
LOG(HAL, Debug) << ss.str() << " (internal)";
+
+ descriptor->pendingStreamsToProcess_.insert(
+ { cameraStream, &buffer });
break;
}
@@ -1118,42 +1124,42 @@ void CameraDevice::requestComplete(Request *request)
}
/* Handle post-processing. */
- for (auto &buffer : descriptor->buffers_) {
- CameraStream *stream = buffer.stream;
-
- if (stream->type() == CameraStream::Type::Direct)
- continue;
+ /*
+ * \todo Protect the loop below with streamsProcessMutex_ when post
+ * processor runs asynchronously.
+ */
+ auto iter = descriptor->pendingStreamsToProcess_.begin();
+ while (iter != descriptor->pendingStreamsToProcess_.end()) {
+ CameraStream *stream = iter->first;
+ Camera3RequestDescriptor::StreamBuffer *buffer = iter->second;
FrameBuffer *src = request->findBuffer(stream->stream());
if (!src) {
LOG(HAL, Error) << "Failed to find a source stream buffer";
- buffer.status = Camera3RequestDescriptor::Status::Error;
- notifyError(descriptor->frameNumber_, stream->camera3Stream(),
- CAMERA3_MSG_ERROR_BUFFER);
- descriptor->status_ = Camera3RequestDescriptor::Status::Error;
+ setBufferStatus(*buffer, Camera3RequestDescriptor::Status::Error);
+ iter = descriptor->pendingStreamsToProcess_.erase(iter);
continue;
}
- buffer.srcBuffer = src;
-
- int ret = stream->process(&buffer);
-
- /*
- * If the framebuffer is internal to CameraStream return it back
- * now that we're done processing it.
- */
- if (buffer.internalBuffer)
- stream->putBuffer(buffer.internalBuffer);
+ buffer->srcBuffer = src;
+ ++iter;
+ int ret = stream->process(buffer);
if (ret) {
- buffer.status = Camera3RequestDescriptor::Status::Error;
- notifyError(descriptor->frameNumber_, stream->camera3Stream(),
- CAMERA3_MSG_ERROR_BUFFER);
- descriptor->status_ = Camera3RequestDescriptor::Status::Error;
+ setBufferStatus(*buffer, Camera3RequestDescriptor::Status::Error);
+ descriptor->pendingStreamsToProcess_.erase(stream);
+
+ /*
+ * If the framebuffer is internal to CameraStream return
+ * it back now that we're done processing it.
+ */
+ if (buffer->internalBuffer)
+ stream->putBuffer(buffer->internalBuffer);
}
}
- completeDescriptor(descriptor);
+ if (descriptor->pendingStreamsToProcess_.empty())
+ completeDescriptor(descriptor);
}
void CameraDevice::completeDescriptor(Camera3RequestDescriptor *descriptor)
@@ -1208,6 +1214,39 @@ void CameraDevice::sendCaptureResults()
}
}
+void CameraDevice::setBufferStatus(Camera3RequestDescriptor::StreamBuffer &streamBuffer,
+ Camera3RequestDescriptor::Status status)
+{
+ streamBuffer.status = status;
+ if (status != Camera3RequestDescriptor::Status::Success) {
+ notifyError(streamBuffer.request->frameNumber_,
+ streamBuffer.stream->camera3Stream(),
+ CAMERA3_MSG_ERROR_BUFFER);
+
+ /* Also set error status on entire request descriptor. */
+ streamBuffer.request->status_ =
+ Camera3RequestDescriptor::Status::Error;
+ }
+}
+
+void CameraDevice::streamProcessingComplete(Camera3RequestDescriptor::StreamBuffer *streamBuffer,
+ Camera3RequestDescriptor::Status status)
+{
+ setBufferStatus(*streamBuffer, status);
+
+ /*
+ * If the framebuffer is internal to CameraStream return it back now
+ * that we're done processing it.
+ */
+ if (streamBuffer->internalBuffer)
+ streamBuffer->stream->putBuffer(streamBuffer->internalBuffer);
+
+ Camera3RequestDescriptor *request = streamBuffer->request;
+ MutexLocker locker(request->streamsProcessMutex_);
+
+ request->pendingStreamsToProcess_.erase(streamBuffer->stream);
+}
+
std::string CameraDevice::logPrefix() const
{
return "'" + camera_->id() + "'";
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index e544f2bd..2a414020 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -66,6 +66,8 @@ public:
int configureStreams(camera3_stream_configuration_t *stream_list);
int processCaptureRequest(camera3_capture_request_t *request);
void requestComplete(libcamera::Request *request);
+ void streamProcessingComplete(Camera3RequestDescriptor::StreamBuffer *bufferStream,
+ Camera3RequestDescriptor::Status status);
protected:
std::string logPrefix() const override;
@@ -95,6 +97,8 @@ private:
int processControls(Camera3RequestDescriptor *descriptor);
void completeDescriptor(Camera3RequestDescriptor *descriptor);
void sendCaptureResults();
+ void setBufferStatus(Camera3RequestDescriptor::StreamBuffer &buffer,
+ Camera3RequestDescriptor::Status status);
std::unique_ptr<CameraMetadata> getResultMetadata(
const Camera3RequestDescriptor &descriptor) const;
diff --git a/src/android/camera_request.h b/src/android/camera_request.h
index ebe2e89d..cfafa445 100644
--- a/src/android/camera_request.h
+++ b/src/android/camera_request.h
@@ -7,7 +7,9 @@
#ifndef __ANDROID_CAMERA_REQUEST_H__
#define __ANDROID_CAMERA_REQUEST_H__
+#include <map>
#include <memory>
+#include <mutex>
#include <vector>
#include <libcamera/base/class.h>
@@ -43,6 +45,10 @@ public:
Camera3RequestDescriptor *request;
};
+ /* Keeps track of streams requiring post-processing. */
+ std::map<CameraStream *, StreamBuffer *> pendingStreamsToProcess_;
+ std::mutex streamsProcessMutex_;
+
Camera3RequestDescriptor(libcamera::Camera *camera,
const camera3_capture_request_t *camera3Request);
~Camera3RequestDescriptor();
diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp
index 282b19b0..dac216d6 100644
--- a/src/android/camera_stream.cpp
+++ b/src/android/camera_stream.cpp
@@ -22,6 +22,7 @@
#include "camera_capabilities.h"
#include "camera_device.h"
#include "camera_metadata.h"
+#include "post_processor.h"
using namespace libcamera;
@@ -97,6 +98,20 @@ int CameraStream::configure()
int ret = postProcessor_->configure(configuration(), output);
if (ret)
return ret;
+
+ postProcessor_->processComplete.connect(
+ this, [&](Camera3RequestDescriptor::StreamBuffer *streamBuffer,
+ PostProcessor::Status status) {
+ Camera3RequestDescriptor::Status bufferStatus;
+
+ if (status == PostProcessor::Status::Success)
+ bufferStatus = Camera3RequestDescriptor::Status::Success;
+ else
+ bufferStatus = Camera3RequestDescriptor::Status::Error;
+
+ cameraDevice_->streamProcessingComplete(streamBuffer,
+ bufferStatus);
+ });
}
if (type_ == Type::Internal) {
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index 240e29f6..5e8c61fc 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -198,6 +198,7 @@ int PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBuf
exif.data(), quality);
if (jpeg_size < 0) {
LOG(JPEG, Error) << "Failed to encode stream image";
+ processComplete.emit(streamBuffer, PostProcessor::Status::Error);
return jpeg_size;
}
@@ -211,6 +212,7 @@ int PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBuf
/* Update the JPEG result Metadata. */
resultMetadata->addEntry(ANDROID_JPEG_SIZE, jpeg_size);
+ processComplete.emit(streamBuffer, PostProcessor::Status::Success);
return 0;
}
diff --git a/src/android/post_processor.h b/src/android/post_processor.h
index 128161c8..4ac74fcf 100644
--- a/src/android/post_processor.h
+++ b/src/android/post_processor.h
@@ -7,6 +7,8 @@
#ifndef __ANDROID_POST_PROCESSOR_H__
#define __ANDROID_POST_PROCESSOR_H__
+#include <libcamera/base/signal.h>
+
#include <libcamera/framebuffer.h>
#include <libcamera/stream.h>
@@ -16,11 +18,18 @@
class PostProcessor
{
public:
+ enum class Status {
+ Error,
+ Success
+ };
+
virtual ~PostProcessor() = default;
virtual int configure(const libcamera::StreamConfiguration &inCfg,
const libcamera::StreamConfiguration &outCfg) = 0;
virtual int process(Camera3RequestDescriptor::StreamBuffer *streamBuffer) = 0;
+
+ libcamera::Signal<Camera3RequestDescriptor::StreamBuffer *, Status> processComplete;
};
#endif /* __ANDROID_POST_PROCESSOR_H__ */
diff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp
index 70385ab3..05c4f1cf 100644
--- a/src/android/yuv/post_processor_yuv.cpp
+++ b/src/android/yuv/post_processor_yuv.cpp
@@ -54,12 +54,15 @@ int PostProcessorYuv::process(Camera3RequestDescriptor::StreamBuffer *streamBuff
const FrameBuffer &source = *streamBuffer->srcBuffer;
CameraBuffer *destination = streamBuffer->dstBuffer.get();
- if (!isValidBuffers(source, *destination))
+ if (!isValidBuffers(source, *destination)) {
+ processComplete.emit(streamBuffer, PostProcessor::Status::Error);
return -EINVAL;
+ }
const MappedFrameBuffer sourceMapped(&source, MappedFrameBuffer::MapFlag::Read);
if (!sourceMapped.isValid()) {
LOG(YUV, Error) << "Failed to mmap camera frame buffer";
+ processComplete.emit(streamBuffer, PostProcessor::Status::Error);
return -EINVAL;
}
@@ -77,9 +80,12 @@ int PostProcessorYuv::process(Camera3RequestDescriptor::StreamBuffer *streamBuff
libyuv::FilterMode::kFilterBilinear);
if (ret) {
LOG(YUV, Error) << "Failed NV12 scaling: " << ret;
+ processComplete.emit(streamBuffer, PostProcessor::Status::Error);
return -EINVAL;
}
+ processComplete.emit(streamBuffer, PostProcessor::Status::Success);
+
return 0;
}