summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/request.h3
-rw-r--r--src/libcamera/include/pipeline_handler.h2
-rw-r--r--src/libcamera/pipeline/ipu3/ipu3.cpp2
-rw-r--r--src/libcamera/pipeline/rkisp1/rkisp1.cpp2
-rw-r--r--src/libcamera/pipeline/uvcvideo.cpp1
-rw-r--r--src/libcamera/pipeline/vimc.cpp1
-rw-r--r--src/libcamera/pipeline_handler.cpp29
-rw-r--r--src/libcamera/request.cpp14
-rw-r--r--src/libcamera/v4l2_videodevice.cpp14
-rw-r--r--test/v4l2_videodevice/buffer_sharing.cpp6
10 files changed, 34 insertions, 40 deletions
diff --git a/include/libcamera/request.h b/include/libcamera/request.h
index f69b4e7a..9edf1ced 100644
--- a/include/libcamera/request.h
+++ b/include/libcamera/request.h
@@ -51,7 +51,7 @@ private:
friend class PipelineHandler;
int prepare();
- void complete(Status status);
+ void complete();
bool completeBuffer(Buffer *buffer);
@@ -62,6 +62,7 @@ private:
const uint64_t cookie_;
Status status_;
+ bool cancelled_;
};
} /* namespace libcamera */
diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index f836d5d1..1fdef9ce 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -74,7 +74,7 @@ public:
const std::set<Stream *> &streams) = 0;
virtual int start(Camera *camera) = 0;
- virtual void stop(Camera *camera);
+ virtual void stop(Camera *camera) = 0;
virtual int queueRequest(Camera *camera, Request *request);
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 5a14edb6..7a54c1fd 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -711,8 +711,6 @@ void PipelineHandlerIPU3::stop(Camera *camera)
if (ret)
LOG(IPU3, Warning) << "Failed to stop camera "
<< camera->name();
-
- PipelineHandler::stop(camera);
}
int PipelineHandlerIPU3::queueRequest(Camera *camera, Request *request)
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 38323643..cc33a2cb 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -354,8 +354,6 @@ void PipelineHandlerRkISP1::stop(Camera *camera)
LOG(RkISP1, Warning)
<< "Failed to stop camera " << camera->name();
- PipelineHandler::stop(camera);
-
activeCamera_ = nullptr;
}
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index 387d71ef..b299c5da 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -220,7 +220,6 @@ void PipelineHandlerUVC::stop(Camera *camera)
{
UVCCameraData *data = cameraData(camera);
data->video_->streamOff();
- PipelineHandler::stop(camera);
}
int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index ff2529c9..7d96c364 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -222,7 +222,6 @@ void PipelineHandlerVimc::stop(Camera *camera)
{
VimcCameraData *data = cameraData(camera);
data->video_->streamOff();
- PipelineHandler::stop(camera);
}
int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request)
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index c6092002..83938a71 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -328,31 +328,7 @@ const ControlInfoMap &PipelineHandler::controls(Camera *camera)
*
* This method stops capturing and processing requests immediately. All pending
* requests are cancelled and complete immediately in an error state.
- *
- * Pipeline handlers shall override this method to stop the pipeline, ensure
- * that all pending request completion signaled through completeRequest() have
- * returned, and call the base implementation of the stop() method as the last
- * step of their implementation. The base implementation cancels all requests
- * queued but not yet complete.
*/
-void PipelineHandler::stop(Camera *camera)
-{
- CameraData *data = cameraData(camera);
-
- while (!data->queuedRequests_.empty()) {
- Request *request = data->queuedRequests_.front();
- data->queuedRequests_.pop_front();
-
- while (!request->pending_.empty()) {
- Buffer *buffer = *request->pending_.begin();
- buffer->cancel();
- completeBuffer(camera, request, buffer);
- }
-
- request->complete(Request::RequestCancelled);
- camera->requestComplete(request);
- }
-}
/**
* \fn PipelineHandler::queueRequest()
@@ -420,15 +396,16 @@ bool PipelineHandler::completeBuffer(Camera *camera, Request *request,
*/
void PipelineHandler::completeRequest(Camera *camera, Request *request)
{
- request->complete(Request::RequestComplete);
+ request->complete();
CameraData *data = cameraData(camera);
while (!data->queuedRequests_.empty()) {
request = data->queuedRequests_.front();
- if (request->hasPendingBuffers())
+ if (request->status() == Request::RequestPending)
break;
+ ASSERT(!request->hasPendingBuffers());
data->queuedRequests_.pop_front();
camera->requestComplete(request);
}
diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp
index 45e7133f..19131472 100644
--- a/src/libcamera/request.cpp
+++ b/src/libcamera/request.cpp
@@ -56,7 +56,7 @@ LOG_DEFINE_CATEGORY(Request)
*/
Request::Request(Camera *camera, uint64_t cookie)
: camera_(camera), controls_(camera), cookie_(cookie),
- status_(RequestPending)
+ status_(RequestPending), cancelled_(false)
{
}
@@ -199,14 +199,15 @@ int Request::prepare()
/**
* \brief Complete a queued request
- * \param[in] status The request completion status
*
- * Mark the request as complete by updating its status to \a status.
+ * Mark the request as complete by updating its status to RequestComplete,
+ * unless buffers have been cancelled in which case the status is set to
+ * RequestCancelled.
*/
-void Request::complete(Status status)
+void Request::complete()
{
ASSERT(!hasPendingBuffers());
- status_ = status;
+ status_ = cancelled_ ? RequestCancelled : RequestComplete;
}
/**
@@ -229,6 +230,9 @@ bool Request::completeBuffer(Buffer *buffer)
buffer->setRequest(nullptr);
+ if (buffer->status() == Buffer::BufferCancelled)
+ cancelled_ = true;
+
return !hasPendingBuffers();
}
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 86e299c0..c43d7cc5 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -1089,7 +1089,9 @@ int V4L2VideoDevice::streamOn()
* \brief Stop the video stream
*
* Buffers that are still queued when the video stream is stopped are
- * implicitly dequeued, but no bufferReady signal is emitted for them.
+ * immediately dequeued with their status set to Buffer::BufferError,
+ * and the bufferReady signal is emitted for them. The order in which those
+ * buffers are dequeued is not specified.
*
* \return 0 on success or a negative error code otherwise
*/
@@ -1104,6 +1106,16 @@ int V4L2VideoDevice::streamOff()
return ret;
}
+ /* Send back all queued buffers. */
+ for (auto it : queuedBuffers_) {
+ unsigned int index = it.first;
+ Buffer *buffer = it.second;
+
+ buffer->index_ = index;
+ buffer->cancel();
+ bufferReady.emit(buffer);
+ }
+
queuedBuffers_.clear();
fdEvent_->setEnabled(false);
diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
index da052f34..12ec88f2 100644
--- a/test/v4l2_videodevice/buffer_sharing.cpp
+++ b/test/v4l2_videodevice/buffer_sharing.cpp
@@ -95,6 +95,9 @@ protected:
std::cout << "Received capture buffer: " << buffer->index()
<< " sequence " << buffer->sequence() << std::endl;
+ if (buffer->status() != Buffer::BufferSuccess)
+ return;
+
output_->queueBuffer(buffer);
framesCaptured_++;
}
@@ -104,6 +107,9 @@ protected:
std::cout << "Received output buffer: " << buffer->index()
<< " sequence " << buffer->sequence() << std::endl;
+ if (buffer->status() != Buffer::BufferSuccess)
+ return;
+
capture_->queueBuffer(buffer);
framesOutput_++;
}