diff options
-rw-r--r-- | include/libcamera/request.h | 3 | ||||
-rw-r--r-- | src/libcamera/include/pipeline_handler.h | 2 | ||||
-rw-r--r-- | src/libcamera/pipeline/ipu3/ipu3.cpp | 2 | ||||
-rw-r--r-- | src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 | ||||
-rw-r--r-- | src/libcamera/pipeline/uvcvideo.cpp | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/vimc.cpp | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline_handler.cpp | 29 | ||||
-rw-r--r-- | src/libcamera/request.cpp | 14 | ||||
-rw-r--r-- | src/libcamera/v4l2_videodevice.cpp | 14 | ||||
-rw-r--r-- | test/v4l2_videodevice/buffer_sharing.cpp | 6 |
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_++; } |