xref: /aosp_15_r20/frameworks/av/services/camera/virtualcamera/VirtualCameraSession.cc (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "VirtualCameraSession"
19*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraSession.h"
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
22*ec779b8eSAndroid Build Coastguard Worker #include <atomic>
23*ec779b8eSAndroid Build Coastguard Worker #include <chrono>
24*ec779b8eSAndroid Build Coastguard Worker #include <cmath>
25*ec779b8eSAndroid Build Coastguard Worker #include <cstddef>
26*ec779b8eSAndroid Build Coastguard Worker #include <cstdint>
27*ec779b8eSAndroid Build Coastguard Worker #include <cstring>
28*ec779b8eSAndroid Build Coastguard Worker #include <map>
29*ec779b8eSAndroid Build Coastguard Worker #include <memory>
30*ec779b8eSAndroid Build Coastguard Worker #include <mutex>
31*ec779b8eSAndroid Build Coastguard Worker #include <numeric>
32*ec779b8eSAndroid Build Coastguard Worker #include <optional>
33*ec779b8eSAndroid Build Coastguard Worker #include <tuple>
34*ec779b8eSAndroid Build Coastguard Worker #include <unordered_set>
35*ec779b8eSAndroid Build Coastguard Worker #include <utility>
36*ec779b8eSAndroid Build Coastguard Worker #include <vector>
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker #include "CameraMetadata.h"
39*ec779b8eSAndroid Build Coastguard Worker #include "EGL/egl.h"
40*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraDevice.h"
41*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraRenderThread.h"
42*ec779b8eSAndroid Build Coastguard Worker #include "VirtualCameraStream.h"
43*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
44*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/common/Status.h"
45*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/BufferCache.h"
46*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/BufferStatus.h"
47*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/CameraMetadata.h"
48*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/CaptureRequest.h"
49*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/HalStream.h"
50*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/NotifyMsg.h"
51*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/RequestTemplate.h"
52*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/ShutterMsg.h"
53*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/Stream.h"
54*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/StreamBuffer.h"
55*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/StreamConfiguration.h"
56*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/camera/device/StreamRotation.h"
57*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/graphics/common/BufferUsage.h"
58*ec779b8eSAndroid Build Coastguard Worker #include "aidl/android/hardware/graphics/common/PixelFormat.h"
59*ec779b8eSAndroid Build Coastguard Worker #include "android/hardware_buffer.h"
60*ec779b8eSAndroid Build Coastguard Worker #include "android/native_window_aidl.h"
61*ec779b8eSAndroid Build Coastguard Worker #include "fmq/AidlMessageQueue.h"
62*ec779b8eSAndroid Build Coastguard Worker #include "system/camera_metadata.h"
63*ec779b8eSAndroid Build Coastguard Worker #include "ui/GraphicBuffer.h"
64*ec779b8eSAndroid Build Coastguard Worker #include "util/EglDisplayContext.h"
65*ec779b8eSAndroid Build Coastguard Worker #include "util/EglFramebuffer.h"
66*ec779b8eSAndroid Build Coastguard Worker #include "util/EglProgram.h"
67*ec779b8eSAndroid Build Coastguard Worker #include "util/JpegUtil.h"
68*ec779b8eSAndroid Build Coastguard Worker #include "util/MetadataUtil.h"
69*ec779b8eSAndroid Build Coastguard Worker #include "util/Util.h"
70*ec779b8eSAndroid Build Coastguard Worker 
71*ec779b8eSAndroid Build Coastguard Worker namespace android {
72*ec779b8eSAndroid Build Coastguard Worker namespace companion {
73*ec779b8eSAndroid Build Coastguard Worker namespace virtualcamera {
74*ec779b8eSAndroid Build Coastguard Worker 
75*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::IVirtualCameraCallback;
76*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
77*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::common::Status;
78*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::BufferCache;
79*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::CameraMetadata;
80*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::CameraOfflineSessionInfo;
81*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::CaptureRequest;
82*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::HalStream;
83*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::ICameraDeviceCallback;
84*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::ICameraOfflineSession;
85*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::RequestTemplate;
86*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::Stream;
87*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::StreamBuffer;
88*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::camera::device::StreamConfiguration;
89*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::common::fmq::MQDescriptor;
90*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
91*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::BufferUsage;
92*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::PixelFormat;
93*ec779b8eSAndroid Build Coastguard Worker using ::android::base::unique_fd;
94*ec779b8eSAndroid Build Coastguard Worker 
95*ec779b8eSAndroid Build Coastguard Worker namespace {
96*ec779b8eSAndroid Build Coastguard Worker 
97*ec779b8eSAndroid Build Coastguard Worker using metadata_ptr =
98*ec779b8eSAndroid Build Coastguard Worker     std::unique_ptr<camera_metadata_t, void (*)(camera_metadata_t*)>;
99*ec779b8eSAndroid Build Coastguard Worker 
100*ec779b8eSAndroid Build Coastguard Worker using namespace std::chrono_literals;
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker // Size of request/result metadata fast message queue.
103*ec779b8eSAndroid Build Coastguard Worker // Setting to 0 to always disables FMQ.
104*ec779b8eSAndroid Build Coastguard Worker constexpr size_t kMetadataMsgQueueSize = 0;
105*ec779b8eSAndroid Build Coastguard Worker 
106*ec779b8eSAndroid Build Coastguard Worker // Maximum number of buffers to use per single stream.
107*ec779b8eSAndroid Build Coastguard Worker constexpr size_t kMaxStreamBuffers = 2;
108*ec779b8eSAndroid Build Coastguard Worker 
109*ec779b8eSAndroid Build Coastguard Worker // Thumbnail size (0,0) correspods to disabling thumbnail.
110*ec779b8eSAndroid Build Coastguard Worker const Resolution kDefaultJpegThumbnailSize(0, 0);
111*ec779b8eSAndroid Build Coastguard Worker 
requestTemplateToIntent(const RequestTemplate type)112*ec779b8eSAndroid Build Coastguard Worker camera_metadata_enum_android_control_capture_intent_t requestTemplateToIntent(
113*ec779b8eSAndroid Build Coastguard Worker     const RequestTemplate type) {
114*ec779b8eSAndroid Build Coastguard Worker   switch (type) {
115*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::PREVIEW:
116*ec779b8eSAndroid Build Coastguard Worker       return ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
117*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::STILL_CAPTURE:
118*ec779b8eSAndroid Build Coastguard Worker       return ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
119*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::VIDEO_RECORD:
120*ec779b8eSAndroid Build Coastguard Worker       return ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
121*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::VIDEO_SNAPSHOT:
122*ec779b8eSAndroid Build Coastguard Worker       return ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
123*ec779b8eSAndroid Build Coastguard Worker     default:
124*ec779b8eSAndroid Build Coastguard Worker       // Return PREVIEW by default
125*ec779b8eSAndroid Build Coastguard Worker       return ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
126*ec779b8eSAndroid Build Coastguard Worker   }
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker 
getMaxFps(const std::vector<SupportedStreamConfiguration> & configs)129*ec779b8eSAndroid Build Coastguard Worker int getMaxFps(const std::vector<SupportedStreamConfiguration>& configs) {
130*ec779b8eSAndroid Build Coastguard Worker   return std::transform_reduce(
131*ec779b8eSAndroid Build Coastguard Worker       configs.begin(), configs.end(), 0,
132*ec779b8eSAndroid Build Coastguard Worker       [](const int a, const int b) { return std::max(a, b); },
133*ec779b8eSAndroid Build Coastguard Worker       [](const SupportedStreamConfiguration& config) { return config.maxFps; });
134*ec779b8eSAndroid Build Coastguard Worker }
135*ec779b8eSAndroid Build Coastguard Worker 
createDefaultRequestSettings(const RequestTemplate type,const std::vector<SupportedStreamConfiguration> & inputConfigs)136*ec779b8eSAndroid Build Coastguard Worker CameraMetadata createDefaultRequestSettings(
137*ec779b8eSAndroid Build Coastguard Worker     const RequestTemplate type,
138*ec779b8eSAndroid Build Coastguard Worker     const std::vector<SupportedStreamConfiguration>& inputConfigs) {
139*ec779b8eSAndroid Build Coastguard Worker   int maxFps = getMaxFps(inputConfigs);
140*ec779b8eSAndroid Build Coastguard Worker   auto metadata =
141*ec779b8eSAndroid Build Coastguard Worker       MetadataBuilder()
142*ec779b8eSAndroid Build Coastguard Worker           .setAberrationCorrectionMode(
143*ec779b8eSAndroid Build Coastguard Worker               ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF)
144*ec779b8eSAndroid Build Coastguard Worker           .setControlCaptureIntent(requestTemplateToIntent(type))
145*ec779b8eSAndroid Build Coastguard Worker           .setControlMode(ANDROID_CONTROL_MODE_AUTO)
146*ec779b8eSAndroid Build Coastguard Worker           .setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
147*ec779b8eSAndroid Build Coastguard Worker           .setControlAeExposureCompensation(0)
148*ec779b8eSAndroid Build Coastguard Worker           .setControlAeTargetFpsRange(FpsRange{maxFps, maxFps})
149*ec779b8eSAndroid Build Coastguard Worker           .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO)
150*ec779b8eSAndroid Build Coastguard Worker           .setControlAePrecaptureTrigger(
151*ec779b8eSAndroid Build Coastguard Worker               ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
152*ec779b8eSAndroid Build Coastguard Worker           .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
153*ec779b8eSAndroid Build Coastguard Worker           .setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF)
154*ec779b8eSAndroid Build Coastguard Worker           .setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
155*ec779b8eSAndroid Build Coastguard Worker           .setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF)
156*ec779b8eSAndroid Build Coastguard Worker           .setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF)
157*ec779b8eSAndroid Build Coastguard Worker           .setFlashMode(ANDROID_FLASH_MODE_OFF)
158*ec779b8eSAndroid Build Coastguard Worker           .setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE)
159*ec779b8eSAndroid Build Coastguard Worker           .setJpegQuality(VirtualCameraDevice::kDefaultJpegQuality)
160*ec779b8eSAndroid Build Coastguard Worker           .setJpegThumbnailQuality(VirtualCameraDevice::kDefaultJpegQuality)
161*ec779b8eSAndroid Build Coastguard Worker           .setJpegThumbnailSize(0, 0)
162*ec779b8eSAndroid Build Coastguard Worker           .setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF)
163*ec779b8eSAndroid Build Coastguard Worker           .build();
164*ec779b8eSAndroid Build Coastguard Worker   if (metadata == nullptr) {
165*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: Failed to construct metadata for default request type %s",
166*ec779b8eSAndroid Build Coastguard Worker           __func__, toString(type).c_str());
167*ec779b8eSAndroid Build Coastguard Worker     return CameraMetadata();
168*ec779b8eSAndroid Build Coastguard Worker   } else {
169*ec779b8eSAndroid Build Coastguard Worker     ALOGV("%s: Successfully created metadata for request type %s", __func__,
170*ec779b8eSAndroid Build Coastguard Worker           toString(type).c_str());
171*ec779b8eSAndroid Build Coastguard Worker   }
172*ec779b8eSAndroid Build Coastguard Worker   return *metadata;
173*ec779b8eSAndroid Build Coastguard Worker }
174*ec779b8eSAndroid Build Coastguard Worker 
getHalStream(const Stream & stream)175*ec779b8eSAndroid Build Coastguard Worker HalStream getHalStream(const Stream& stream) {
176*ec779b8eSAndroid Build Coastguard Worker   HalStream halStream;
177*ec779b8eSAndroid Build Coastguard Worker   halStream.id = stream.id;
178*ec779b8eSAndroid Build Coastguard Worker   halStream.physicalCameraId = stream.physicalCameraId;
179*ec779b8eSAndroid Build Coastguard Worker   halStream.maxBuffers = kMaxStreamBuffers;
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker   if (stream.format == PixelFormat::IMPLEMENTATION_DEFINED) {
182*ec779b8eSAndroid Build Coastguard Worker     // If format is implementation defined we need it to override
183*ec779b8eSAndroid Build Coastguard Worker     // it with actual format.
184*ec779b8eSAndroid Build Coastguard Worker     // TODO(b/301023410) Override with the format based on the
185*ec779b8eSAndroid Build Coastguard Worker     // camera configuration, once we support more formats.
186*ec779b8eSAndroid Build Coastguard Worker     halStream.overrideFormat = PixelFormat::YCBCR_420_888;
187*ec779b8eSAndroid Build Coastguard Worker   } else {
188*ec779b8eSAndroid Build Coastguard Worker     halStream.overrideFormat = stream.format;
189*ec779b8eSAndroid Build Coastguard Worker   }
190*ec779b8eSAndroid Build Coastguard Worker   halStream.overrideDataSpace = stream.dataSpace;
191*ec779b8eSAndroid Build Coastguard Worker 
192*ec779b8eSAndroid Build Coastguard Worker   halStream.producerUsage = static_cast<BufferUsage>(
193*ec779b8eSAndroid Build Coastguard Worker       static_cast<int64_t>(stream.usage) |
194*ec779b8eSAndroid Build Coastguard Worker       static_cast<int64_t>(BufferUsage::CAMERA_OUTPUT) |
195*ec779b8eSAndroid Build Coastguard Worker       static_cast<int64_t>(BufferUsage::GPU_RENDER_TARGET));
196*ec779b8eSAndroid Build Coastguard Worker 
197*ec779b8eSAndroid Build Coastguard Worker   halStream.supportOffline = false;
198*ec779b8eSAndroid Build Coastguard Worker   return halStream;
199*ec779b8eSAndroid Build Coastguard Worker }
200*ec779b8eSAndroid Build Coastguard Worker 
getHighestResolutionStream(const std::vector<Stream> & streams)201*ec779b8eSAndroid Build Coastguard Worker Stream getHighestResolutionStream(const std::vector<Stream>& streams) {
202*ec779b8eSAndroid Build Coastguard Worker   return *(std::max_element(streams.begin(), streams.end(),
203*ec779b8eSAndroid Build Coastguard Worker                             [](const Stream& a, const Stream& b) {
204*ec779b8eSAndroid Build Coastguard Worker                               return a.width * a.height < b.width * b.height;
205*ec779b8eSAndroid Build Coastguard Worker                             }));
206*ec779b8eSAndroid Build Coastguard Worker }
207*ec779b8eSAndroid Build Coastguard Worker 
resolutionFromStream(const Stream & stream)208*ec779b8eSAndroid Build Coastguard Worker Resolution resolutionFromStream(const Stream& stream) {
209*ec779b8eSAndroid Build Coastguard Worker   return Resolution(stream.width, stream.height);
210*ec779b8eSAndroid Build Coastguard Worker }
211*ec779b8eSAndroid Build Coastguard Worker 
resolutionFromInputConfig(const SupportedStreamConfiguration & inputConfig)212*ec779b8eSAndroid Build Coastguard Worker Resolution resolutionFromInputConfig(
213*ec779b8eSAndroid Build Coastguard Worker     const SupportedStreamConfiguration& inputConfig) {
214*ec779b8eSAndroid Build Coastguard Worker   return Resolution(inputConfig.width, inputConfig.height);
215*ec779b8eSAndroid Build Coastguard Worker }
216*ec779b8eSAndroid Build Coastguard Worker 
resolutionFromSurface(const sp<Surface> surface)217*ec779b8eSAndroid Build Coastguard Worker std::optional<Resolution> resolutionFromSurface(const sp<Surface> surface) {
218*ec779b8eSAndroid Build Coastguard Worker   Resolution res{0, 0};
219*ec779b8eSAndroid Build Coastguard Worker   if (surface == nullptr) {
220*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: Cannot get resolution from null surface", __func__);
221*ec779b8eSAndroid Build Coastguard Worker     return std::nullopt;
222*ec779b8eSAndroid Build Coastguard Worker   }
223*ec779b8eSAndroid Build Coastguard Worker 
224*ec779b8eSAndroid Build Coastguard Worker   int status = surface->query(NATIVE_WINDOW_WIDTH, &res.width);
225*ec779b8eSAndroid Build Coastguard Worker   if (status != NO_ERROR) {
226*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: Failed to get width from surface", __func__);
227*ec779b8eSAndroid Build Coastguard Worker     return std::nullopt;
228*ec779b8eSAndroid Build Coastguard Worker   }
229*ec779b8eSAndroid Build Coastguard Worker 
230*ec779b8eSAndroid Build Coastguard Worker   status = surface->query(NATIVE_WINDOW_HEIGHT, &res.height);
231*ec779b8eSAndroid Build Coastguard Worker   if (status != NO_ERROR) {
232*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: Failed to get height from surface", __func__);
233*ec779b8eSAndroid Build Coastguard Worker     return std::nullopt;
234*ec779b8eSAndroid Build Coastguard Worker   }
235*ec779b8eSAndroid Build Coastguard Worker   return res;
236*ec779b8eSAndroid Build Coastguard Worker }
237*ec779b8eSAndroid Build Coastguard Worker 
pickInputConfigurationForStreams(const std::vector<Stream> & requestedStreams,const std::vector<SupportedStreamConfiguration> & supportedInputConfigs)238*ec779b8eSAndroid Build Coastguard Worker std::optional<SupportedStreamConfiguration> pickInputConfigurationForStreams(
239*ec779b8eSAndroid Build Coastguard Worker     const std::vector<Stream>& requestedStreams,
240*ec779b8eSAndroid Build Coastguard Worker     const std::vector<SupportedStreamConfiguration>& supportedInputConfigs) {
241*ec779b8eSAndroid Build Coastguard Worker   Stream maxResolutionStream = getHighestResolutionStream(requestedStreams);
242*ec779b8eSAndroid Build Coastguard Worker   Resolution maxResolution = resolutionFromStream(maxResolutionStream);
243*ec779b8eSAndroid Build Coastguard Worker 
244*ec779b8eSAndroid Build Coastguard Worker   // Find best fitting stream to satisfy all requested streams:
245*ec779b8eSAndroid Build Coastguard Worker   // Best fitting => same or higher resolution as input with lowest pixel count
246*ec779b8eSAndroid Build Coastguard Worker   // difference and same aspect ratio.
247*ec779b8eSAndroid Build Coastguard Worker   auto isBetterInputConfig = [maxResolution](
248*ec779b8eSAndroid Build Coastguard Worker                                  const SupportedStreamConfiguration& configA,
249*ec779b8eSAndroid Build Coastguard Worker                                  const SupportedStreamConfiguration& configB) {
250*ec779b8eSAndroid Build Coastguard Worker     int maxResPixelCount = maxResolution.width * maxResolution.height;
251*ec779b8eSAndroid Build Coastguard Worker     int pixelCountDiffA =
252*ec779b8eSAndroid Build Coastguard Worker         std::abs((configA.width * configA.height) - maxResPixelCount);
253*ec779b8eSAndroid Build Coastguard Worker     int pixelCountDiffB =
254*ec779b8eSAndroid Build Coastguard Worker         std::abs((configB.width * configB.height) - maxResPixelCount);
255*ec779b8eSAndroid Build Coastguard Worker 
256*ec779b8eSAndroid Build Coastguard Worker     return pixelCountDiffA < pixelCountDiffB;
257*ec779b8eSAndroid Build Coastguard Worker   };
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker   std::optional<SupportedStreamConfiguration> bestConfig;
260*ec779b8eSAndroid Build Coastguard Worker   for (const SupportedStreamConfiguration& inputConfig : supportedInputConfigs) {
261*ec779b8eSAndroid Build Coastguard Worker     Resolution inputConfigResolution = resolutionFromInputConfig(inputConfig);
262*ec779b8eSAndroid Build Coastguard Worker     if (inputConfigResolution < maxResolution ||
263*ec779b8eSAndroid Build Coastguard Worker         !isApproximatellySameAspectRatio(inputConfigResolution, maxResolution)) {
264*ec779b8eSAndroid Build Coastguard Worker       // We don't want to upscale from lower resolution, or use different aspect
265*ec779b8eSAndroid Build Coastguard Worker       // ratio, skip.
266*ec779b8eSAndroid Build Coastguard Worker       continue;
267*ec779b8eSAndroid Build Coastguard Worker     }
268*ec779b8eSAndroid Build Coastguard Worker 
269*ec779b8eSAndroid Build Coastguard Worker     if (!bestConfig.has_value() ||
270*ec779b8eSAndroid Build Coastguard Worker         isBetterInputConfig(inputConfig, bestConfig.value())) {
271*ec779b8eSAndroid Build Coastguard Worker       bestConfig = inputConfig;
272*ec779b8eSAndroid Build Coastguard Worker     }
273*ec779b8eSAndroid Build Coastguard Worker   }
274*ec779b8eSAndroid Build Coastguard Worker 
275*ec779b8eSAndroid Build Coastguard Worker   return bestConfig;
276*ec779b8eSAndroid Build Coastguard Worker }
277*ec779b8eSAndroid Build Coastguard Worker 
createSettingsFromMetadata(const CameraMetadata & metadata)278*ec779b8eSAndroid Build Coastguard Worker RequestSettings createSettingsFromMetadata(const CameraMetadata& metadata) {
279*ec779b8eSAndroid Build Coastguard Worker   return RequestSettings{
280*ec779b8eSAndroid Build Coastguard Worker       .jpegQuality = getJpegQuality(metadata).value_or(
281*ec779b8eSAndroid Build Coastguard Worker           VirtualCameraDevice::kDefaultJpegQuality),
282*ec779b8eSAndroid Build Coastguard Worker       .jpegOrientation = getJpegOrientation(metadata),
283*ec779b8eSAndroid Build Coastguard Worker       .thumbnailResolution =
284*ec779b8eSAndroid Build Coastguard Worker           getJpegThumbnailSize(metadata).value_or(Resolution(0, 0)),
285*ec779b8eSAndroid Build Coastguard Worker       .thumbnailJpegQuality = getJpegThumbnailQuality(metadata).value_or(
286*ec779b8eSAndroid Build Coastguard Worker           VirtualCameraDevice::kDefaultJpegQuality),
287*ec779b8eSAndroid Build Coastguard Worker       .fpsRange = getFpsRange(metadata),
288*ec779b8eSAndroid Build Coastguard Worker       .captureIntent = getCaptureIntent(metadata).value_or(
289*ec779b8eSAndroid Build Coastguard Worker           ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW),
290*ec779b8eSAndroid Build Coastguard Worker       .gpsCoordinates = getGpsCoordinates(metadata),
291*ec779b8eSAndroid Build Coastguard Worker       .aePrecaptureTrigger = getPrecaptureTrigger(metadata)};
292*ec779b8eSAndroid Build Coastguard Worker }
293*ec779b8eSAndroid Build Coastguard Worker 
294*ec779b8eSAndroid Build Coastguard Worker }  // namespace
295*ec779b8eSAndroid Build Coastguard Worker 
VirtualCameraSession(std::shared_ptr<VirtualCameraDevice> cameraDevice,std::shared_ptr<ICameraDeviceCallback> cameraDeviceCallback,std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback)296*ec779b8eSAndroid Build Coastguard Worker VirtualCameraSession::VirtualCameraSession(
297*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<VirtualCameraDevice> cameraDevice,
298*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<ICameraDeviceCallback> cameraDeviceCallback,
299*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<IVirtualCameraCallback> virtualCameraClientCallback)
300*ec779b8eSAndroid Build Coastguard Worker     : mCameraDevice(cameraDevice),
301*ec779b8eSAndroid Build Coastguard Worker       mCameraDeviceCallback(cameraDeviceCallback),
302*ec779b8eSAndroid Build Coastguard Worker       mVirtualCameraClientCallback(virtualCameraClientCallback) {
303*ec779b8eSAndroid Build Coastguard Worker   mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
304*ec779b8eSAndroid Build Coastguard Worker       kMetadataMsgQueueSize, false /* non blocking */);
305*ec779b8eSAndroid Build Coastguard Worker   if (!mRequestMetadataQueue->isValid()) {
306*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: invalid request fmq", __func__);
307*ec779b8eSAndroid Build Coastguard Worker   }
308*ec779b8eSAndroid Build Coastguard Worker 
309*ec779b8eSAndroid Build Coastguard Worker   mResultMetadataQueue = std::make_shared<ResultMetadataQueue>(
310*ec779b8eSAndroid Build Coastguard Worker       kMetadataMsgQueueSize, false /* non blocking */);
311*ec779b8eSAndroid Build Coastguard Worker   if (!mResultMetadataQueue->isValid()) {
312*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: invalid result fmq", __func__);
313*ec779b8eSAndroid Build Coastguard Worker   }
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker 
close()316*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::close() {
317*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
318*ec779b8eSAndroid Build Coastguard Worker   {
319*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
320*ec779b8eSAndroid Build Coastguard Worker 
321*ec779b8eSAndroid Build Coastguard Worker     if (mVirtualCameraClientCallback != nullptr) {
322*ec779b8eSAndroid Build Coastguard Worker       mVirtualCameraClientCallback->onStreamClosed(mCurrentInputStreamId);
323*ec779b8eSAndroid Build Coastguard Worker     }
324*ec779b8eSAndroid Build Coastguard Worker 
325*ec779b8eSAndroid Build Coastguard Worker     if (mRenderThread != nullptr) {
326*ec779b8eSAndroid Build Coastguard Worker       mRenderThread->stop();
327*ec779b8eSAndroid Build Coastguard Worker       mRenderThread = nullptr;
328*ec779b8eSAndroid Build Coastguard Worker     }
329*ec779b8eSAndroid Build Coastguard Worker   }
330*ec779b8eSAndroid Build Coastguard Worker 
331*ec779b8eSAndroid Build Coastguard Worker   mSessionContext.closeAllStreams();
332*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
333*ec779b8eSAndroid Build Coastguard Worker }
334*ec779b8eSAndroid Build Coastguard Worker 
configureStreams(const StreamConfiguration & in_requestedConfiguration,std::vector<HalStream> * _aidl_return)335*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::configureStreams(
336*ec779b8eSAndroid Build Coastguard Worker     const StreamConfiguration& in_requestedConfiguration,
337*ec779b8eSAndroid Build Coastguard Worker     std::vector<HalStream>* _aidl_return) {
338*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s: requestedConfiguration: %s", __func__,
339*ec779b8eSAndroid Build Coastguard Worker         in_requestedConfiguration.toString().c_str());
340*ec779b8eSAndroid Build Coastguard Worker 
341*ec779b8eSAndroid Build Coastguard Worker   if (_aidl_return == nullptr) {
342*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::ILLEGAL_ARGUMENT);
343*ec779b8eSAndroid Build Coastguard Worker   }
344*ec779b8eSAndroid Build Coastguard Worker 
345*ec779b8eSAndroid Build Coastguard Worker   std::shared_ptr<VirtualCameraDevice> virtualCamera = mCameraDevice.lock();
346*ec779b8eSAndroid Build Coastguard Worker   if (virtualCamera == nullptr) {
347*ec779b8eSAndroid Build Coastguard Worker     ALOGW("%s: configure called on already unregistered camera", __func__);
348*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::CAMERA_DISCONNECTED);
349*ec779b8eSAndroid Build Coastguard Worker   }
350*ec779b8eSAndroid Build Coastguard Worker 
351*ec779b8eSAndroid Build Coastguard Worker   mSessionContext.removeStreamsNotInStreamConfiguration(
352*ec779b8eSAndroid Build Coastguard Worker       in_requestedConfiguration);
353*ec779b8eSAndroid Build Coastguard Worker 
354*ec779b8eSAndroid Build Coastguard Worker   auto& streams = in_requestedConfiguration.streams;
355*ec779b8eSAndroid Build Coastguard Worker   auto& halStreams = *_aidl_return;
356*ec779b8eSAndroid Build Coastguard Worker   halStreams.clear();
357*ec779b8eSAndroid Build Coastguard Worker   halStreams.resize(in_requestedConfiguration.streams.size());
358*ec779b8eSAndroid Build Coastguard Worker 
359*ec779b8eSAndroid Build Coastguard Worker   if (!virtualCamera->isStreamCombinationSupported(in_requestedConfiguration)) {
360*ec779b8eSAndroid Build Coastguard Worker     ALOGE("%s: Requested stream configuration is not supported", __func__);
361*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::ILLEGAL_ARGUMENT);
362*ec779b8eSAndroid Build Coastguard Worker   }
363*ec779b8eSAndroid Build Coastguard Worker 
364*ec779b8eSAndroid Build Coastguard Worker   sp<Surface> inputSurface = nullptr;
365*ec779b8eSAndroid Build Coastguard Worker   int inputStreamId = -1;
366*ec779b8eSAndroid Build Coastguard Worker   std::optional<SupportedStreamConfiguration> inputConfig;
367*ec779b8eSAndroid Build Coastguard Worker   {
368*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
369*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < in_requestedConfiguration.streams.size(); ++i) {
370*ec779b8eSAndroid Build Coastguard Worker       halStreams[i] = getHalStream(streams[i]);
371*ec779b8eSAndroid Build Coastguard Worker       if (mSessionContext.initializeStream(streams[i])) {
372*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Configured new stream: %s", streams[i].toString().c_str());
373*ec779b8eSAndroid Build Coastguard Worker       }
374*ec779b8eSAndroid Build Coastguard Worker     }
375*ec779b8eSAndroid Build Coastguard Worker 
376*ec779b8eSAndroid Build Coastguard Worker     inputConfig = pickInputConfigurationForStreams(
377*ec779b8eSAndroid Build Coastguard Worker         streams, virtualCamera->getInputConfigs());
378*ec779b8eSAndroid Build Coastguard Worker     if (!inputConfig.has_value()) {
379*ec779b8eSAndroid Build Coastguard Worker       ALOGE(
380*ec779b8eSAndroid Build Coastguard Worker           "%s: Failed to pick any input configuration for stream configuration "
381*ec779b8eSAndroid Build Coastguard Worker           "request: %s",
382*ec779b8eSAndroid Build Coastguard Worker           __func__, in_requestedConfiguration.toString().c_str());
383*ec779b8eSAndroid Build Coastguard Worker       return cameraStatus(Status::ILLEGAL_ARGUMENT);
384*ec779b8eSAndroid Build Coastguard Worker     }
385*ec779b8eSAndroid Build Coastguard Worker 
386*ec779b8eSAndroid Build Coastguard Worker     if (mRenderThread != nullptr) {
387*ec779b8eSAndroid Build Coastguard Worker       // If there's already a render thread, it means this is not a first
388*ec779b8eSAndroid Build Coastguard Worker       // configuration call. If the surface has the same resolution and pixel
389*ec779b8eSAndroid Build Coastguard Worker       // format as the picked config, we don't need to do anything, the current
390*ec779b8eSAndroid Build Coastguard Worker       // render thread is capable of serving new set of configuration. However
391*ec779b8eSAndroid Build Coastguard Worker       // if it differens, we need to discard the current surface and
392*ec779b8eSAndroid Build Coastguard Worker       // reinitialize the render thread.
393*ec779b8eSAndroid Build Coastguard Worker 
394*ec779b8eSAndroid Build Coastguard Worker       std::optional<Resolution> currentInputResolution =
395*ec779b8eSAndroid Build Coastguard Worker           resolutionFromSurface(mRenderThread->getInputSurface());
396*ec779b8eSAndroid Build Coastguard Worker       if (currentInputResolution.has_value() &&
397*ec779b8eSAndroid Build Coastguard Worker           *currentInputResolution == resolutionFromInputConfig(*inputConfig)) {
398*ec779b8eSAndroid Build Coastguard Worker         ALOGI(
399*ec779b8eSAndroid Build Coastguard Worker             "%s: Newly configured set of streams matches existing client "
400*ec779b8eSAndroid Build Coastguard Worker             "surface (%dx%d)",
401*ec779b8eSAndroid Build Coastguard Worker             __func__, currentInputResolution->width,
402*ec779b8eSAndroid Build Coastguard Worker             currentInputResolution->height);
403*ec779b8eSAndroid Build Coastguard Worker         return ndk::ScopedAStatus::ok();
404*ec779b8eSAndroid Build Coastguard Worker       }
405*ec779b8eSAndroid Build Coastguard Worker 
406*ec779b8eSAndroid Build Coastguard Worker       if (mVirtualCameraClientCallback != nullptr) {
407*ec779b8eSAndroid Build Coastguard Worker         mVirtualCameraClientCallback->onStreamClosed(mCurrentInputStreamId);
408*ec779b8eSAndroid Build Coastguard Worker       }
409*ec779b8eSAndroid Build Coastguard Worker 
410*ec779b8eSAndroid Build Coastguard Worker       ALOGV(
411*ec779b8eSAndroid Build Coastguard Worker           "%s: Newly requested output streams are not suitable for "
412*ec779b8eSAndroid Build Coastguard Worker           "pre-existing surface (%dx%d), creating new surface (%dx%d)",
413*ec779b8eSAndroid Build Coastguard Worker           __func__, currentInputResolution->width,
414*ec779b8eSAndroid Build Coastguard Worker           currentInputResolution->height, inputConfig->width,
415*ec779b8eSAndroid Build Coastguard Worker           inputConfig->height);
416*ec779b8eSAndroid Build Coastguard Worker 
417*ec779b8eSAndroid Build Coastguard Worker       mRenderThread->flush();
418*ec779b8eSAndroid Build Coastguard Worker       mRenderThread->stop();
419*ec779b8eSAndroid Build Coastguard Worker     }
420*ec779b8eSAndroid Build Coastguard Worker 
421*ec779b8eSAndroid Build Coastguard Worker     mRenderThread = std::make_unique<VirtualCameraRenderThread>(
422*ec779b8eSAndroid Build Coastguard Worker         mSessionContext, resolutionFromInputConfig(*inputConfig),
423*ec779b8eSAndroid Build Coastguard Worker         virtualCamera->getMaxInputResolution(), mCameraDeviceCallback);
424*ec779b8eSAndroid Build Coastguard Worker     mRenderThread->start();
425*ec779b8eSAndroid Build Coastguard Worker     inputSurface = mRenderThread->getInputSurface();
426*ec779b8eSAndroid Build Coastguard Worker     inputStreamId = mCurrentInputStreamId =
427*ec779b8eSAndroid Build Coastguard Worker         virtualCamera->allocateInputStreamId();
428*ec779b8eSAndroid Build Coastguard Worker   }
429*ec779b8eSAndroid Build Coastguard Worker 
430*ec779b8eSAndroid Build Coastguard Worker   if (mVirtualCameraClientCallback != nullptr && inputSurface != nullptr) {
431*ec779b8eSAndroid Build Coastguard Worker     // TODO(b/301023410) Pass streamId based on client input stream id once
432*ec779b8eSAndroid Build Coastguard Worker     // support for multiple input streams is implemented. For now we always
433*ec779b8eSAndroid Build Coastguard Worker     // create single texture.
434*ec779b8eSAndroid Build Coastguard Worker     mVirtualCameraClientCallback->onStreamConfigured(
435*ec779b8eSAndroid Build Coastguard Worker         inputStreamId, aidl::android::view::Surface(inputSurface.get()),
436*ec779b8eSAndroid Build Coastguard Worker         inputConfig->width, inputConfig->height, inputConfig->pixelFormat);
437*ec779b8eSAndroid Build Coastguard Worker   }
438*ec779b8eSAndroid Build Coastguard Worker 
439*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
440*ec779b8eSAndroid Build Coastguard Worker }
441*ec779b8eSAndroid Build Coastguard Worker 
constructDefaultRequestSettings(RequestTemplate in_type,CameraMetadata * _aidl_return)442*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::constructDefaultRequestSettings(
443*ec779b8eSAndroid Build Coastguard Worker     RequestTemplate in_type, CameraMetadata* _aidl_return) {
444*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s: type %d", __func__, static_cast<int32_t>(in_type));
445*ec779b8eSAndroid Build Coastguard Worker 
446*ec779b8eSAndroid Build Coastguard Worker   std::shared_ptr<VirtualCameraDevice> camera = mCameraDevice.lock();
447*ec779b8eSAndroid Build Coastguard Worker   if (camera == nullptr) {
448*ec779b8eSAndroid Build Coastguard Worker     ALOGW(
449*ec779b8eSAndroid Build Coastguard Worker         "%s: constructDefaultRequestSettings called on already unregistered "
450*ec779b8eSAndroid Build Coastguard Worker         "camera",
451*ec779b8eSAndroid Build Coastguard Worker         __func__);
452*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::CAMERA_DISCONNECTED);
453*ec779b8eSAndroid Build Coastguard Worker   }
454*ec779b8eSAndroid Build Coastguard Worker 
455*ec779b8eSAndroid Build Coastguard Worker   switch (in_type) {
456*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::PREVIEW:
457*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::STILL_CAPTURE:
458*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::VIDEO_RECORD:
459*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::VIDEO_SNAPSHOT: {
460*ec779b8eSAndroid Build Coastguard Worker       *_aidl_return =
461*ec779b8eSAndroid Build Coastguard Worker           createDefaultRequestSettings(in_type, camera->getInputConfigs());
462*ec779b8eSAndroid Build Coastguard Worker       return ndk::ScopedAStatus::ok();
463*ec779b8eSAndroid Build Coastguard Worker     }
464*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::MANUAL:
465*ec779b8eSAndroid Build Coastguard Worker     case RequestTemplate::ZERO_SHUTTER_LAG:
466*ec779b8eSAndroid Build Coastguard Worker       // Don't support VIDEO_SNAPSHOT, MANUAL, ZSL templates
467*ec779b8eSAndroid Build Coastguard Worker       return ndk::ScopedAStatus::fromServiceSpecificError(
468*ec779b8eSAndroid Build Coastguard Worker           static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
469*ec779b8eSAndroid Build Coastguard Worker       ;
470*ec779b8eSAndroid Build Coastguard Worker     default:
471*ec779b8eSAndroid Build Coastguard Worker       ALOGE("%s: unknown request template type %d", __FUNCTION__,
472*ec779b8eSAndroid Build Coastguard Worker             static_cast<int>(in_type));
473*ec779b8eSAndroid Build Coastguard Worker       return ndk::ScopedAStatus::fromServiceSpecificError(
474*ec779b8eSAndroid Build Coastguard Worker           static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
475*ec779b8eSAndroid Build Coastguard Worker       ;
476*ec779b8eSAndroid Build Coastguard Worker   }
477*ec779b8eSAndroid Build Coastguard Worker }
478*ec779b8eSAndroid Build Coastguard Worker 
flush()479*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::flush() {
480*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
481*ec779b8eSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(mLock);
482*ec779b8eSAndroid Build Coastguard Worker   if (mRenderThread != nullptr) {
483*ec779b8eSAndroid Build Coastguard Worker     mRenderThread->flush();
484*ec779b8eSAndroid Build Coastguard Worker   }
485*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
486*ec779b8eSAndroid Build Coastguard Worker }
487*ec779b8eSAndroid Build Coastguard Worker 
getCaptureRequestMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * _aidl_return)488*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::getCaptureRequestMetadataQueue(
489*ec779b8eSAndroid Build Coastguard Worker     MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
490*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
491*ec779b8eSAndroid Build Coastguard Worker   *_aidl_return = mRequestMetadataQueue->dupeDesc();
492*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
493*ec779b8eSAndroid Build Coastguard Worker }
494*ec779b8eSAndroid Build Coastguard Worker 
getCaptureResultMetadataQueue(MQDescriptor<int8_t,SynchronizedReadWrite> * _aidl_return)495*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::getCaptureResultMetadataQueue(
496*ec779b8eSAndroid Build Coastguard Worker     MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
497*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
498*ec779b8eSAndroid Build Coastguard Worker   *_aidl_return = mResultMetadataQueue->dupeDesc();
499*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
500*ec779b8eSAndroid Build Coastguard Worker }
501*ec779b8eSAndroid Build Coastguard Worker 
isReconfigurationRequired(const CameraMetadata & in_oldSessionParams,const CameraMetadata & in_newSessionParams,bool * _aidl_return)502*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::isReconfigurationRequired(
503*ec779b8eSAndroid Build Coastguard Worker     const CameraMetadata& in_oldSessionParams,
504*ec779b8eSAndroid Build Coastguard Worker     const CameraMetadata& in_newSessionParams, bool* _aidl_return) {
505*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s: oldSessionParams: %s newSessionParams: %s", __func__,
506*ec779b8eSAndroid Build Coastguard Worker         in_newSessionParams.toString().c_str(),
507*ec779b8eSAndroid Build Coastguard Worker         in_oldSessionParams.toString().c_str());
508*ec779b8eSAndroid Build Coastguard Worker 
509*ec779b8eSAndroid Build Coastguard Worker   if (_aidl_return == nullptr) {
510*ec779b8eSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::fromServiceSpecificError(
511*ec779b8eSAndroid Build Coastguard Worker         static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
512*ec779b8eSAndroid Build Coastguard Worker   }
513*ec779b8eSAndroid Build Coastguard Worker 
514*ec779b8eSAndroid Build Coastguard Worker   *_aidl_return = true;
515*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
516*ec779b8eSAndroid Build Coastguard Worker }
517*ec779b8eSAndroid Build Coastguard Worker 
processCaptureRequest(const std::vector<CaptureRequest> & in_requests,const std::vector<BufferCache> & in_cachesToRemove,int32_t * _aidl_return)518*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::processCaptureRequest(
519*ec779b8eSAndroid Build Coastguard Worker     const std::vector<CaptureRequest>& in_requests,
520*ec779b8eSAndroid Build Coastguard Worker     const std::vector<BufferCache>& in_cachesToRemove, int32_t* _aidl_return) {
521*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
522*ec779b8eSAndroid Build Coastguard Worker 
523*ec779b8eSAndroid Build Coastguard Worker   if (!in_cachesToRemove.empty()) {
524*ec779b8eSAndroid Build Coastguard Worker     mSessionContext.removeBufferCaches(in_cachesToRemove);
525*ec779b8eSAndroid Build Coastguard Worker   }
526*ec779b8eSAndroid Build Coastguard Worker 
527*ec779b8eSAndroid Build Coastguard Worker   for (const auto& captureRequest : in_requests) {
528*ec779b8eSAndroid Build Coastguard Worker     auto status = processCaptureRequest(captureRequest);
529*ec779b8eSAndroid Build Coastguard Worker     if (!status.isOk()) {
530*ec779b8eSAndroid Build Coastguard Worker       return status;
531*ec779b8eSAndroid Build Coastguard Worker     }
532*ec779b8eSAndroid Build Coastguard Worker   }
533*ec779b8eSAndroid Build Coastguard Worker   *_aidl_return = in_requests.size();
534*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
535*ec779b8eSAndroid Build Coastguard Worker }
536*ec779b8eSAndroid Build Coastguard Worker 
signalStreamFlush(const std::vector<int32_t> & in_streamIds,int32_t in_streamConfigCounter)537*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::signalStreamFlush(
538*ec779b8eSAndroid Build Coastguard Worker     const std::vector<int32_t>& in_streamIds, int32_t in_streamConfigCounter) {
539*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
540*ec779b8eSAndroid Build Coastguard Worker 
541*ec779b8eSAndroid Build Coastguard Worker   (void)in_streamIds;
542*ec779b8eSAndroid Build Coastguard Worker   (void)in_streamConfigCounter;
543*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
544*ec779b8eSAndroid Build Coastguard Worker }
545*ec779b8eSAndroid Build Coastguard Worker 
switchToOffline(const std::vector<int32_t> & in_streamsToKeep,CameraOfflineSessionInfo * out_offlineSessionInfo,std::shared_ptr<ICameraOfflineSession> * _aidl_return)546*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::switchToOffline(
547*ec779b8eSAndroid Build Coastguard Worker     const std::vector<int32_t>& in_streamsToKeep,
548*ec779b8eSAndroid Build Coastguard Worker     CameraOfflineSessionInfo* out_offlineSessionInfo,
549*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<ICameraOfflineSession>* _aidl_return) {
550*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
551*ec779b8eSAndroid Build Coastguard Worker 
552*ec779b8eSAndroid Build Coastguard Worker   (void)in_streamsToKeep;
553*ec779b8eSAndroid Build Coastguard Worker   (void)out_offlineSessionInfo;
554*ec779b8eSAndroid Build Coastguard Worker 
555*ec779b8eSAndroid Build Coastguard Worker   if (_aidl_return == nullptr) {
556*ec779b8eSAndroid Build Coastguard Worker     return ndk::ScopedAStatus::fromServiceSpecificError(
557*ec779b8eSAndroid Build Coastguard Worker         static_cast<int32_t>(Status::ILLEGAL_ARGUMENT));
558*ec779b8eSAndroid Build Coastguard Worker   }
559*ec779b8eSAndroid Build Coastguard Worker 
560*ec779b8eSAndroid Build Coastguard Worker   *_aidl_return = nullptr;
561*ec779b8eSAndroid Build Coastguard Worker   return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
562*ec779b8eSAndroid Build Coastguard Worker }
563*ec779b8eSAndroid Build Coastguard Worker 
repeatingRequestEnd(int32_t in_frameNumber,const std::vector<int32_t> & in_streamIds)564*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::repeatingRequestEnd(
565*ec779b8eSAndroid Build Coastguard Worker     int32_t in_frameNumber, const std::vector<int32_t>& in_streamIds) {
566*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s", __func__);
567*ec779b8eSAndroid Build Coastguard Worker   (void)in_frameNumber;
568*ec779b8eSAndroid Build Coastguard Worker   (void)in_streamIds;
569*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
570*ec779b8eSAndroid Build Coastguard Worker }
571*ec779b8eSAndroid Build Coastguard Worker 
getStreamIds() const572*ec779b8eSAndroid Build Coastguard Worker std::set<int> VirtualCameraSession::getStreamIds() const {
573*ec779b8eSAndroid Build Coastguard Worker   return mSessionContext.getStreamIds();
574*ec779b8eSAndroid Build Coastguard Worker }
575*ec779b8eSAndroid Build Coastguard Worker 
processCaptureRequest(const CaptureRequest & request)576*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus VirtualCameraSession::processCaptureRequest(
577*ec779b8eSAndroid Build Coastguard Worker     const CaptureRequest& request) {
578*ec779b8eSAndroid Build Coastguard Worker   ALOGV("%s: request: %s", __func__, request.toString().c_str());
579*ec779b8eSAndroid Build Coastguard Worker 
580*ec779b8eSAndroid Build Coastguard Worker   std::shared_ptr<ICameraDeviceCallback> cameraCallback = nullptr;
581*ec779b8eSAndroid Build Coastguard Worker   RequestSettings requestSettings;
582*ec779b8eSAndroid Build Coastguard Worker   int currentInputStreamId;
583*ec779b8eSAndroid Build Coastguard Worker   {
584*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
585*ec779b8eSAndroid Build Coastguard Worker 
586*ec779b8eSAndroid Build Coastguard Worker     // If metadata it empty, last received metadata applies, if  it's non-empty
587*ec779b8eSAndroid Build Coastguard Worker     // update it.
588*ec779b8eSAndroid Build Coastguard Worker     if (!request.settings.metadata.empty()) {
589*ec779b8eSAndroid Build Coastguard Worker       mCurrentRequestMetadata = request.settings;
590*ec779b8eSAndroid Build Coastguard Worker     }
591*ec779b8eSAndroid Build Coastguard Worker 
592*ec779b8eSAndroid Build Coastguard Worker     // We don't have any metadata for this request - this means we received none
593*ec779b8eSAndroid Build Coastguard Worker     // in first request, this is an error state.
594*ec779b8eSAndroid Build Coastguard Worker     if (mCurrentRequestMetadata.metadata.empty()) {
595*ec779b8eSAndroid Build Coastguard Worker       return cameraStatus(Status::ILLEGAL_ARGUMENT);
596*ec779b8eSAndroid Build Coastguard Worker     }
597*ec779b8eSAndroid Build Coastguard Worker 
598*ec779b8eSAndroid Build Coastguard Worker     requestSettings = createSettingsFromMetadata(mCurrentRequestMetadata);
599*ec779b8eSAndroid Build Coastguard Worker 
600*ec779b8eSAndroid Build Coastguard Worker     cameraCallback = mCameraDeviceCallback;
601*ec779b8eSAndroid Build Coastguard Worker     currentInputStreamId = mCurrentInputStreamId;
602*ec779b8eSAndroid Build Coastguard Worker   }
603*ec779b8eSAndroid Build Coastguard Worker 
604*ec779b8eSAndroid Build Coastguard Worker   if (cameraCallback == nullptr) {
605*ec779b8eSAndroid Build Coastguard Worker     ALOGE(
606*ec779b8eSAndroid Build Coastguard Worker         "%s: processCaptureRequest called, but there's no camera callback "
607*ec779b8eSAndroid Build Coastguard Worker         "configured",
608*ec779b8eSAndroid Build Coastguard Worker         __func__);
609*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::INTERNAL_ERROR);
610*ec779b8eSAndroid Build Coastguard Worker   }
611*ec779b8eSAndroid Build Coastguard Worker 
612*ec779b8eSAndroid Build Coastguard Worker   if (!mSessionContext.importBuffersFromCaptureRequest(request)) {
613*ec779b8eSAndroid Build Coastguard Worker     ALOGE("Failed to import buffers from capture request.");
614*ec779b8eSAndroid Build Coastguard Worker     return cameraStatus(Status::INTERNAL_ERROR);
615*ec779b8eSAndroid Build Coastguard Worker   }
616*ec779b8eSAndroid Build Coastguard Worker 
617*ec779b8eSAndroid Build Coastguard Worker   std::vector<CaptureRequestBuffer> taskBuffers;
618*ec779b8eSAndroid Build Coastguard Worker   taskBuffers.reserve(request.outputBuffers.size());
619*ec779b8eSAndroid Build Coastguard Worker   for (const StreamBuffer& streamBuffer : request.outputBuffers) {
620*ec779b8eSAndroid Build Coastguard Worker     taskBuffers.emplace_back(streamBuffer.streamId, streamBuffer.bufferId,
621*ec779b8eSAndroid Build Coastguard Worker                              importFence(streamBuffer.acquireFence));
622*ec779b8eSAndroid Build Coastguard Worker   }
623*ec779b8eSAndroid Build Coastguard Worker 
624*ec779b8eSAndroid Build Coastguard Worker   {
625*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> lock(mLock);
626*ec779b8eSAndroid Build Coastguard Worker     if (mRenderThread == nullptr) {
627*ec779b8eSAndroid Build Coastguard Worker       ALOGE(
628*ec779b8eSAndroid Build Coastguard Worker           "%s: processCaptureRequest (frameNumber %d)called before configure "
629*ec779b8eSAndroid Build Coastguard Worker           "(render thread not initialized)",
630*ec779b8eSAndroid Build Coastguard Worker           __func__, request.frameNumber);
631*ec779b8eSAndroid Build Coastguard Worker       return cameraStatus(Status::INTERNAL_ERROR);
632*ec779b8eSAndroid Build Coastguard Worker     }
633*ec779b8eSAndroid Build Coastguard Worker     mRenderThread->enqueueTask(std::make_unique<ProcessCaptureRequestTask>(
634*ec779b8eSAndroid Build Coastguard Worker         request.frameNumber, taskBuffers, requestSettings));
635*ec779b8eSAndroid Build Coastguard Worker   }
636*ec779b8eSAndroid Build Coastguard Worker 
637*ec779b8eSAndroid Build Coastguard Worker   if (mVirtualCameraClientCallback != nullptr) {
638*ec779b8eSAndroid Build Coastguard Worker     auto status = mVirtualCameraClientCallback->onProcessCaptureRequest(
639*ec779b8eSAndroid Build Coastguard Worker         currentInputStreamId, request.frameNumber);
640*ec779b8eSAndroid Build Coastguard Worker     if (!status.isOk()) {
641*ec779b8eSAndroid Build Coastguard Worker       ALOGE(
642*ec779b8eSAndroid Build Coastguard Worker           "Failed to invoke onProcessCaptureRequest client callback for frame "
643*ec779b8eSAndroid Build Coastguard Worker           "%d",
644*ec779b8eSAndroid Build Coastguard Worker           request.frameNumber);
645*ec779b8eSAndroid Build Coastguard Worker     }
646*ec779b8eSAndroid Build Coastguard Worker   }
647*ec779b8eSAndroid Build Coastguard Worker 
648*ec779b8eSAndroid Build Coastguard Worker   return ndk::ScopedAStatus::ok();
649*ec779b8eSAndroid Build Coastguard Worker }
650*ec779b8eSAndroid Build Coastguard Worker 
651*ec779b8eSAndroid Build Coastguard Worker }  // namespace virtualcamera
652*ec779b8eSAndroid Build Coastguard Worker }  // namespace companion
653*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
654