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

Commit 0397f3ee authored by Vadim Caen's avatar Vadim Caen Committed by Android (Google) Code Review
Browse files

Merge "Better separation of concern for the render thread" into main

parents f627d7ca 550634de
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -65,14 +65,7 @@ cc_library_static {
cc_library_static {
    name: "libvirtualcamera",
    srcs: [
        "VirtualCameraProvider.cc",
        "VirtualCameraDevice.cc",
        "VirtualCameraSession.cc",
        "VirtualCameraStream.cc",
        "VirtualCameraService.cc",
        "VirtualCameraSessionContext.cc",
        "VirtualCameraTestInstance.cc",
        "VirtualCameraRenderThread.cc",
        "*.cc",
    ],
    defaults: [
        "libvirtualcamera_defaults",
+59 −0
Original line number 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 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 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 Diff line number Diff line
@@ -29,6 +29,7 @@

#include "Exif.h"
#include "GLES/gl.h"
#include "VirtualCameraCaptureResult.h"
#include "VirtualCameraDevice.h"
#include "VirtualCameraSessionContext.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;

// 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 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,
                                 std::chrono::nanoseconds timestamp) {
  NotifyMsg msg;
Loading