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

Commit 550634de authored by Vadim Caen's avatar Vadim Caen
Browse files

Better separation of concern for the render thread

Move struct and functions into their own file to clean up the
VirtualCameraRenderThread.cc file.

Test: Existing
Flag: EXEMPT refactor
Bug: 341083465
Change-Id: I86894ecbc69e8f6203a5d029629a290851b69f47
parent b0b97d52
Loading
Loading
Loading
Loading
+1 −8
Original line number Original line Diff line number Diff line
@@ -65,14 +65,7 @@ cc_library_static {
cc_library_static {
cc_library_static {
    name: "libvirtualcamera",
    name: "libvirtualcamera",
    srcs: [
    srcs: [
        "VirtualCameraProvider.cc",
        "*.cc",
        "VirtualCameraDevice.cc",
        "VirtualCameraSession.cc",
        "VirtualCameraStream.cc",
        "VirtualCameraService.cc",
        "VirtualCameraSessionContext.cc",
        "VirtualCameraTestInstance.cc",
        "VirtualCameraRenderThread.cc",
    ],
    ],
    defaults: [
    defaults: [
        "libvirtualcamera_defaults",
        "libvirtualcamera_defaults",
+59 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H
#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H

#include "VirtualCameraDevice.h"

namespace android {
namespace companion {
namespace virtualcamera {

// Struct used to pass request settings in the different part of
// the virtual camera system.
struct RequestSettings {
  // JPEG_QUALITY metadata
  int jpegQuality = VirtualCameraDevice::kDefaultJpegQuality;

  // JPEG_ORIENTATION metadata
  int jpegOrientation = VirtualCameraDevice::kDefaultJpegOrientation;

  // JPEG_THUMBNAIL_SIZE metadata
  Resolution thumbnailResolution = Resolution(0, 0);

  // JPEG_THUMBNAIL_QUALITY metadata
  int thumbnailJpegQuality = VirtualCameraDevice::kDefaultJpegQuality;

  // ANDROID_CONTROL_AE_TARGET_FPS_RANGE metadata
  std::optional<FpsRange> fpsRange;

  // CONTROL_CAPTURE_INTENT metadata
  camera_metadata_enum_android_control_capture_intent_t captureIntent =
      VirtualCameraDevice::kDefaultCaptureIntent;

  // JPEG_GPS_LOCATION metadata
  std::optional<GpsCoordinates> gpsCoordinates;

  // CONTROL_AE_PRECAPTURE_TRIGGER metadata
  std::optional<camera_metadata_enum_android_control_ae_precapture_trigger>
      aePrecaptureTrigger;
};

}  // namespace virtualcamera
}  // namespace companion
}  // namespace android

#endif  // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTUREREQUEST_H
 No newline at end of file
+119 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "VirtualCameraCaptureResult.h"

#include <cstdint>

#include "VirtualCameraCaptureRequest.h"
#include "aidl/android/hardware/camera/device/CameraMetadata.h"
#include "util/MetadataUtil.h"

namespace android {
namespace companion {
namespace virtualcamera {

using ::aidl::android::hardware::camera::device::CameraMetadata;
namespace {
// See REQUEST_PIPELINE_DEPTH in CaptureResult.java.
// This roughly corresponds to frame latency, we set to
// documented minimum of 2.
static constexpr uint8_t kPipelineDepth = 2;

}  // namespace

CameraMetadata createCaptureResultMetadata(
    const std::chrono::nanoseconds timestamp,
    const RequestSettings& requestSettings,
    const Resolution reportedSensorSize) {
  // All of the keys used in the response needs to be referenced in
  // availableResultKeys in CameraCharacteristics (see initCameraCharacteristics
  // in VirtualCameraDevice.cc).
  MetadataBuilder builder =
      MetadataBuilder()
          .setAberrationCorrectionMode(
              ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF)
          .setControlAeAvailableAntibandingModes(
              {ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF})
          .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF)
          .setControlAeExposureCompensation(0)
          .setControlAeLockAvailable(false)
          .setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF)
          .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
          .setControlAePrecaptureTrigger(
              // Limited devices are expected to have precapture ae enabled and
              // respond to cancellation request. Since we don't actuall support
              // AE at all, let's just respect the cancellation expectation in
              // case it's requested
              requestSettings.aePrecaptureTrigger ==
                      ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
                  ? ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
                  : ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
          .setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE)
          .setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF)
          .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
          .setControlAfState(ANDROID_CONTROL_AF_STATE_INACTIVE)
          .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
          .setControlAwbLock(ANDROID_CONTROL_AWB_LOCK_OFF)
          .setControlAwbState(ANDROID_CONTROL_AWB_STATE_INACTIVE)
          .setControlCaptureIntent(requestSettings.captureIntent)
          .setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF)
          .setControlMode(ANDROID_CONTROL_MODE_AUTO)
          .setControlSceneMode(ANDROID_CONTROL_SCENE_MODE_DISABLED)
          .setControlVideoStabilizationMode(
              ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF)
          .setCropRegion(0, 0, reportedSensorSize.width,
                         reportedSensorSize.height)
          .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF)
          .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE)
          .setFlashMode(ANDROID_FLASH_MODE_OFF)
          .setFocalLength(VirtualCameraDevice::kFocalLength)
          .setJpegQuality(requestSettings.jpegQuality)
          .setJpegOrientation(requestSettings.jpegOrientation)
          .setJpegThumbnailSize(requestSettings.thumbnailResolution.width,
                                requestSettings.thumbnailResolution.height)
          .setJpegThumbnailQuality(requestSettings.thumbnailJpegQuality)
          .setLensOpticalStabilizationMode(
              ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF)
          .setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF)
          .setPipelineDepth(kPipelineDepth)
          .setSensorTimestamp(timestamp)
          .setStatisticsHotPixelMapMode(
              ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF)
          .setStatisticsLensShadingMapMode(
              ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF)
          .setStatisticsSceneFlicker(ANDROID_STATISTICS_SCENE_FLICKER_NONE);

  if (requestSettings.fpsRange.has_value()) {
    builder.setControlAeTargetFpsRange(requestSettings.fpsRange.value());
  }

  if (requestSettings.gpsCoordinates.has_value()) {
    const GpsCoordinates& coordinates = requestSettings.gpsCoordinates.value();
    builder.setJpegGpsCoordinates(coordinates);
  }

  std::unique_ptr<CameraMetadata> metadata = builder.build();

  if (metadata == nullptr) {
    ALOGE("%s: Failed to build capture result metadata", __func__);
    return CameraMetadata();
  }
  return std::move(*metadata);
}

}  // namespace virtualcamera
}  // namespace companion
}  // namespace android
 No newline at end of file
