[libcamera-devel] [PATCH] android: Implement flush()

Hirokazu Honda hiroh at chromium.org
Thu Apr 8 11:17:00 CEST 2021


Thanks Jacopo for comments,
You're right. I missed the description. I will fix it.

On Tue, Apr 6, 2021 at 10:23 PM Jacopo Mondi <jacopo at jmondi.org> wrote:
>
> Hi Hiro,
>
> On Tue, Apr 06, 2021 at 06:13:34PM +0900, Hirokazu Honda wrote:
> > This implements camera3_device_ops::flush().
> >
>
> Is this enough ? reading the flush() operation documentation in
> camera3.h it seems it can be called concurrently to
> process_capture_request() and requests yet to be queued shall be
> returned immediately. Should that be handled as well ?
>
> > Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> > ---
> >  src/android/camera_device.cpp | 48 +++++++++++++++++++++++++++++++----
> >  src/android/camera_device.h   |  3 +++
> >  src/android/camera_ops.cpp    |  3 ++-
> >  3 files changed, 48 insertions(+), 6 deletions(-)
> >
> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> > index 4a3f6f8e..5a56fe4b 100644
> > --- a/src/android/camera_device.cpp
> > +++ b/src/android/camera_device.cpp
> > @@ -2029,20 +2029,22 @@ void CameraDevice::requestComplete(Request *request)
> >       camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;
> >       std::unique_ptr<CameraMetadata> resultMetadata;
> >
> > -     decltype(descriptors_)::node_type node;
> > +     Camera3RequestDescriptor descriptor;
> >       {
> >               std::scoped_lock<std::mutex> lock(mutex_);
> >               auto it = descriptors_.find(request->cookie());
> >               if (it == descriptors_.end()) {
> >                       LOG(HAL, Fatal)
> >                               << "Unknown request: " << request->cookie();
> > -                     status = CAMERA3_BUFFER_STATUS_ERROR;
> >                       return;
> >               }
> >
> > -             node = descriptors_.extract(it);
> > +             descriptor = std::move(it->second);
> > +             /* Restore frameNumber_ because it is used in the case of flush
> > +              * timeout case.
> > +              */
> > +             it->second.frameNumber_ = descriptor.frameNumber_;
>
> Is accessing it->second after having moved it valid ? also, aren't
> the lhs and rhs referring to the same variable ?
>
> >       }
> > -     Camera3RequestDescriptor &descriptor = node.mapped();
> >
> >       if (request->status() != Request::RequestComplete) {
> >               LOG(HAL, Error) << "Request not successfully completed: "
> > @@ -2122,7 +2124,43 @@ void CameraDevice::requestComplete(Request *request)
> >                           descriptor.buffers_[0].stream);
> >       }
> >
> > -     callbacks_->process_capture_result(callbacks_, &captureResult);
> > +     {
> > +             std::scoped_lock<std::mutex> lock(mutex_);
> > +             if (descriptors_.erase(request->cookie()) == 0) {
> > +                     // flush() cleans up the descriptor due to time out
> > +                     // during a post processing.
>
> No C++ comments please
>
> > +                     return;
> > +             }
> > +             callbacks_->process_capture_result(callbacks_, &captureResult);
> > +             conditionVariable_.notify_one();
>
> aren't this function and flush() being run in the same thread ? Won't
> this contend the mutex ?
>
> To be honest I would have expected flush to stop the libcamera::Camera
> to have all requests in-flight be immediately be completed with
> errors. As said flush also prevents calls to
> process_capture_request() to be queued if flush is called concurrently
> (which makes me think my assumption on the flush calls happening on the same
> thread to be wrong).
>
> Another question is how to interrupt post-processing to happen once it
> will be moved to a separate thread. If flush() times out and delete
> the descriptor, won't post-processor then tries to access a non-valid
> memory address ?
>
> Thanks
>   j
>
> > +     }
> > +}
> > +
> > +int CameraDevice::flush()
> > +{
> > +     std::unique_lock<std::mutex> lock(mutex_);
> > +     /* flush() should return in less than one second. Sets the timeout to 900ms. */
> > +     auto flushTimeout =
> > +             std::chrono::system_clock::now() + std::chrono::milliseconds(900);
> > +     bool completeAllRequests = conditionVariable_.wait_until(
> > +             lock, flushTimeout, [this]() { return descriptors_.empty(); });
> > +
> > +     if (!completeAllRequests) {
> > +             for (auto &node : descriptors_) {
> > +                     auto &descriptor = node.second;
> > +                     camera3_capture_result_t captureResult{};
> > +                     captureResult.frame_number = descriptor.frameNumber_;
> > +                     for (camera3_stream_buffer_t &buffer : descriptor.buffers_) {
> > +                             buffer.acquire_fence = -1;
> > +                             buffer.release_fence = -1;
> > +                             buffer.status = CAMERA3_BUFFER_STATUS_ERROR;
> > +                     }
> > +                     callbacks_->process_capture_result(callbacks_, &captureResult);
> > +             }
> > +             descriptors_.clear();
> > +     }
> > +
> > +     return 0;
> >  }
> >
> >  std::string CameraDevice::logPrefix() const
> > diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> > index c63e8e21..dd5336ee 100644
> > --- a/src/android/camera_device.h
> > +++ b/src/android/camera_device.h
> > @@ -7,6 +7,7 @@
> >  #ifndef __ANDROID_CAMERA_DEVICE_H__
> >  #define __ANDROID_CAMERA_DEVICE_H__
> >
> > +#include <condition_variable>
> >  #include <map>
> >  #include <memory>
> >  #include <mutex>
> > @@ -62,6 +63,7 @@ public:
> >       int configureStreams(camera3_stream_configuration_t *stream_list);
> >       int processCaptureRequest(camera3_capture_request_t *request);
> >       void requestComplete(libcamera::Request *request);
> > +     int flush();
> >
> >  protected:
> >       std::string logPrefix() const override;
> > @@ -128,6 +130,7 @@ private:
> >       std::vector<CameraStream> streams_;
> >
> >       std::mutex mutex_; /* Protect descriptors_ */
> > +     std::condition_variable conditionVariable_;
> >       std::map<uint64_t, Camera3RequestDescriptor> descriptors_;
> >
> >       std::string maker_;
> > diff --git a/src/android/camera_ops.cpp b/src/android/camera_ops.cpp
> > index 696e8043..1b73af13 100644
> > --- a/src/android/camera_ops.cpp
> > +++ b/src/android/camera_ops.cpp
> > @@ -68,7 +68,8 @@ static void hal_dev_dump([[maybe_unused]] const struct camera3_device *dev,
> >
> >  static int hal_dev_flush([[maybe_unused]] const struct camera3_device *dev)
> >  {
> > -     return 0;
> > +     CameraDevice *camera = reinterpret_cast<CameraDevice *>(dev->priv);
> > +     return camera->flush();
> >  }
> >
> >  int hal_dev_close(hw_device_t *hw_device)
> > --
> > 2.31.0.208.g409f899ff0-goog
> >
> > _______________________________________________
> > libcamera-devel mailing list
> > libcamera-devel at lists.libcamera.org
> > https://lists.libcamera.org/listinfo/libcamera-devel


More information about the libcamera-devel mailing list