[libcamera-devel] [PATCH v4 8/8] android: Implement flush() camera operation

Hirokazu Honda hiroh at chromium.org
Fri May 28 09:37:42 CEST 2021


Hi Jacopo, thank you for the work.

On Fri, May 28, 2021 at 4:33 PM Niklas Söderlund <
niklas.soderlund at ragnatech.se> wrote:

> Hi Jacopo,
>
> Thanks for your work.
>
> On 2021-05-28 00:03:59 +0200, Jacopo Mondi wrote:
> > Implement the flush() camera operation in the CameraDevice class
> > and make it available to the camera framework by implementing the
> > operation wrapper in camera_ops.cpp.
> >
> > Introduce a new camera state State::Flushing to handle concurrent
> > flush() and process_capture_request() calls.
> >
> > As flush() can race with processCaptureRequest() protect it
> > by introducing a new State::Flushing state that
> > processCaptureRequest() inspects before queuing the Request to the
> > Camera. If flush() is in progress while processCaptureRequest() is
> > called, return the current Request immediately in error state. If
> > flush() has completed and a new call to processCaptureRequest() is
> > made just after, start the camera again before queuing the request.
> >
> > Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
>
> Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
>
>
Reviewed-by: Hirokazu Honda <hiroh at chromium.org>


> > ---
> >  src/android/camera_device.cpp | 74 ++++++++++++++++++++++++++++++++++-
> >  src/android/camera_device.h   |  3 ++
> >  src/android/camera_ops.cpp    |  8 +++-
> >  3 files changed, 83 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/android/camera_device.cpp
> b/src/android/camera_device.cpp
> > index a20c3eaa0ff6..6a8d4d4d5f76 100644
> > --- a/src/android/camera_device.cpp
> > +++ b/src/android/camera_device.cpp
> > @@ -797,6 +797,23 @@ void CameraDevice::close()
> >       camera_->release();
> >  }
> >
> > +void CameraDevice::flush()
> > +{
> > +     {
> > +             MutexLocker stateLock(stateMutex_);
> > +             if (state_ != State::Running)
> > +                     return;
> > +
> > +             state_ = State::Flushing;
> > +     }
> > +
> > +     worker_.stop();
> > +     camera_->stop();
> > +
> > +     MutexLocker stateLock(stateMutex_);
> > +     state_ = State::Stopped;
> > +}
> > +
> >  void CameraDevice::stop()
> >  {
> >       MutexLocker stateLock(stateMutex_);
> > @@ -1894,15 +1911,46 @@ int
> CameraDevice::processControls(Camera3RequestDescriptor *descriptor)
> >       return 0;
> >  }
> >
> > +void CameraDevice::abortRequest(camera3_capture_request_t *request)
> > +{
> > +     notifyError(request->frame_number, nullptr,
> CAMERA3_MSG_ERROR_REQUEST);
> > +
> > +     camera3_capture_result_t result = {};
> > +     result.num_output_buffers = request->num_output_buffers;
> > +     result.frame_number = request->frame_number;
> > +     result.partial_result = 0;
> > +
> > +     std::vector<camera3_stream_buffer_t>
> resultBuffers(result.num_output_buffers);
> > +     for (auto [i, buffer] : utils::enumerate(resultBuffers)) {
> > +             buffer = request->output_buffers[i];
> > +             buffer.release_fence =
> request->output_buffers[i].acquire_fence;
> > +             buffer.acquire_fence = -1;
> > +             buffer.status = CAMERA3_BUFFER_STATUS_ERROR;
> > +     }
> > +     result.output_buffers = resultBuffers.data();
> > +
> > +     callbacks_->process_capture_result(callbacks_, &result);
> > +}
> > +
> >  int CameraDevice::processCaptureRequest(camera3_capture_request_t
> *camera3Request)
> >  {
> >       if (!isValidRequest(camera3Request))
> >               return -EINVAL;
> >
> >       {
> > +             /*
> > +              * Start the camera if that's the first request we handle
> after
> > +              * a configuration or after a flush.
> > +              *
> > +              * If flush is in progress, return the pending request
> > +              * immediately in error state.
> > +              */
> >               MutexLocker stateLock(stateMutex_);
> > +             if (state_ == State::Flushing) {
> > +                     abortRequest(camera3Request);
> > +                     return 0;
> > +             }
> >
> > -             /* Start the camera if that's the first request we handle.
> */
> >               if (state_ == State::Stopped) {
> >                       worker_.start();
> >
> > @@ -2004,6 +2052,30 @@ int
> CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
> >       if (ret)
> >               return ret;
> >
> > +     /*
> > +      * Just before queuing the request, make sure flush() has not
> > +      * been called while this function was running. If flush is in
> progress
> > +      * abort the request. If flush has completed and has stopped the
> camera
> > +      * we have to re-start it to be able to process the request.
> > +      */
> > +     MutexLocker stateLock(stateMutex_);
> > +     if (state_ == State::Flushing) {
> > +             abortRequest(camera3Request);
> > +             return 0;
> > +     }
> > +
> > +     if (state_ == State::Stopped) {
> > +             worker_.start();
> > +
> > +             ret = camera_->start();
> > +             if (ret) {
> > +                     LOG(HAL, Error) << "Failed to start camera";
> > +                     return ret;
> > +             }
> > +
> > +             state_ = State::Running;
> > +     }
> > +
> >       worker_.queueRequest(descriptor.request_.get());
> >
> >       {
> > diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> > index c949fa509ca4..4aadb27c562c 100644
> > --- a/src/android/camera_device.h
> > +++ b/src/android/camera_device.h
> > @@ -43,6 +43,7 @@ public:
> >
> >       int open(const hw_module_t *hardwareModule);
> >       void close();
> > +     void flush();
> >
> >       unsigned int id() const { return id_; }
> >       camera3_device_t *camera3Device() { return &camera3Device_; }
> > @@ -92,6 +93,7 @@ private:
> >
> >       enum class State {
> >               Stopped,
> > +             Flushing,
> >               Running,
> >       };
> >
> > @@ -106,6 +108,7 @@ private:
> >       getRawResolutions(const libcamera::PixelFormat &pixelFormat);
> >
> >       libcamera::FrameBuffer *createFrameBuffer(const buffer_handle_t
> camera3buffer);
> > +     void abortRequest(camera3_capture_request_t *request);
> >       void notifyShutter(uint32_t frameNumber, uint64_t timestamp);
> >       void notifyError(uint32_t frameNumber, camera3_stream_t *stream,
> >                        camera3_error_msg_code code);
> > diff --git a/src/android/camera_ops.cpp b/src/android/camera_ops.cpp
> > index 696e80436821..8a3cfa175ff5 100644
> > --- a/src/android/camera_ops.cpp
> > +++ b/src/android/camera_ops.cpp
> > @@ -66,8 +66,14 @@ static void hal_dev_dump([[maybe_unused]] const
> struct camera3_device *dev,
> >  {
> >  }
> >
> > -static int hal_dev_flush([[maybe_unused]] const struct camera3_device
> *dev)
> > +static int hal_dev_flush(const struct camera3_device *dev)
> >  {
> > +     if (!dev)
> > +             return -EINVAL;
> > +
> > +     CameraDevice *camera = reinterpret_cast<CameraDevice *>(dev->priv);
> > +     camera->flush();
> > +
> >       return 0;
> >  }
> >
> > --
> > 2.31.1
> >
>
> --
> Regards,
> Niklas Söderlund
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20210528/181cf675/attachment.htm>


More information about the libcamera-devel mailing list