+53 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTURERESULT_H
#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTURERESULT_H

#include <chrono>
#include <cstdint>
#include <cstring>
#include <future>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>
#include <vector>

#include "Exif.h"
#include "GLES/gl.h"
#include "VirtualCameraCaptureRequest.h"
#include "VirtualCameraDevice.h"
#include "VirtualCameraRenderThread.h"
#include "VirtualCameraSessionContext.h"
#include "aidl/android/hardware/camera/device/CameraMetadata.h"

namespace android {
namespace companion {
namespace virtualcamera {

// Construct the Metadata for the Capture result based on the request
// settings, timestamp and reported sensore size
::aidl::android::hardware::camera::device::CameraMetadata
createCaptureResultMetadata(std::chrono::nanoseconds timestamp,
                            const RequestSettings& requestSettings,
                            Resolution reportedSensorSize);

}  // namespace virtualcamera
}  // namespace companion
}  // namespace android

#endif  // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERACAPTURERESULT_H
 No newline at end of file
+1 −85
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@


#include "Exif.h"
#include "Exif.h"
#include "GLES/gl.h"
#include "GLES/gl.h"
#include "VirtualCameraCaptureResult.h"
#include "VirtualCameraDevice.h"
#include "VirtualCameraDevice.h"
#include "VirtualCameraSessionContext.h"
#include "VirtualCameraSessionContext.h"
#include "aidl/android/hardware/camera/common/Status.h"
#include "aidl/android/hardware/camera/common/Status.h"
@@ -92,95 +93,10 @@ using namespace std::chrono_literals;


