[{"id":3253,"web_url":"https://patchwork.libcamera.org/comment/3253/","msgid":"<20191215091235.GA4889@pendragon.ideasonboard.com>","date":"2019-12-15T09:12:35","subject":"Re: [libcamera-devel] [PATCH 30/30] libcamera: camera: Remove the\n\tprepared state","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Wed, Nov 27, 2019 at 12:36:20AM +0100, Niklas Söderlund wrote:\n> With the FrameBuffer rework completed there is no reason to keep the\n> camera prepared state around as buffer allocations are now decoupled\n> from the camera state. Remove the camera state simplifying the API.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n>  include/libcamera/camera.h    |   4 --\n>  src/android/camera_device.cpp |  10 +---\n>  src/cam/capture.cpp           |   8 ---\n>  src/libcamera/camera.cpp      | 104 ++++++++--------------------------\n>  src/qcam/main_window.cpp      |   9 ---\n>  test/camera/buffer_import.cpp |  10 ----\n>  test/camera/capture.cpp       |  10 ----\n>  test/camera/statemachine.cpp  |  83 ---------------------------\n>  8 files changed, 26 insertions(+), 212 deletions(-)\n> \n> diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h\n> index 02d047b9649f53d0..9f542aab213c5d47 100644\n> --- a/include/libcamera/camera.h\n> +++ b/include/libcamera/camera.h\n> @@ -90,9 +90,6 @@ public:\n>  \tstd::unique_ptr<CameraConfiguration> generateConfiguration(const StreamRoles &roles);\n>  \tint configure(CameraConfiguration *config);\n>  \n> -\tint allocateBuffers();\n> -\tint freeBuffers();\n> -\n>  \tRequest *createRequest(uint64_t cookie = 0);\n>  \tint queueRequest(Request *request);\n>  \n> @@ -104,7 +101,6 @@ private:\n>  \t\tCameraAvailable,\n>  \t\tCameraAcquired,\n>  \t\tCameraConfigured,\n> -\t\tCameraPrepared,\n>  \t\tCameraRunning,\n>  \t};\n>  \n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index a6da658bec277933..34c6119228a9ac0e 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -78,7 +78,6 @@ void CameraDevice::close()\n>  {\n>  \tcamera_->stop();\n>  \n\nI think you can remove this blank line too.\n\n> -\tcamera_->freeBuffers();\n>  \tcamera_->release();\n>  \n>  \trunning_ = false;\n> @@ -690,16 +689,9 @@ void CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reque\n>  \n>  \t/* Start the camera if that's the first request we handle. */\n>  \tif (!running_) {\n> -\t\tint ret = camera_->allocateBuffers();\n> -\t\tif (ret) {\n> -\t\t\tLOG(HAL, Error) << \"Failed to allocate buffers\";\n> -\t\t\treturn;\n> -\t\t}\n> -\n> -\t\tret = camera_->start();\n> +\t\tint ret = camera_->start();\n>  \t\tif (ret) {\n>  \t\t\tLOG(HAL, Error) << \"Failed to start camera\";\n> -\t\t\tcamera_->freeBuffers();\n>  \t\t\treturn;\n>  \t\t}\n>  \n> diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp\n> index 154e6e461ee2b96b..835943a7d2b82e79 100644\n> --- a/src/cam/capture.cpp\n> +++ b/src/cam/capture.cpp\n> @@ -42,12 +42,6 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options)\n>  \t\treturn ret;\n>  \t}\n>  \n> -\tret = camera_->allocateBuffers();\n> -\tif (ret) {\n> -\t\tstd::cerr << \"Failed to allocate buffers\" << std::endl;\n> -\t\treturn ret;\n> -\t}\n> -\n>  \tcamera_->requestCompleted.connect(this, &Capture::requestComplete);\n>  \n>  \tif (options.isSet(OptFile)) {\n> @@ -67,8 +61,6 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options)\n>  \t\twriter_ = nullptr;\n>  \t}\n>  \n> -\tcamera_->freeBuffers();\n> -\n>  \treturn ret;\n>  }\n>  \n> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n> index 12878a1c2e6076d3..fca75040ad8b16e7 100644\n> --- a/src/libcamera/camera.cpp\n> +++ b/src/libcamera/camera.cpp\n> @@ -274,15 +274,13 @@ std::size_t CameraConfiguration::size() const\n>   * \\section camera_operation Operating the Camera\n>   *\n>   * An application needs to perform a sequence of operations on a camera before\n> - * it is ready to process requests. The camera needs to be acquired, configured\n> - * and resources allocated or imported to prepare the camera for capture. Once\n> - * started the camera can process requests until it is stopped. When an\n> - * application is done with a camera all resources allocated need to be freed\n> - * and the camera released.\n> + * it is ready to process requests. The camera needs to be acquired and\n> + * configured to prepare the camera for capture. Once started the camera can\n> + * process requests until it is stopped. When an application is done with a\n> + * camera it needs to be released.\n\n\"it\" as ambiguous here as it could refer to the application or the\ncamera. I would write \"When an application is done with a camera, the\ncamera needs to be released.\".\n\n>   *\n>   * An application may start and stop a camera multiple times as long as it is\n> - * not released. The camera may also be reconfigured provided that all\n> - * resources allocated are freed prior to the reconfiguration.\n> + * not released. The camera may also be reconfigured.\n>   *\n>   * \\subsection Camera States\n>   *\n> @@ -296,7 +294,6 @@ std::size_t CameraConfiguration::size() const\n>   *   node [shape = doublecircle ]; Available;\n>   *   node [shape = circle ]; Acquired;\n>   *   node [shape = circle ]; Configured;\n> - *   node [shape = circle ]; Prepared;\n>   *   node [shape = circle ]; Running;\n>   *\n>   *   Available -> Available [label = \"release()\"];\n> @@ -306,14 +303,10 @@ std::size_t CameraConfiguration::size() const\n>   *   Acquired -> Configured [label = \"configure()\"];\n>   *\n>   *   Configured -> Available [label = \"release()\"];\n> - *   Configured -> Configured [label = \"configure()\"];\n> - *   Configured -> Prepared [label = \"allocateBuffers()\"];\n> + *   Configured -> Configured [label = \"configure(), createRequest()\"];\n> + *   Configured -> Running [label = \"start()\"];\n>   *\n> - *   Prepared -> Configured [label = \"freeBuffers()\"];\n> - *   Prepared -> Prepared [label = \"createRequest()\"];\n> - *   Prepared -> Running [label = \"start()\"];\n> - *\n> - *   Running -> Prepared [label = \"stop()\"];\n> + *   Running -> Configured [label = \"stop()\"];\n>   *   Running -> Running [label = \"createRequest(), queueRequest()\"];\n>   * }\n>   * \\enddot\n> @@ -329,19 +322,14 @@ std::size_t CameraConfiguration::size() const\n>   * Configured state.\n>   *\n>   * \\subsubsection Configured\n> - * The camera is configured and ready for the application to prepare it with\n> - * resources. The camera may be reconfigured multiple times until resources\n> - * are provided and the state progresses to Prepared.\n> - *\n> - * \\subsubsection Prepared\n> - * The camera has been configured and provided with resources and is ready to be\n> - * started. The application may free the camera's resources to get back to the\n> - * Configured state or start() it to progress to the Running state.\n> + * The camera has been configured and is ready to be started. The application\n\n\"is configured and ready to be started\" to be consistent with the other\nstates ?\n\nThese minor issues apart,\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> + * may release() the camera and to get back to the Available state or start()\n> + * it to progress to the Running state.\n>   *\n>   * \\subsubsection Running\n>   * The camera is running and ready to process requests queued by the\n>   * application. The camera remains in this state until it is stopped and moved\n> - * to the Prepared state.\n> + * to the Configured state.\n>   */\n>  \n>  /**\n> @@ -419,7 +407,6 @@ static const char *const camera_state_names[] = {\n>  \t\"Available\",\n>  \t\"Acquired\",\n>  \t\"Configured\",\n> -\t\"Prepared\",\n>  \t\"Running\",\n>  };\n>  \n> @@ -473,11 +460,11 @@ void Camera::disconnect()\n>  \n>  \t/*\n>  \t * If the camera was running when the hardware was removed force the\n> -\t * state to Prepared to allow applications to call freeBuffers() and\n> -\t * release() before deleting the camera.\n> +\t * state to Configured state to allow applications to free resources\n> +\t * and release() before deleting the camera.\n>  \t */\n>  \tif (state_ == CameraRunning)\n> -\t\tstate_ = CameraPrepared;\n> +\t\tstate_ = CameraConfigured;\n>  \n>  \tdisconnected_ = true;\n>  \tdisconnected.emit(this);\n> @@ -685,53 +672,6 @@ int Camera::configure(CameraConfiguration *config)\n>  \treturn 0;\n>  }\n>  \n> -/**\n> - * \\brief Allocate buffers for all configured streams\n> - *\n> - * This function affects the state of the camera, see \\ref camera_operation.\n> - *\n> - * \\return 0 on success or a negative error code otherwise\n> - * \\retval -ENODEV The camera has been disconnected from the system\n> - * \\retval -EACCES The camera is not in a state where buffers can be allocated\n> - * \\retval -EINVAL The configuration is not valid\n> - */\n> -int Camera::allocateBuffers()\n> -{\n> -\tif (disconnected_)\n> -\t\treturn -ENODEV;\n> -\n> -\tif (!stateIs(CameraConfigured))\n> -\t\treturn -EACCES;\n> -\n> -\tif (activeStreams_.empty()) {\n> -\t\tLOG(Camera, Error)\n> -\t\t\t<< \"Can't allocate buffers without streams\";\n> -\t\treturn -EINVAL;\n> -\t}\n> -\n> -\tstate_ = CameraPrepared;\n> -\n> -\treturn 0;\n> -}\n> -\n> -/**\n> - * \\brief Release all buffers from allocated pools in each stream\n> - *\n> - * This function affects the state of the camera, see \\ref camera_operation.\n> - *\n> - * \\return 0 on success or a negative error code otherwise\n> - * \\retval -EACCES The camera is not in a state where buffers can be freed\n> - */\n> -int Camera::freeBuffers()\n> -{\n> -\tif (!stateIs(CameraPrepared))\n> -\t\treturn -EACCES;\n> -\n> -\tstate_ = CameraConfigured;\n> -\n> -\treturn 0;\n> -}\n> -\n>  /**\n>   * \\brief Create a request object for the camera\n>   * \\param[in] cookie Opaque cookie for application use\n> @@ -747,14 +687,14 @@ int Camera::freeBuffers()\n>   * The ownership of the returned request is passed to the caller, which is\n>   * responsible for either queueing the request or deleting it.\n>   *\n> - * This function shall only be called when the camera is in the Prepared\n> + * This function shall only be called when the camera is in the Configured\n>   * or Running state, see \\ref camera_operation.\n>   *\n>   * \\return A pointer to the newly created request, or nullptr on error\n>   */\n>  Request *Camera::createRequest(uint64_t cookie)\n>  {\n> -\tif (disconnected_ || !stateBetween(CameraPrepared, CameraRunning))\n> +\tif (disconnected_ || !stateBetween(CameraConfigured, CameraRunning))\n>  \t\treturn nullptr;\n>  \n>  \treturn new Request(this, cookie);\n> @@ -828,9 +768,15 @@ int Camera::start()\n>  \tif (disconnected_)\n>  \t\treturn -ENODEV;\n>  \n> -\tif (!stateIs(CameraPrepared))\n> +\tif (!stateIs(CameraConfigured))\n>  \t\treturn -EACCES;\n>  \n> +\tif (activeStreams_.empty()) {\n> +\t\tLOG(Camera, Error)\n> +\t\t\t<< \"Can't start camera without streams\";\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n>  \tfor (Stream *stream : activeStreams_) {\n>  \t\tret = stream->start();\n>  \t\tif (ret < 0)\n> @@ -870,7 +816,7 @@ int Camera::stop()\n>  \n>  \tLOG(Camera, Debug) << \"Stopping capture\";\n>  \n> -\tstate_ = CameraPrepared;\n> +\tstate_ = CameraConfigured;\n>  \n>  \tpipe_->stop(this);\n>  \n> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\n> index 9650bd970f89aa41..38cf79deed37a089 100644\n> --- a/src/qcam/main_window.cpp\n> +++ b/src/qcam/main_window.cpp\n> @@ -172,13 +172,6 @@ int MainWindow::startCapture()\n>  \n>  \tadjustSize();\n>  \n> -\tret = camera_->allocateBuffers();\n> -\tif (ret) {\n> -\t\tstd::cerr << \"Failed to allocate buffers\"\n> -\t\t\t  << std::endl;\n> -\t\treturn ret;\n> -\t}\n> -\n>  \tret = allocator_->allocate(stream, cfg);\n>  \tif (ret < 0) {\n>  \t\tstd::cerr << \"Failed to allocate internal buffers\" << std::endl;\n> @@ -230,7 +223,6 @@ error:\n>  \tfor (Request *request : requests)\n>  \t\tdelete request;\n>  \n> -\tcamera_->freeBuffers();\n>  \treturn ret;\n>  }\n>  \n> @@ -243,7 +235,6 @@ void MainWindow::stopCapture()\n>  \tif (ret)\n>  \t\tstd::cout << \"Failed to stop capture\" << std::endl;\n>  \n> -\tcamera_->freeBuffers();\n>  \tisCapturing_ = false;\n>  \n>  \tconfig_.reset();\n> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> index c98afeb9597e21c2..9ae364d44d63b4d5 100644\n> --- a/test/camera/buffer_import.cpp\n> +++ b/test/camera/buffer_import.cpp\n> @@ -174,11 +174,6 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (camera_->allocateBuffers()) {\n> -\t\t\tcout << \"Failed to allocate buffers\" << endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n>  \t\tStream *stream = cfg.stream();\n>  \n>  \t\tBufferSource source;\n> @@ -246,11 +241,6 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (camera_->freeBuffers()) {\n> -\t\t\tcout << \"Failed to free buffers\" << endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n>  \t\treturn TestPass;\n>  \t}\n>  \n> diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp\n> index ee6d0a1bc1fa839d..545496fe2f7655ea 100644\n> --- a/test/camera/capture.cpp\n> +++ b/test/camera/capture.cpp\n> @@ -80,11 +80,6 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (camera_->allocateBuffers()) {\n> -\t\t\tcout << \"Failed to allocate buffers\" << endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n>  \t\tStream *stream = cfg.stream();\n>  \n>  \t\tBufferAllocator allocator(camera_);\n> @@ -152,11 +147,6 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (camera_->freeBuffers()) {\n> -\t\t\tcout << \"Failed to free buffers\" << endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n>  \t\treturn TestPass;\n>  \t}\n>  \n> diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp\n> index e9468d806f977a63..7d409ca20689568b 100644\n> --- a/test/camera/statemachine.cpp\n> +++ b/test/camera/statemachine.cpp\n> @@ -29,12 +29,6 @@ protected:\n>  \t\tif (camera_->configure(defconf_.get()) != -EACCES)\n>  \t\t\treturn TestFail;\n>  \n> -\t\tif (camera_->allocateBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->freeBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n>  \t\tif (camera_->createRequest())\n>  \t\t\treturn TestFail;\n>  \n> @@ -65,12 +59,6 @@ protected:\n>  \t\tif (camera_->acquire() != -EBUSY)\n>  \t\t\treturn TestFail;\n>  \n> -\t\tif (camera_->allocateBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->freeBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n>  \t\tif (camera_->createRequest())\n>  \t\t\treturn TestFail;\n>  \n> @@ -103,57 +91,6 @@ protected:\n>  \t\tif (camera_->acquire() != -EBUSY)\n>  \t\t\treturn TestFail;\n>  \n> -\t\tif (camera_->freeBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->createRequest())\n> -\t\t\treturn TestFail;\n> -\n> -\t\tRequest request(camera_.get());\n> -\t\tif (camera_->queueRequest(&request) != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->start() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->stop() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\t/* Test operations which should pass. */\n> -\t\tif (camera_->configure(defconf_.get()))\n> -\t\t\treturn TestFail;\n> -\n> -\t\t/* Test valid state transitions, end in Prepared state. */\n> -\t\tif (camera_->release())\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->acquire())\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->configure(defconf_.get()))\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->allocateBuffers())\n> -\t\t\treturn TestFail;\n> -\n> -\t\treturn TestPass;\n> -\t}\n> -\n> -\tint testPrepared()\n> -\t{\n> -\t\t/* Test operations which should fail. */\n> -\t\tif (camera_->acquire() != -EBUSY)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->release() != -EBUSY)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->configure(defconf_.get()) != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->allocateBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n>  \t\tRequest request1(camera_.get());\n>  \t\tif (camera_->queueRequest(&request1) != -EACCES)\n>  \t\t\treturn TestFail;\n> @@ -170,9 +107,6 @@ protected:\n>  \t\tdelete request2;\n>  \n>  \t\t/* Test valid state transitions, end in Running state. */\n> -\t\tif (camera_->freeBuffers())\n> -\t\t\treturn TestFail;\n> -\n>  \t\tif (camera_->release())\n>  \t\t\treturn TestFail;\n>  \n> @@ -182,9 +116,6 @@ protected:\n>  \t\tif (camera_->configure(defconf_.get()))\n>  \t\t\treturn TestFail;\n>  \n> -\t\tif (camera_->allocateBuffers())\n> -\t\t\treturn TestFail;\n> -\n>  \t\t/* Use internally allocated buffers. */\n>  \t\tallocator_ = new BufferAllocator(camera_);\n>  \t\tStream *stream = *camera_->streams().begin();\n> @@ -209,12 +140,6 @@ protected:\n>  \t\tif (camera_->configure(defconf_.get()) != -EACCES)\n>  \t\t\treturn TestFail;\n>  \n> -\t\tif (camera_->allocateBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n> -\t\tif (camera_->freeBuffers() != -EACCES)\n> -\t\t\treturn TestFail;\n> -\n>  \t\tif (camera_->start() != -EACCES)\n>  \t\t\treturn TestFail;\n>  \n> @@ -236,9 +161,6 @@ protected:\n>  \n>  \t\tdelete allocator_;\n>  \n> -\t\tif (camera_->freeBuffers())\n> -\t\t\treturn TestFail;\n> -\n>  \t\tif (camera_->release())\n>  \t\t\treturn TestFail;\n>  \n> @@ -276,11 +198,6 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (testPrepared() != TestPass) {\n> -\t\t\tcout << \"State machine in Prepared state failed\" << endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n>  \t\tif (testRuning() != TestPass) {\n>  \t\t\tcout << \"State machine in Running state failed\" << endl;\n>  \t\t\treturn TestFail;","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["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 B97DB601E4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 15 Dec 2019 10:12:45 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1F25C2D1;\n\tSun, 15 Dec 2019 10:12:45 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1576401165;\n\tbh=c4acuS6e27g8DAb/vinXStILabX9+ueJmKDU8s3cJWY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=vT0W2vwSnNCzuz/GisF987TvvsPuRBq7CUlunuVZiDTiPIK8V74v8JGMNN0G9ucKI\n\tjwp8x2B+TAIKAqIiKzExmWHleuVX6F3cbM5UqfmTVuhNWfWCk+1f6xxUOXsATi26u4\n\tvOGkYj8q6DhX8vhdJCbai2p5rPclghstNUTX/bjE=","Date":"Sun, 15 Dec 2019 11:12:35 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20191215091235.GA4889@pendragon.ideasonboard.com>","References":"<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>\n\t<20191126233620.1695316-31-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20191126233620.1695316-31-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 30/30] libcamera: camera: Remove the\n\tprepared state","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>","X-List-Received-Date":"Sun, 15 Dec 2019 09:12:45 -0000"}},{"id":3254,"web_url":"https://patchwork.libcamera.org/comment/3254/","msgid":"<20191215091814.GA5786@pendragon.ideasonboard.com>","date":"2019-12-15T09:18:14","subject":"Re: [libcamera-devel] [PATCH 30/30] libcamera: camera: Remove the\n\tprepared state","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nA couple of nother comments.\n\nOn Sun, Dec 15, 2019 at 11:12:35AM +0200, Laurent Pinchart wrote:\n> On Wed, Nov 27, 2019 at 12:36:20AM +0100, Niklas Söderlund wrote:\n> > With the FrameBuffer rework completed there is no reason to keep the\n> > camera prepared state around as buffer allocations are now decoupled\n> > from the camera state. Remove the camera state simplifying the API.\n> > \n> > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > ---\n> >  include/libcamera/camera.h    |   4 --\n> >  src/android/camera_device.cpp |  10 +---\n> >  src/cam/capture.cpp           |   8 ---\n> >  src/libcamera/camera.cpp      | 104 ++++++++--------------------------\n> >  src/qcam/main_window.cpp      |   9 ---\n> >  test/camera/buffer_import.cpp |  10 ----\n> >  test/camera/capture.cpp       |  10 ----\n> >  test/camera/statemachine.cpp  |  83 ---------------------------\n> >  8 files changed, 26 insertions(+), 212 deletions(-)\n> > \n> > diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h\n> > index 02d047b9649f53d0..9f542aab213c5d47 100644\n> > --- a/include/libcamera/camera.h\n> > +++ b/include/libcamera/camera.h\n> > @@ -90,9 +90,6 @@ public:\n> >  \tstd::unique_ptr<CameraConfiguration> generateConfiguration(const StreamRoles &roles);\n> >  \tint configure(CameraConfiguration *config);\n> >  \n> > -\tint allocateBuffers();\n> > -\tint freeBuffers();\n> > -\n> >  \tRequest *createRequest(uint64_t cookie = 0);\n> >  \tint queueRequest(Request *request);\n> >  \n> > @@ -104,7 +101,6 @@ private:\n> >  \t\tCameraAvailable,\n> >  \t\tCameraAcquired,\n> >  \t\tCameraConfigured,\n> > -\t\tCameraPrepared,\n> >  \t\tCameraRunning,\n> >  \t};\n> >  \n> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > index a6da658bec277933..34c6119228a9ac0e 100644\n> > --- a/src/android/camera_device.cpp\n> > +++ b/src/android/camera_device.cpp\n> > @@ -78,7 +78,6 @@ void CameraDevice::close()\n> >  {\n> >  \tcamera_->stop();\n> >  \n> \n> I think you can remove this blank line too.\n> \n> > -\tcamera_->freeBuffers();\n> >  \tcamera_->release();\n> >  \n> >  \trunning_ = false;\n> > @@ -690,16 +689,9 @@ void CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reque\n> >  \n> >  \t/* Start the camera if that's the first request we handle. */\n> >  \tif (!running_) {\n> > -\t\tint ret = camera_->allocateBuffers();\n> > -\t\tif (ret) {\n> > -\t\t\tLOG(HAL, Error) << \"Failed to allocate buffers\";\n> > -\t\t\treturn;\n> > -\t\t}\n> > -\n> > -\t\tret = camera_->start();\n> > +\t\tint ret = camera_->start();\n> >  \t\tif (ret) {\n> >  \t\t\tLOG(HAL, Error) << \"Failed to start camera\";\n> > -\t\t\tcamera_->freeBuffers();\n> >  \t\t\treturn;\n> >  \t\t}\n> >  \n> > diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp\n> > index 154e6e461ee2b96b..835943a7d2b82e79 100644\n> > --- a/src/cam/capture.cpp\n> > +++ b/src/cam/capture.cpp\n> > @@ -42,12 +42,6 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options)\n> >  \t\treturn ret;\n> >  \t}\n> >  \n> > -\tret = camera_->allocateBuffers();\n> > -\tif (ret) {\n> > -\t\tstd::cerr << \"Failed to allocate buffers\" << std::endl;\n> > -\t\treturn ret;\n> > -\t}\n> > -\n> >  \tcamera_->requestCompleted.connect(this, &Capture::requestComplete);\n> >  \n> >  \tif (options.isSet(OptFile)) {\n> > @@ -67,8 +61,6 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options)\n> >  \t\twriter_ = nullptr;\n> >  \t}\n> >  \n> > -\tcamera_->freeBuffers();\n> > -\n> >  \treturn ret;\n> >  }\n> >  \n> > diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp\n> > index 12878a1c2e6076d3..fca75040ad8b16e7 100644\n> > --- a/src/libcamera/camera.cpp\n> > +++ b/src/libcamera/camera.cpp\n> > @@ -274,15 +274,13 @@ std::size_t CameraConfiguration::size() const\n> >   * \\section camera_operation Operating the Camera\n> >   *\n> >   * An application needs to perform a sequence of operations on a camera before\n> > - * it is ready to process requests. The camera needs to be acquired, configured\n> > - * and resources allocated or imported to prepare the camera for capture. Once\n> > - * started the camera can process requests until it is stopped. When an\n> > - * application is done with a camera all resources allocated need to be freed\n> > - * and the camera released.\n> > + * it is ready to process requests. The camera needs to be acquired and\n> > + * configured to prepare the camera for capture. Once started the camera can\n> > + * process requests until it is stopped. When an application is done with a\n> > + * camera it needs to be released.\n> \n> \"it\" as ambiguous here as it could refer to the application or the\n> camera. I would write \"When an application is done with a camera, the\n> camera needs to be released.\".\n> \n> >   *\n> >   * An application may start and stop a camera multiple times as long as it is\n> > - * not released. The camera may also be reconfigured provided that all\n> > - * resources allocated are freed prior to the reconfiguration.\n> > + * not released. The camera may also be reconfigured.\n> >   *\n> >   * \\subsection Camera States\n> >   *\n> > @@ -296,7 +294,6 @@ std::size_t CameraConfiguration::size() const\n> >   *   node [shape = doublecircle ]; Available;\n> >   *   node [shape = circle ]; Acquired;\n> >   *   node [shape = circle ]; Configured;\n> > - *   node [shape = circle ]; Prepared;\n> >   *   node [shape = circle ]; Running;\n> >   *\n> >   *   Available -> Available [label = \"release()\"];\n> > @@ -306,14 +303,10 @@ std::size_t CameraConfiguration::size() const\n> >   *   Acquired -> Configured [label = \"configure()\"];\n> >   *\n> >   *   Configured -> Available [label = \"release()\"];\n> > - *   Configured -> Configured [label = \"configure()\"];\n> > - *   Configured -> Prepared [label = \"allocateBuffers()\"];\n> > + *   Configured -> Configured [label = \"configure(), createRequest()\"];\n> > + *   Configured -> Running [label = \"start()\"];\n> >   *\n> > - *   Prepared -> Configured [label = \"freeBuffers()\"];\n> > - *   Prepared -> Prepared [label = \"createRequest()\"];\n> > - *   Prepared -> Running [label = \"start()\"];\n> > - *\n> > - *   Running -> Prepared [label = \"stop()\"];\n> > + *   Running -> Configured [label = \"stop()\"];\n> >   *   Running -> Running [label = \"createRequest(), queueRequest()\"];\n> >   * }\n> >   * \\enddot\n> > @@ -329,19 +322,14 @@ std::size_t CameraConfiguration::size() const\n> >   * Configured state.\n> >   *\n> >   * \\subsubsection Configured\n> > - * The camera is configured and ready for the application to prepare it with\n> > - * resources. The camera may be reconfigured multiple times until resources\n> > - * are provided and the state progresses to Prepared.\n> > - *\n> > - * \\subsubsection Prepared\n> > - * The camera has been configured and provided with resources and is ready to be\n> > - * started. The application may free the camera's resources to get back to the\n> > - * Configured state or start() it to progress to the Running state.\n> > + * The camera has been configured and is ready to be started. The application\n> \n> \"is configured and ready to be started\" to be consistent with the other\n> states ?\n> \n> These minor issues apart,\n> \n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> > + * may release() the camera and to get back to the Available state or start()\n> > + * it to progress to the Running state.\n> >   *\n> >   * \\subsubsection Running\n> >   * The camera is running and ready to process requests queued by the\n> >   * application. The camera remains in this state until it is stopped and moved\n> > - * to the Prepared state.\n> > + * to the Configured state.\n> >   */\n> >  \n> >  /**\n> > @@ -419,7 +407,6 @@ static const char *const camera_state_names[] = {\n> >  \t\"Available\",\n> >  \t\"Acquired\",\n> >  \t\"Configured\",\n> > -\t\"Prepared\",\n> >  \t\"Running\",\n> >  };\n> >  \n> > @@ -473,11 +460,11 @@ void Camera::disconnect()\n\nThere's a todo item for this method stating\n\n * \\todo Update comment about Running state when importing buffers as well as\n * allocating them are supported.\n\nI'm not sure what it means. Is it still valid ?\n\n> >  \n> >  \t/*\n> >  \t * If the camera was running when the hardware was removed force the\n> > -\t * state to Prepared to allow applications to call freeBuffers() and\n> > -\t * release() before deleting the camera.\n> > +\t * state to Configured state to allow applications to free resources\n> > +\t * and release() before deleting the camera.\n\ns/release()/call release()/\n\nand are there any resources to be freed ?\n\n> >  \t */\n> >  \tif (state_ == CameraRunning)\n> > -\t\tstate_ = CameraPrepared;\n> > +\t\tstate_ = CameraConfigured;\n> >  \n> >  \tdisconnected_ = true;\n> >  \tdisconnected.emit(this);\n> > @@ -685,53 +672,6 @@ int Camera::configure(CameraConfiguration *config)\n> >  \treturn 0;\n> >  }\n> >  \n> > -/**\n> > - * \\brief Allocate buffers for all configured streams\n> > - *\n> > - * This function affects the state of the camera, see \\ref camera_operation.\n> > - *\n> > - * \\return 0 on success or a negative error code otherwise\n> > - * \\retval -ENODEV The camera has been disconnected from the system\n> > - * \\retval -EACCES The camera is not in a state where buffers can be allocated\n> > - * \\retval -EINVAL The configuration is not valid\n> > - */\n> > -int Camera::allocateBuffers()\n> > -{\n> > -\tif (disconnected_)\n> > -\t\treturn -ENODEV;\n> > -\n> > -\tif (!stateIs(CameraConfigured))\n> > -\t\treturn -EACCES;\n> > -\n> > -\tif (activeStreams_.empty()) {\n> > -\t\tLOG(Camera, Error)\n> > -\t\t\t<< \"Can't allocate buffers without streams\";\n> > -\t\treturn -EINVAL;\n> > -\t}\n> > -\n> > -\tstate_ = CameraPrepared;\n> > -\n> > -\treturn 0;\n> > -}\n> > -\n> > -/**\n> > - * \\brief Release all buffers from allocated pools in each stream\n> > - *\n> > - * This function affects the state of the camera, see \\ref camera_operation.\n> > - *\n> > - * \\return 0 on success or a negative error code otherwise\n> > - * \\retval -EACCES The camera is not in a state where buffers can be freed\n> > - */\n> > -int Camera::freeBuffers()\n> > -{\n> > -\tif (!stateIs(CameraPrepared))\n> > -\t\treturn -EACCES;\n> > -\n> > -\tstate_ = CameraConfigured;\n> > -\n> > -\treturn 0;\n> > -}\n> > -\n> >  /**\n> >   * \\brief Create a request object for the camera\n> >   * \\param[in] cookie Opaque cookie for application use\n> > @@ -747,14 +687,14 @@ int Camera::freeBuffers()\n> >   * The ownership of the returned request is passed to the caller, which is\n> >   * responsible for either queueing the request or deleting it.\n> >   *\n> > - * This function shall only be called when the camera is in the Prepared\n> > + * This function shall only be called when the camera is in the Configured\n> >   * or Running state, see \\ref camera_operation.\n> >   *\n> >   * \\return A pointer to the newly created request, or nullptr on error\n> >   */\n> >  Request *Camera::createRequest(uint64_t cookie)\n> >  {\n> > -\tif (disconnected_ || !stateBetween(CameraPrepared, CameraRunning))\n> > +\tif (disconnected_ || !stateBetween(CameraConfigured, CameraRunning))\n> >  \t\treturn nullptr;\n> >  \n> >  \treturn new Request(this, cookie);\n> > @@ -828,9 +768,15 @@ int Camera::start()\n> >  \tif (disconnected_)\n> >  \t\treturn -ENODEV;\n> >  \n> > -\tif (!stateIs(CameraPrepared))\n> > +\tif (!stateIs(CameraConfigured))\n> >  \t\treturn -EACCES;\n> >  \n> > +\tif (activeStreams_.empty()) {\n> > +\t\tLOG(Camera, Error)\n> > +\t\t\t<< \"Can't start camera without streams\";\n> > +\t\treturn -EINVAL;\n> > +\t}\n> > +\n> >  \tfor (Stream *stream : activeStreams_) {\n> >  \t\tret = stream->start();\n> >  \t\tif (ret < 0)\n> > @@ -870,7 +816,7 @@ int Camera::stop()\n> >  \n> >  \tLOG(Camera, Debug) << \"Stopping capture\";\n> >  \n> > -\tstate_ = CameraPrepared;\n> > +\tstate_ = CameraConfigured;\n> >  \n> >  \tpipe_->stop(this);\n> >  \n> > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\n> > index 9650bd970f89aa41..38cf79deed37a089 100644\n> > --- a/src/qcam/main_window.cpp\n> > +++ b/src/qcam/main_window.cpp\n> > @@ -172,13 +172,6 @@ int MainWindow::startCapture()\n> >  \n> >  \tadjustSize();\n> >  \n> > -\tret = camera_->allocateBuffers();\n> > -\tif (ret) {\n> > -\t\tstd::cerr << \"Failed to allocate buffers\"\n> > -\t\t\t  << std::endl;\n> > -\t\treturn ret;\n> > -\t}\n> > -\n> >  \tret = allocator_->allocate(stream, cfg);\n> >  \tif (ret < 0) {\n> >  \t\tstd::cerr << \"Failed to allocate internal buffers\" << std::endl;\n> > @@ -230,7 +223,6 @@ error:\n> >  \tfor (Request *request : requests)\n> >  \t\tdelete request;\n> >  \n> > -\tcamera_->freeBuffers();\n> >  \treturn ret;\n> >  }\n> >  \n> > @@ -243,7 +235,6 @@ void MainWindow::stopCapture()\n> >  \tif (ret)\n> >  \t\tstd::cout << \"Failed to stop capture\" << std::endl;\n> >  \n> > -\tcamera_->freeBuffers();\n> >  \tisCapturing_ = false;\n> >  \n> >  \tconfig_.reset();\n> > diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> > index c98afeb9597e21c2..9ae364d44d63b4d5 100644\n> > --- a/test/camera/buffer_import.cpp\n> > +++ b/test/camera/buffer_import.cpp\n> > @@ -174,11 +174,6 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >  \n> > -\t\tif (camera_->allocateBuffers()) {\n> > -\t\t\tcout << \"Failed to allocate buffers\" << endl;\n> > -\t\t\treturn TestFail;\n> > -\t\t}\n> > -\n> >  \t\tStream *stream = cfg.stream();\n> >  \n> >  \t\tBufferSource source;\n> > @@ -246,11 +241,6 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >  \n> > -\t\tif (camera_->freeBuffers()) {\n> > -\t\t\tcout << \"Failed to free buffers\" << endl;\n> > -\t\t\treturn TestFail;\n> > -\t\t}\n> > -\n> >  \t\treturn TestPass;\n> >  \t}\n> >  \n> > diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp\n> > index ee6d0a1bc1fa839d..545496fe2f7655ea 100644\n> > --- a/test/camera/capture.cpp\n> > +++ b/test/camera/capture.cpp\n> > @@ -80,11 +80,6 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >  \n> > -\t\tif (camera_->allocateBuffers()) {\n> > -\t\t\tcout << \"Failed to allocate buffers\" << endl;\n> > -\t\t\treturn TestFail;\n> > -\t\t}\n> > -\n> >  \t\tStream *stream = cfg.stream();\n> >  \n> >  \t\tBufferAllocator allocator(camera_);\n> > @@ -152,11 +147,6 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >  \n> > -\t\tif (camera_->freeBuffers()) {\n> > -\t\t\tcout << \"Failed to free buffers\" << endl;\n> > -\t\t\treturn TestFail;\n> > -\t\t}\n> > -\n> >  \t\treturn TestPass;\n> >  \t}\n> >  \n> > diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp\n> > index e9468d806f977a63..7d409ca20689568b 100644\n> > --- a/test/camera/statemachine.cpp\n> > +++ b/test/camera/statemachine.cpp\n> > @@ -29,12 +29,6 @@ protected:\n> >  \t\tif (camera_->configure(defconf_.get()) != -EACCES)\n> >  \t\t\treturn TestFail;\n> >  \n> > -\t\tif (camera_->allocateBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->freeBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tif (camera_->createRequest())\n> >  \t\t\treturn TestFail;\n> >  \n> > @@ -65,12 +59,6 @@ protected:\n> >  \t\tif (camera_->acquire() != -EBUSY)\n> >  \t\t\treturn TestFail;\n> >  \n> > -\t\tif (camera_->allocateBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->freeBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tif (camera_->createRequest())\n> >  \t\t\treturn TestFail;\n> >  \n> > @@ -103,57 +91,6 @@ protected:\n> >  \t\tif (camera_->acquire() != -EBUSY)\n> >  \t\t\treturn TestFail;\n> >  \n> > -\t\tif (camera_->freeBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->createRequest())\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tRequest request(camera_.get());\n> > -\t\tif (camera_->queueRequest(&request) != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->start() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->stop() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\t/* Test operations which should pass. */\n> > -\t\tif (camera_->configure(defconf_.get()))\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\t/* Test valid state transitions, end in Prepared state. */\n> > -\t\tif (camera_->release())\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->acquire())\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->configure(defconf_.get()))\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->allocateBuffers())\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\treturn TestPass;\n> > -\t}\n> > -\n> > -\tint testPrepared()\n> > -\t{\n> > -\t\t/* Test operations which should fail. */\n> > -\t\tif (camera_->acquire() != -EBUSY)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->release() != -EBUSY)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->configure(defconf_.get()) != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->allocateBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tRequest request1(camera_.get());\n> >  \t\tif (camera_->queueRequest(&request1) != -EACCES)\n> >  \t\t\treturn TestFail;\n> > @@ -170,9 +107,6 @@ protected:\n> >  \t\tdelete request2;\n> >  \n> >  \t\t/* Test valid state transitions, end in Running state. */\n> > -\t\tif (camera_->freeBuffers())\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tif (camera_->release())\n> >  \t\t\treturn TestFail;\n> >  \n> > @@ -182,9 +116,6 @@ protected:\n> >  \t\tif (camera_->configure(defconf_.get()))\n> >  \t\t\treturn TestFail;\n> >  \n> > -\t\tif (camera_->allocateBuffers())\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\t/* Use internally allocated buffers. */\n> >  \t\tallocator_ = new BufferAllocator(camera_);\n> >  \t\tStream *stream = *camera_->streams().begin();\n> > @@ -209,12 +140,6 @@ protected:\n> >  \t\tif (camera_->configure(defconf_.get()) != -EACCES)\n> >  \t\t\treturn TestFail;\n> >  \n> > -\t\tif (camera_->allocateBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> > -\t\tif (camera_->freeBuffers() != -EACCES)\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tif (camera_->start() != -EACCES)\n> >  \t\t\treturn TestFail;\n> >  \n> > @@ -236,9 +161,6 @@ protected:\n> >  \n> >  \t\tdelete allocator_;\n> >  \n> > -\t\tif (camera_->freeBuffers())\n> > -\t\t\treturn TestFail;\n> > -\n> >  \t\tif (camera_->release())\n> >  \t\t\treturn TestFail;\n> >  \n> > @@ -276,11 +198,6 @@ protected:\n> >  \t\t\treturn TestFail;\n> >  \t\t}\n> >  \n> > -\t\tif (testPrepared() != TestPass) {\n> > -\t\t\tcout << \"State machine in Prepared state failed\" << endl;\n> > -\t\t\treturn TestFail;\n> > -\t\t}\n> > -\n> >  \t\tif (testRuning() != TestPass) {\n> >  \t\t\tcout << \"State machine in Running state failed\" << endl;\n> >  \t\t\treturn TestFail;","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 04D99601E4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 15 Dec 2019 10:18:24 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 763A22D1;\n\tSun, 15 Dec 2019 10:18:23 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1576401503;\n\tbh=jSF4IE/euszVlmR3ejnXuF9n7jvKSt+G5lwDtPGU70Y=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=qXJ/sEfAdQBUaeWEqrg1sm1vvS+qC0rziI2faMX0asEQ+RBCsXDEtOd9GAsw4ECqJ\n\tX1KpFaLhP+CEiUd1AVe4bOnUAoC70ctdsfunTb6A9g0d87zZW9+5Hg2fx/VaAlfhvJ\n\t+XK9UIkS7ChJpzD61LYY8lv8KeA6rkrmquvJ+9Sg=","Date":"Sun, 15 Dec 2019 11:18:14 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20191215091814.GA5786@pendragon.ideasonboard.com>","References":"<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>\n\t<20191126233620.1695316-31-niklas.soderlund@ragnatech.se>\n\t<20191215091235.GA4889@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20191215091235.GA4889@pendragon.ideasonboard.com>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 30/30] libcamera: camera: Remove the\n\tprepared state","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>","X-List-Received-Date":"Sun, 15 Dec 2019 09:18:24 -0000"}}]