Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5eca7d6 authored by Jan Sebechlebsky's avatar Jan Sebechlebsky Committed by Ján Sebechlebský
Browse files

Respect max fps if specified in the request.

Sleep for appropriate amount of time before acquiring new image
from Surface in case acquiring image imediatelly would exceed max fps
specified by the request.

Bug: 338251124
Test: atest CtsVirtualDevicesCameraCtsTestCases:android.hardware.camera2.cts.CaptureRequestTest#testNoiseReductionModeControl[1]
Change-Id: I1ac504f05cef044b81a2531074e1bedd77412805
parent 7b9d4bb4
Loading
Loading
Loading
Loading
+31 −10
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
 * limitations under the License.
 */

#include "hardware/gralloc.h"
#define LOG_TAG "VirtualCameraRenderThread"
#include "VirtualCameraRenderThread.h"

@@ -45,6 +44,7 @@
#include "android-base/thread_annotations.h"
#include "android/binder_auto_utils.h"
#include "android/hardware_buffer.h"
#include "hardware/gralloc.h"
#include "system/camera_metadata.h"
#include "ui/GraphicBuffer.h"
#include "ui/Rect.h"
@@ -422,9 +422,38 @@ void VirtualCameraRenderThread::threadLoop() {

void VirtualCameraRenderThread::processCaptureRequest(
    const ProcessCaptureRequestTask& request) {
  const std::chrono::nanoseconds timestamp =
  if (mTestMode) {
    // In test mode let's just render something to the Surface ourselves.
    renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(),
                              request.getFrameNumber());
  }

  std::chrono::nanoseconds timestamp =
      std::chrono::duration_cast<std::chrono::nanoseconds>(
          std::chrono::steady_clock::now().time_since_epoch());
  std::chrono::nanoseconds lastAcquisitionTimestamp(
      mLastAcquisitionTimestampNanoseconds.exchange(timestamp.count(),
                                                    std::memory_order_relaxed));

  if (request.getRequestSettings().fpsRange) {
    const int maxFps =
        std::min(1, request.getRequestSettings().fpsRange->maxFps);
    const std::chrono::nanoseconds minFrameDuration(
        static_cast<uint64_t>(1e9 / maxFps));
    std::chrono::nanoseconds frameDuration =
        timestamp - lastAcquisitionTimestamp;
    if (frameDuration < minFrameDuration) {
      // We're too fast for the configured maxFps, let's wait a bit.
      std::this_thread::sleep_for(minFrameDuration - frameDuration);
      timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
          std::chrono::steady_clock::now().time_since_epoch());
      mLastAcquisitionTimestampNanoseconds.store(timestamp.count(),
                                                 std::memory_order_relaxed);
    }
  }

  // Acquire new (most recent) image from the Surface.
  mEglSurfaceTexture->updateTexture();

  CaptureResult captureResult;
  captureResult.fmqResultSize = 0;
@@ -439,14 +468,6 @@ void VirtualCameraRenderThread::processCaptureRequest(
  const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers();
  captureResult.outputBuffers.resize(buffers.size());

  if (mTestMode) {
    // In test mode let's just render something to the Surface ourselves.
    renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(),
                              request.getFrameNumber());
  }

  mEglSurfaceTexture->updateTexture();

  for (int i = 0; i < buffers.size(); ++i) {
    const CaptureRequestBuffer& reqBuffer = buffers[i];
    StreamBuffer& resBuffer = captureResult.outputBuffers[i];
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H

#include <atomic>
#include <cstdint>
#include <deque>
#include <future>
@@ -195,6 +196,9 @@ class VirtualCameraRenderThread {
  std::condition_variable mCondVar;
  volatile bool mPendingExit GUARDED_BY(mLock);

  // Acquisition timestamp of last frame.
  std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;

  // EGL helpers - constructed and accessed only from rendering thread.
  std::unique_ptr<EglDisplayContext> mEglDisplayContext;
  std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram;