mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-15 08:25:07 +03:00
libcamera: pipeline: simple: Move bufferReady handler to SimpleCameraData
To use multiple cameras at the same time, a per-camera buffer ready handler is needed. Move the bufferReady() function connected to the V4L2VideoDevice bufferReady signal from the SimplePipelineHandler class to the SimpleCameraData class. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Martin Kepplinger <martin.kepplinger@puri.sm>
This commit is contained in:
parent
d6e48e5e7c
commit
33914c4cee
1 changed files with 92 additions and 96 deletions
|
@ -181,6 +181,7 @@ public:
|
|||
int setupLinks();
|
||||
int setupFormats(V4L2SubdeviceFormat *format,
|
||||
V4L2Subdevice::Whence whence);
|
||||
void bufferReady(FrameBuffer *buffer);
|
||||
|
||||
unsigned int streamIndex(const Stream *stream) const
|
||||
{
|
||||
|
@ -308,8 +309,6 @@ private:
|
|||
const MediaPad *acquirePipeline(SimpleCameraData *data);
|
||||
void releasePipeline(SimpleCameraData *data);
|
||||
|
||||
void bufferReady(FrameBuffer *buffer);
|
||||
|
||||
MediaDevice *media_;
|
||||
std::map<const MediaEntity *, EntityData> entities_;
|
||||
|
||||
|
@ -627,6 +626,93 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void SimpleCameraData::bufferReady(FrameBuffer *buffer)
|
||||
{
|
||||
SimplePipelineHandler *pipe = SimpleCameraData::pipe();
|
||||
|
||||
/*
|
||||
* If an error occurred during capture, or if the buffer was cancelled,
|
||||
* complete the request, even if the converter is in use as there's no
|
||||
* point converting an erroneous buffer.
|
||||
*/
|
||||
if (buffer->metadata().status != FrameMetadata::FrameSuccess) {
|
||||
if (!useConverter_) {
|
||||
/* No conversion, just complete the request. */
|
||||
Request *request = buffer->request();
|
||||
pipe->completeBuffer(request, buffer);
|
||||
pipe->completeRequest(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The converter is in use. Requeue the internal buffer for
|
||||
* capture (unless the stream is being stopped), and complete
|
||||
* the request with all the user-facing buffers.
|
||||
*/
|
||||
if (buffer->metadata().status != FrameMetadata::FrameCancelled)
|
||||
video_->queueBuffer(buffer);
|
||||
|
||||
if (converterQueue_.empty())
|
||||
return;
|
||||
|
||||
Request *request = nullptr;
|
||||
for (auto &item : converterQueue_.front()) {
|
||||
FrameBuffer *outputBuffer = item.second;
|
||||
request = outputBuffer->request();
|
||||
pipe->completeBuffer(request, outputBuffer);
|
||||
}
|
||||
converterQueue_.pop();
|
||||
|
||||
if (request)
|
||||
pipe->completeRequest(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the sensor's timestamp in the request metadata. The request
|
||||
* needs to be obtained from the user-facing buffer, as internal
|
||||
* buffers are free-wheeling and have no request associated with them.
|
||||
*
|
||||
* \todo The sensor timestamp should be better estimated by connecting
|
||||
* to the V4L2Device::frameStart signal if the platform provides it.
|
||||
*/
|
||||
Request *request = buffer->request();
|
||||
|
||||
if (useConverter_ && !converterQueue_.empty()) {
|
||||
const std::map<unsigned int, FrameBuffer *> &outputs =
|
||||
converterQueue_.front();
|
||||
if (!outputs.empty()) {
|
||||
FrameBuffer *outputBuffer = outputs.begin()->second;
|
||||
if (outputBuffer)
|
||||
request = outputBuffer->request();
|
||||
}
|
||||
}
|
||||
|
||||
if (request)
|
||||
request->metadata().set(controls::SensorTimestamp,
|
||||
buffer->metadata().timestamp);
|
||||
|
||||
/*
|
||||
* Queue the captured and the request buffer to the converter if format
|
||||
* conversion is needed. If there's no queued request, just requeue the
|
||||
* captured buffer for capture.
|
||||
*/
|
||||
if (useConverter_) {
|
||||
if (converterQueue_.empty()) {
|
||||
video_->queueBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
converter_->queueBuffers(buffer, converterQueue_.front());
|
||||
converterQueue_.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise simply complete the request. */
|
||||
pipe->completeBuffer(request, buffer);
|
||||
pipe->completeRequest(request);
|
||||
}
|
||||
|
||||
void SimpleCameraData::converterInputDone(FrameBuffer *buffer)
|
||||
{
|
||||
/* Queue the input buffer back for capture. */
|
||||
|
@ -929,6 +1015,8 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
|
|||
return ret;
|
||||
}
|
||||
|
||||
video->bufferReady.connect(data, &SimpleCameraData::bufferReady);
|
||||
|
||||
ret = video->streamOn();
|
||||
if (ret < 0) {
|
||||
stop(camera);
|
||||
|
@ -963,6 +1051,8 @@ void SimplePipelineHandler::stop(Camera *camera)
|
|||
video->streamOff();
|
||||
video->releaseBuffers();
|
||||
|
||||
video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady);
|
||||
|
||||
data->converterBuffers_.clear();
|
||||
activeCamera_ = nullptr;
|
||||
|
||||
|
@ -1143,8 +1233,6 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
|
|||
<< ": " << strerror(-ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady);
|
||||
break;
|
||||
|
||||
case MediaEntity::Type::V4L2Subdevice:
|
||||
|
@ -1259,98 +1347,6 @@ void SimplePipelineHandler::releasePipeline(SimpleCameraData *data)
|
|||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Buffer Handling
|
||||
*/
|
||||
|
||||
void SimplePipelineHandler::bufferReady(FrameBuffer *buffer)
|
||||
{
|
||||
ASSERT(activeCamera_);
|
||||
SimpleCameraData *data = cameraData(activeCamera_);
|
||||
|
||||
/*
|
||||
* If an error occurred during capture, or if the buffer was cancelled,
|
||||
* complete the request, even if the converter is in use as there's no
|
||||
* point converting an erroneous buffer.
|
||||
*/
|
||||
if (buffer->metadata().status != FrameMetadata::FrameSuccess) {
|
||||
if (!data->useConverter_) {
|
||||
/* No conversion, just complete the request. */
|
||||
Request *request = buffer->request();
|
||||
completeBuffer(request, buffer);
|
||||
completeRequest(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The converter is in use. Requeue the internal buffer for
|
||||
* capture (unless the stream is being stopped), and complete
|
||||
* the request with all the user-facing buffers.
|
||||
*/
|
||||
if (buffer->metadata().status != FrameMetadata::FrameCancelled)
|
||||
data->video_->queueBuffer(buffer);
|
||||
|
||||
if (data->converterQueue_.empty())
|
||||
return;
|
||||
|
||||
Request *request = nullptr;
|
||||
for (auto &item : data->converterQueue_.front()) {
|
||||
FrameBuffer *outputBuffer = item.second;
|
||||
request = outputBuffer->request();
|
||||
completeBuffer(request, outputBuffer);
|
||||
}
|
||||
data->converterQueue_.pop();
|
||||
|
||||
if (request)
|
||||
completeRequest(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the sensor's timestamp in the request metadata. The request
|
||||
* needs to be obtained from the user-facing buffer, as internal
|
||||
* buffers are free-wheeling and have no request associated with them.
|
||||
*
|
||||
* \todo The sensor timestamp should be better estimated by connecting
|
||||
* to the V4L2Device::frameStart signal if the platform provides it.
|
||||
*/
|
||||
Request *request = buffer->request();
|
||||
|
||||
if (data->useConverter_ && !data->converterQueue_.empty()) {
|
||||
const std::map<unsigned int, FrameBuffer *> &outputs =
|
||||
data->converterQueue_.front();
|
||||
if (!outputs.empty()) {
|
||||
FrameBuffer *outputBuffer = outputs.begin()->second;
|
||||
if (outputBuffer)
|
||||
request = outputBuffer->request();
|
||||
}
|
||||
}
|
||||
|
||||
if (request)
|
||||
request->metadata().set(controls::SensorTimestamp,
|
||||
buffer->metadata().timestamp);
|
||||
|
||||
/*
|
||||
* Queue the captured and the request buffer to the converter if format
|
||||
* conversion is needed. If there's no queued request, just requeue the
|
||||
* captured buffer for capture.
|
||||
*/
|
||||
if (data->useConverter_) {
|
||||
if (data->converterQueue_.empty()) {
|
||||
data->video_->queueBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
data->converter_->queueBuffers(buffer, data->converterQueue_.front());
|
||||
data->converterQueue_.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise simply complete the request. */
|
||||
completeBuffer(request, buffer);
|
||||
completeRequest(request);
|
||||
}
|
||||
|
||||
REGISTER_PIPELINE_HANDLER(SimplePipelineHandler)
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue