[{"id":21670,"web_url":"https://patchwork.libcamera.org/comment/21670/","msgid":"<YbCa1l/LI5UD8I1V@pendragon.ideasonboard.com>","date":"2021-12-08T11:45:26","subject":"Re: [libcamera-devel] [PATCH v4 08/11] libcamera: pipeline:\n\tIntroduce stopDevice()","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Wed, Dec 01, 2021 at 03:29:33PM +0100, Jacopo Mondi wrote:\n> Since a queue of waiting Requests has been introduced, not all Requests\n> queued to the PipelineHandler are immediately queued to the device.\n> \n> As a Camera can be stopped at any time, it is required to complete the\n> waiting requests after the ones queued to the device had been completed.\n> \n> Introduce a pure virtual PipelineHandler::stopDevice() function to be\n> implemented by pipeline handlers and make the PipelineHandler::stop()\n> function call it before completing pending requests.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  include/libcamera/internal/pipeline_handler.h |  3 +-\n>  src/libcamera/pipeline/ipu3/ipu3.cpp          |  4 +--\n>  .../pipeline/raspberrypi/raspberrypi.cpp      |  4 +--\n>  src/libcamera/pipeline/rkisp1/rkisp1.cpp      |  4 +--\n>  src/libcamera/pipeline/simple/simple.cpp      |  4 +--\n>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  |  4 +--\n>  src/libcamera/pipeline/vimc/vimc.cpp          |  4 +--\n>  src/libcamera/pipeline_handler.cpp            | 30 +++++++++++++++++--\n>  8 files changed, 42 insertions(+), 15 deletions(-)\n> \n> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\n> index 6aa3378547ba..ec986a518b5c 100644\n> --- a/include/libcamera/internal/pipeline_handler.h\n> +++ b/include/libcamera/internal/pipeline_handler.h\n> @@ -55,7 +55,7 @@ public:\n>  \t\t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;\n>  \n>  \tvirtual int start(Camera *camera, const ControlList *controls) = 0;\n> -\tvirtual void stop(Camera *camera) = 0;\n> +\tvoid stop(Camera *camera);\n>  \tbool hasPendingRequests(const Camera *camera) const;\n>  \n>  \tvoid queueRequest(Request *request);\n> @@ -70,6 +70,7 @@ protected:\n>  \tvoid hotplugMediaDevice(MediaDevice *media);\n>  \n>  \tvirtual int queueRequestDevice(Camera *camera, Request *request) = 0;\n> +\tvirtual void stopDevice(Camera *camera) = 0;\n>  \n>  \tCameraManager *manager_;\n>  \n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index c65afdb2912a..8da1cd93c4dc 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -134,7 +134,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tint queueRequestDevice(Camera *camera, Request *request) override;\n>  \n> @@ -792,7 +792,7 @@ error:\n>  \treturn ret;\n>  }\n>  \n> -void PipelineHandlerIPU3::stop(Camera *camera)\n> +void PipelineHandlerIPU3::stopDevice(Camera *camera)\n>  {\n>  \tIPU3CameraData *data = cameraData(camera);\n>  \tint ret = 0;\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index fa2848533b29..cb6ba1c2db18 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -303,7 +303,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tint queueRequestDevice(Camera *camera, Request *request) override;\n>  \n> @@ -924,7 +924,7 @@ int PipelineHandlerRPi::start(Camera *camera, const ControlList *controls)\n>  \treturn 0;\n>  }\n>  \n> -void PipelineHandlerRPi::stop(Camera *camera)\n> +void PipelineHandlerRPi::stopDevice(Camera *camera)\n>  {\n>  \tRPiCameraData *data = cameraData(camera);\n>  \n> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n> index 36ef6a02ae90..8cca8a15a3c3 100644\n> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n> @@ -146,7 +146,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tint queueRequestDevice(Camera *camera, Request *request) override;\n>  \n> @@ -827,7 +827,7 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL\n>  \treturn ret;\n>  }\n>  \n> -void PipelineHandlerRkISP1::stop(Camera *camera)\n> +void PipelineHandlerRkISP1::stopDevice(Camera *camera)\n>  {\n>  \tRkISP1CameraData *data = cameraData(camera);\n>  \tint ret;\n> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> index 701fb4be0b71..fdff4ebd5134 100644\n> --- a/src/libcamera/pipeline/simple/simple.cpp\n> +++ b/src/libcamera/pipeline/simple/simple.cpp\n> @@ -279,7 +279,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tbool match(DeviceEnumerator *enumerator) override;\n>  \n> @@ -1036,7 +1036,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>  \treturn 0;\n>  }\n>  \n> -void SimplePipelineHandler::stop(Camera *camera)\n> +void SimplePipelineHandler::stopDevice(Camera *camera)\n>  {\n>  \tSimpleCameraData *data = cameraData(camera);\n>  \tV4L2VideoDevice *video = data->video_;\n> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> index 264f5370cf32..40654a0bc40c 100644\n> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n> @@ -74,7 +74,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tint queueRequestDevice(Camera *camera, Request *request) override;\n>  \n> @@ -250,7 +250,7 @@ int PipelineHandlerUVC::start(Camera *camera, [[maybe_unused]] const ControlList\n>  \treturn 0;\n>  }\n>  \n> -void PipelineHandlerUVC::stop(Camera *camera)\n> +void PipelineHandlerUVC::stopDevice(Camera *camera)\n>  {\n>  \tUVCCameraData *data = cameraData(camera);\n>  \tdata->video_->streamOff();\n> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\n> index e453091da4b2..29960fe3f038 100644\n> --- a/src/libcamera/pipeline/vimc/vimc.cpp\n> +++ b/src/libcamera/pipeline/vimc/vimc.cpp\n> @@ -91,7 +91,7 @@ public:\n>  \t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n>  \n>  \tint start(Camera *camera, const ControlList *controls) override;\n> -\tvoid stop(Camera *camera) override;\n> +\tvoid stopDevice(Camera *camera) override;\n>  \n>  \tint queueRequestDevice(Camera *camera, Request *request) override;\n>  \n> @@ -359,7 +359,7 @@ int PipelineHandlerVimc::start(Camera *camera, [[maybe_unused]] const ControlLis\n>  \treturn 0;\n>  }\n>  \n> -void PipelineHandlerVimc::stop(Camera *camera)\n> +void PipelineHandlerVimc::stopDevice(Camera *camera)\n>  {\n>  \tVimcCameraData *data = cameraData(camera);\n>  \tdata->video_->streamOff();\n> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\n> index 2374c2891c64..863d206a7ddd 100644\n> --- a/src/libcamera/pipeline_handler.cpp\n> +++ b/src/libcamera/pipeline_handler.cpp\n> @@ -267,8 +267,7 @@ void PipelineHandler::unlock()\n>   */\n>  \n>  /**\n> - * \\fn PipelineHandler::stop()\n> - * \\brief Stop capturing from all running streams\n> + * \\brief Stop capturing from all running streams and cancel pending requests\n>   * \\param[in] camera The camera to stop\n>   *\n>   * This function stops capturing and processing requests immediately. All\n> @@ -276,6 +275,33 @@ void PipelineHandler::unlock()\n>   *\n>   * \\context This function is called from the CameraManager thread.\n>   */\n> +void PipelineHandler::stop(Camera *camera)\n> +{\n> +\t/* Stop the pipeline handler and let the queued requests complete. */\n> +\tstopDevice(camera);\n> +\n> +\t/* Cancel and signal as complete all waiting requests. */\n> +\twhile (!waitingRequests_.empty()) {\n> +\t\tRequest *request = waitingRequests_.front();\n> +\n> +\t\trequest->_d()->cancel();\n> +\t\tcompleteRequest(request);\n> +\t\twaitingRequests_.pop();\n\nI'd move the pop() call just after front() to match what we usually do,\nbut it likely makes no real difference.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> +\t}\n> +\n> +\t/* Make sure no requests are pending. */\n> +\tCamera::Private *data = camera->_d();\n> +\tASSERT(data->queuedRequests_.empty());\n> +}\n> +\n> +/**\n> + * \\fn PipelineHandler::stopDevice()\n> + * \\brief Stop capturing from all running streams\n> + * \\param[in] camera The camera to stop\n> + *\n> + * This function stops capturing and processing requests immediately. All\n> + * pending requests are cancelled and complete immediately in an error state.\n> + */\n>  \n>  /**\n>   * \\brief Determine if the camera has any requests pending","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 6808DBDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Dec 2021 11:45:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B13A46086A;\n\tWed,  8 Dec 2021 12:45:58 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8409160225\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Dec 2021 12:45:56 +0100 (CET)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0A1F68BB;\n\tWed,  8 Dec 2021 12:45:55 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"TE2JU9vA\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1638963956;\n\tbh=ZMbmUKJGZje9bAhs5kZVr+lrhf9xVpYir2T6VMMiPmM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=TE2JU9vAlw8lzSwlEJFMVtcj3M506qGY64OTpVXnzSxGqW3BC0KLQtGbTNr2qq46W\n\t6O4xM5Rn5hVDS89gdNDGOECOPeBRNF+5/kiQHjnxCdcbvUVk/TVjOYJA4f5Vr5Oh0w\n\tgB+vgZEXd0viA1ZY5/e4/rgGu1ZIHQCG94DN31dI=","Date":"Wed, 8 Dec 2021 13:45:26 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<YbCa1l/LI5UD8I1V@pendragon.ideasonboard.com>","References":"<20211201142936.107405-1-jacopo@jmondi.org>\n\t<20211201142936.107405-9-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20211201142936.107405-9-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v4 08/11] libcamera: pipeline:\n\tIntroduce stopDevice()","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]