[libcamera-devel,RFC,1/7] libcamera: pipelines: implement start and stop of a camera

Message ID 20190205000702.15370-2-niklas.soderlund@ragnatech.se
State Superseded
Delegated to: Niklas Söderlund
Headers show
Series
  • libcamera: extend camera and pipeline to support requests
Related show

Commit Message

Niklas Söderlund Feb. 5, 2019, 12:06 a.m. UTC
The camera need methods to start and stop capturing once it have been
configured. Extend the pipeline API to provide this and implement stubs
in all pipeline handlers.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/libcamera/include/pipeline_handler.h |  3 +++
 src/libcamera/pipeline/ipu3/ipu3.cpp     | 14 ++++++++++++
 src/libcamera/pipeline/uvcvideo.cpp      | 14 ++++++++++++
 src/libcamera/pipeline/vimc.cpp          | 14 ++++++++++++
 src/libcamera/pipeline_handler.cpp       | 27 ++++++++++++++++++++++++
 5 files changed, 72 insertions(+)

Comments

Kieran Bingham Feb. 5, 2019, 8:39 a.m. UTC | #1
Hi Niklas,

Discussion points at the documentation of start() and stop(),

On 05/02/2019 01:06, Niklas Söderlund wrote:
> The camera need methods to start and stop capturing once it have been
> configured. Extend the pipeline API to provide this and implement stubs
> in all pipeline handlers.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> ---
>  src/libcamera/include/pipeline_handler.h |  3 +++
>  src/libcamera/pipeline/ipu3/ipu3.cpp     | 14 ++++++++++++
>  src/libcamera/pipeline/uvcvideo.cpp      | 14 ++++++++++++
>  src/libcamera/pipeline/vimc.cpp          | 14 ++++++++++++
>  src/libcamera/pipeline_handler.cpp       | 27 ++++++++++++++++++++++++
>  5 files changed, 72 insertions(+)
> 
> diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
> index b4321f0fa0f765be..4bfe45aaf78e34ab 100644
> --- a/src/libcamera/include/pipeline_handler.h
> +++ b/src/libcamera/include/pipeline_handler.h
> @@ -45,6 +45,9 @@ public:
>  	virtual int configureStreams(Camera *camera,
>  				     std::map<Stream *, StreamConfiguration> &config) = 0;
>  
> +	virtual int start(const Camera *camera) = 0;
> +	virtual void stop(const Camera *camera) = 0;
> +
>  	virtual bool match(DeviceEnumerator *enumerator) = 0;
>  
>  protected:
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index 7823bbb55d9bde16..3bf196051f2ebdbc 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -34,6 +34,9 @@ public:
>  	int configureStreams(Camera *camera,
>  			     std::map<Stream *, StreamConfiguration> &config) override;
>  
> +	int start(const Camera *camera) override;
> +	void stop(const Camera *camera) override;
> +
>  	bool match(DeviceEnumerator *enumerator);
>  
>  private:
> @@ -104,6 +107,17 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,
>  	return 0;
>  }
>  
> +int PipelineHandlerIPU3::start(const Camera *camera)
> +{
> +	LOG(IPU3, Error) << "TODO: start camera";
> +	return 0;
> +}
> +
> +void PipelineHandlerIPU3::stop(const Camera *camera)
> +{
> +	LOG(IPU3, Error) << "TODO: stop camera";
> +}
> +
>  bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
>  {
>  	DeviceMatch cio2_dm("ipu3-cio2");
> diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
> index ad4d45d0698519b6..e6a15c58a63cf76b 100644
> --- a/src/libcamera/pipeline/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo.cpp
> @@ -30,6 +30,9 @@ public:
>  	int configureStreams(Camera *camera,
>  			     std::map<Stream *, StreamConfiguration> &config) override;
>  
> +	int start(const Camera *camera) override;
> +	void stop(const Camera *camera) override;
> +
>  	bool match(DeviceEnumerator *enumerator);
>  
>  private:
> @@ -82,6 +85,17 @@ int PipelineHandlerUVC::configureStreams(Camera *camera,
>  	return 0;
>  }
>  
> +int PipelineHandlerUVC::start(const Camera *camera)
> +{
> +	LOG(UVC, Error) << "TODO: start camera";
> +	return 0;
> +}
> +
> +void PipelineHandlerUVC::stop(const Camera *camera)
> +{
> +	LOG(UVC, Error) << "TODO: stop camera";
> +}
> +
>  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>  {
>  	DeviceMatch dm("uvcvideo");
> diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
> index 900477e257232b70..11eca0cd4d9a6e0c 100644
> --- a/src/libcamera/pipeline/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc.cpp
> @@ -30,6 +30,9 @@ public:
>  	int configureStreams(Camera *camera,
>  			     std::map<Stream *, StreamConfiguration> &config) override;
>  
> +	int start(const Camera *camera) override;
> +	void stop(const Camera *camera) override;
> +
>  	bool match(DeviceEnumerator *enumerator);
>  
>  private:
> @@ -77,6 +80,17 @@ int PipeHandlerVimc::configureStreams(Camera *camera,
>  	return 0;
>  }
>  
> +int PipeHandlerVimc::start(const Camera *camera)
> +{
> +	LOG(VIMC, Error) << "TODO: start camera";
> +	return 0;
> +}
> +
> +void PipeHandlerVimc::stop(const Camera *camera)
> +{
> +	LOG(VIMC, Error) << "TODO: stop camera";
> +}
> +
>  bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
>  {
>  	DeviceMatch dm("vimc");
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 3a560e10c442717f..fa5f780cea34fc8f 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -109,6 +109,33 @@ PipelineHandler::~PipelineHandler()
>   * \return 0 on success or a negative error code on error.
>   */
>  
> +/**
> + * \fn PipelineHandler::start()
> + * \brief Start capturing from a group of streams
> + * \param[in] camera The camera to start
> + *
> + * Start the group of streams that have been configured for capture by
> + * \a configureStreams().

Minor:

Aha - so looking at the doxygen manual, \a is not what I thought. It
emphasises the next word. It's not required for the linking. But that's
fine I don't think it hurts to highlight the configureStreams(), but it
might be a mis-use of \a command.

	http://www.doxygen.nl/manual/commands.html#cmda

^ This is a discussion point not a rejection of the \a :)


>                             The intended caller of this interface is
> + * the Camera class which will in turn will receive the call from the
> + * application to indicate that it's done configuring the streams
> + * and are ready to capture.
> + *

The intended caller? Or the only caller?

I don't think anyone else would manage the pipeline (unless we have
pipelines in pipelines ... but lets not go there).



> + * \return 0 on success or a negative error code on error.
> + */
> +
> +/**
> + * \fn PipelineHandler::stop()
> + * \brief Stop capturing from all running streams
> + * \param[in] camera The camera to stop
> + *
> + * Stop processing requests, finish processing all already queued requests
> + * and once all buffers on all streams have been dequeued stop capturing
> + * from all running streams. Finish processing of queued requests do not
> + * necessarily involve processing them by the capture hardware but notifying
> + * the application that a queued request was not processed due to the fact
> + * that the camera was stopped before they could be processed.

Some questions on stop():

Will we expect stop() to be a blocking call (perhaps with a timeout?) if
we want it to make sure all buffers and requests are stopped?

Or should this just be somewhat asynchronous - making sure that any
active processing finishes as soon as possible and that nothing new is
queued?

Should the stop function return a potential error if there is an issue
stopping the stream?

I would expect most of the time a stop is part of a tear down, but
perhaps there will be times we want to assert a clean shutdown has happened.



> + */
> +
>  /**
>   * \fn PipelineHandler::match(DeviceEnumerator *enumerator)
>   * \brief Match media devices and create camera instances
>

Patch

diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
index b4321f0fa0f765be..4bfe45aaf78e34ab 100644
--- a/src/libcamera/include/pipeline_handler.h
+++ b/src/libcamera/include/pipeline_handler.h
@@ -45,6 +45,9 @@  public:
 	virtual int configureStreams(Camera *camera,
 				     std::map<Stream *, StreamConfiguration> &config) = 0;
 
+	virtual int start(const Camera *camera) = 0;
+	virtual void stop(const Camera *camera) = 0;
+
 	virtual bool match(DeviceEnumerator *enumerator) = 0;
 
 protected:
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 7823bbb55d9bde16..3bf196051f2ebdbc 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -34,6 +34,9 @@  public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -104,6 +107,17 @@  int PipelineHandlerIPU3::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipelineHandlerIPU3::start(const Camera *camera)
+{
+	LOG(IPU3, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipelineHandlerIPU3::stop(const Camera *camera)
+{
+	LOG(IPU3, Error) << "TODO: stop camera";
+}
+
 bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch cio2_dm("ipu3-cio2");
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index ad4d45d0698519b6..e6a15c58a63cf76b 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -30,6 +30,9 @@  public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -82,6 +85,17 @@  int PipelineHandlerUVC::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipelineHandlerUVC::start(const Camera *camera)
+{
+	LOG(UVC, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipelineHandlerUVC::stop(const Camera *camera)
+{
+	LOG(UVC, Error) << "TODO: stop camera";
+}
+
 bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("uvcvideo");
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 900477e257232b70..11eca0cd4d9a6e0c 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -30,6 +30,9 @@  public:
 	int configureStreams(Camera *camera,
 			     std::map<Stream *, StreamConfiguration> &config) override;
 
+	int start(const Camera *camera) override;
+	void stop(const Camera *camera) override;
+
 	bool match(DeviceEnumerator *enumerator);
 
 private:
@@ -77,6 +80,17 @@  int PipeHandlerVimc::configureStreams(Camera *camera,
 	return 0;
 }
 
+int PipeHandlerVimc::start(const Camera *camera)
+{
+	LOG(VIMC, Error) << "TODO: start camera";
+	return 0;
+}
+
+void PipeHandlerVimc::stop(const Camera *camera)
+{
+	LOG(VIMC, Error) << "TODO: stop camera";
+}
+
 bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("vimc");
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index 3a560e10c442717f..fa5f780cea34fc8f 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -109,6 +109,33 @@  PipelineHandler::~PipelineHandler()
  * \return 0 on success or a negative error code on error.
  */
 
+/**
+ * \fn PipelineHandler::start()
+ * \brief Start capturing from a group of streams
+ * \param[in] camera The camera to start
+ *
+ * Start the group of streams that have been configured for capture by
+ * \a configureStreams(). The intended caller of this interface is
+ * the Camera class which will in turn will receive the call from the
+ * application to indicate that it's done configuring the streams
+ * and are ready to capture.
+ *
+ * \return 0 on success or a negative error code on error.
+ */
+
+/**
+ * \fn PipelineHandler::stop()
+ * \brief Stop capturing from all running streams
+ * \param[in] camera The camera to stop
+ *
+ * Stop processing requests, finish processing all already queued requests
+ * and once all buffers on all streams have been dequeued stop capturing
+ * from all running streams. Finish processing of queued requests do not
+ * necessarily involve processing them by the capture hardware but notifying
+ * the application that a queued request was not processed due to the fact
+ * that the camera was stopped before they could be processed.
+ */
+
 /**
  * \fn PipelineHandler::match(DeviceEnumerator *enumerator)
  * \brief Match media devices and create camera instances