[libcamera-devel] [RFC 1/7] libcamera: pipelines: implement start and stop of a camera
Kieran Bingham
kieran.bingham at ideasonboard.com
Tue Feb 5 09:39:02 CET 2019
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 at 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
>
--
Regards
--
Kieran
More information about the libcamera-devel
mailing list