static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms;
static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms;


// See REQUEST_PIPELINE_DEPTH in CaptureResult.java.
// This roughly corresponds to frame latency, we set to
// documented minimum of 2.
static constexpr uint8_t kPipelineDepth = 2;

static constexpr size_t kJpegThumbnailBufferSize = 32 * 1024;  // 32 KiB
static constexpr size_t kJpegThumbnailBufferSize = 32 * 1024;  // 32 KiB


static constexpr UpdateTextureTask kUpdateTextureTask;
static constexpr UpdateTextureTask kUpdateTextureTask;


CameraMetadata createCaptureResultMetadata(
    const std::chrono::nanoseconds timestamp,
    const RequestSettings& requestSettings,
    const Resolution reportedSensorSize) {
  // All of the keys used in the response needs to be referenced in
  // availableResultKeys in CameraCharacteristics (see initCameraCharacteristics
  // in VirtualCameraDevice.cc).
  MetadataBuilder builder =
      MetadataBuilder()
          .setAberrationCorrectionMode(
              ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF)
          .setControlAeAvailableAntibandingModes(
              {ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF})
          .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF)
          .setControlAeExposureCompensation(0)
          .setControlAeLockAvailable(false)
          .setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF)
          .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
          .setControlAePrecaptureTrigger(
              // Limited devices are expected to have precapture ae enabled and
              // respond to cancellation request. Since we don't actuall support
              // AE at all, let's just respect the cancellation expectation in
              // case it's requested
              requestSettings.aePrecaptureTrigger ==
                      ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
                  ? ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
                  : ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
          .setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE)
          .setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF)
          .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
          .setControlAfState(ANDROID_CONTROL_AF_STATE_INACTIVE)
          .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
          .setControlAwbLock(ANDROID_CONTROL_AWB_LOCK_OFF)
          .setControlAwbState(ANDROID_CONTROL_AWB_STATE_INACTIVE)
          .setControlCaptureIntent(requestSettings.captureIntent)
          .setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF)
          .setControlMode(ANDROID_CONTROL_MODE_AUTO)
          .setControlSceneMode(ANDROID_CONTROL_SCENE_MODE_DISABLED)
          .setControlVideoStabilizationMode(
              ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF)
          .setCropRegion(0, 0, reportedSensorSize.width,
                         reportedSensorSize.height)
          .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF)
          .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE)
          .setFlashMode(ANDROID_FLASH_MODE_OFF)
          .setFocalLength(VirtualCameraDevice::kFocalLength)
          .setJpegQuality(requestSettings.jpegQuality)
          .setJpegOrientation(requestSettings.jpegOrientation)
          .setJpegThumbnailSize(requestSettings.thumbnailResolution.width,
                                requestSettings.thumbnailResolution.height)
          .setJpegThumbnailQuality(requestSettings.thumbnailJpegQuality)
          .setLensOpticalStabilizationMode(
              ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF)
          .setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF)
          .setPipelineDepth(kPipelineDepth)
          .setSensorTimestamp(timestamp)
          .setStatisticsHotPixelMapMode(
              ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF)
          .setStatisticsLensShadingMapMode(
              ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF)
          .setStatisticsSceneFlicker(ANDROID_STATISTICS_SCENE_FLICKER_NONE);

  if (requestSettings.fpsRange.has_value()) {
    builder.setControlAeTargetFpsRange(requestSettings.fpsRange.value());
  }

  if (requestSettings.gpsCoordinates.has_value()) {
    const GpsCoordinates& coordinates = requestSettings.gpsCoordinates.value();
    builder.setJpegGpsCoordinates(coordinates);
  }

  std::unique_ptr<CameraMetadata> metadata = builder.build();

  if (metadata == nullptr) {
    ALOGE("%s: Failed to build capture result metadata", __func__);
    return CameraMetadata();
  }
  return std::move(*metadata);
}

NotifyMsg createShutterNotifyMsg(int frameNumber,
NotifyMsg createShutterNotifyMsg(int frameNumber,
                                 std::chrono::nanoseconds timestamp) {
                                 std::chrono::nanoseconds timestamp) {
  NotifyMsg msg;
  NotifyMsg msg;
Loading