blob: a35eea16c5fd967f79694ed18e206a018bb181c9 [file] [log] [blame]
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +01001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
18#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
19
Jan Sebechlebsky2f4478e2024-05-08 17:26:42 +020020#include <atomic>
Vadim Caenb79f4e32024-08-30 16:35:33 +020021#include <chrono>
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010022#include <cstdint>
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010023#include <deque>
24#include <future>
25#include <memory>
26#include <thread>
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +020027#include <variant>
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010028#include <vector>
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010029
Vadim Caen550634d2024-07-17 14:01:21 +020030#include "VirtualCameraCaptureRequest.h"
Jan Sebechlebskybb01c1d2024-02-12 11:41:37 +010031#include "VirtualCameraDevice.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010032#include "VirtualCameraSessionContext.h"
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010033#include "aidl/android/hardware/camera/device/CameraMetadata.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010034#include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
Jan Sebechlebsky042d1fb2023-12-12 16:37:00 +010035#include "android/binder_auto_utils.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010036#include "util/EglDisplayContext.h"
Jan Sebechlebsky042d1fb2023-12-12 16:37:00 +010037#include "util/EglFramebuffer.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010038#include "util/EglProgram.h"
39#include "util/EglSurfaceTexture.h"
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010040#include "util/Util.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010041
42namespace android {
43namespace companion {
44namespace virtualcamera {
45
46// Represents single output buffer of capture request.
47class CaptureRequestBuffer {
48 public:
49 CaptureRequestBuffer(int streamId, int bufferId, sp<Fence> fence = nullptr);
50
51 int getStreamId() const;
52 int getBufferId() const;
53 sp<Fence> getFence() const;
54
55 private:
56 const int mStreamId;
57 const int mBufferId;
58 const sp<Fence> mFence;
59};
60
61// Represents single capture request to fill set of buffers.
62class ProcessCaptureRequestTask {
63 public:
64 ProcessCaptureRequestTask(
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010065 int frameNumber, const std::vector<CaptureRequestBuffer>& requestBuffers,
66 const RequestSettings& RequestSettings = {});
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010067
68 // Returns frame number corresponding to the request.
69 int getFrameNumber() const;
70
71 // Get reference to vector describing output buffers corresponding
72 // to this request.
73 //
74 // Note that the vector is owned by the ProcessCaptureRequestTask instance,
75 // so it cannot be access outside of its lifetime.
76 const std::vector<CaptureRequestBuffer>& getBuffers() const;
77
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010078 const RequestSettings& getRequestSettings() const;
79
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010080 private:
81 const int mFrameNumber;
82 const std::vector<CaptureRequestBuffer> mBuffers;
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +010083 const RequestSettings mRequestSettings;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010084};
85
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +020086struct UpdateTextureTask {};
87
88struct RenderThreadTask
89 : public std::variant<std::unique_ptr<ProcessCaptureRequestTask>,
90 UpdateTextureTask> {
91 // Allow implicit conversion to bool.
92 //
93 // Returns false, if the RenderThreadTask consist of null
94 // ProcessCaptureRequestTask, which signals that the thread should terminate.
95 operator bool() const {
96 const bool isExitSignal =
97 std::holds_alternative<std::unique_ptr<ProcessCaptureRequestTask>>(
98 *this) &&
99 std::get<std::unique_ptr<ProcessCaptureRequestTask>>(*this) == nullptr;
100 return !isExitSignal;
101 }
102};
103
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100104// Wraps dedicated rendering thread and rendering business with corresponding
105// input surface.
106class VirtualCameraRenderThread {
107 public:
108 // Create VirtualCameraRenderThread instance:
109 // * sessionContext - VirtualCameraSessionContext reference for shared access
110 // to mapped buffers.
Jan Sebechlebskybb01c1d2024-02-12 11:41:37 +0100111 // * inputSurfaceSize - requested size of input surface.
112 // * reportedSensorSize - reported static sensor size of virtual camera.
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100113 // * cameraDeviceCallback - callback for corresponding camera instance
114 // * testMode - when set to true, test pattern is rendered to input surface
115 // before each capture request is processed to simulate client input.
116 VirtualCameraRenderThread(
Jan Sebechlebskybb01c1d2024-02-12 11:41:37 +0100117 VirtualCameraSessionContext& sessionContext, Resolution inputSurfaceSize,
118 Resolution reportedSensorSize,
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100119 std::shared_ptr<
120 ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
Jan Sebechlebsky288900f2024-05-24 14:47:54 +0200121 cameraDeviceCallback);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100122
123 ~VirtualCameraRenderThread();
124
125 // Start rendering thread.
126 void start();
127 // Stop rendering thread.
128 void stop();
129
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +0200130 // Send request to render thread to update the texture.
131 // Currently queued buffers in the input surface will be consumed and the most
132 // recent buffer in the input surface will be attached to the texture), all
133 // other buffers will be returned to the buffer queue.
134 void requestTextureUpdate() EXCLUDES(mLock);
135
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100136 // Equeue capture task for processing on render thread.
137 void enqueueTask(std::unique_ptr<ProcessCaptureRequestTask> task)
138 EXCLUDES(mLock);
139
140 // Flush all in-flight requests.
141 void flush() EXCLUDES(mLock);
142
143 // Returns input surface corresponding to "virtual camera sensor".
144 sp<Surface> getInputSurface();
145
146 private:
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +0200147 RenderThreadTask dequeueTask() EXCLUDES(mLock);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100148
149 // Rendering thread entry point.
150 void threadLoop();
151
152 // Process single capture request task (always called on render thread).
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +0200153 void processTask(const ProcessCaptureRequestTask& captureRequestTask);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100154
155 // Flush single capture request task returning the error status immediately.
156 void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);
157
158 // TODO(b/301023410) - Refactor the actual rendering logic off this class for
159 // easier testability.
160
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +0100161 // Create thumbnail with specified size for current image.
162 // The compressed image size is limited by 32KiB.
163 // Returns vector with compressed thumbnail if successful,
164 // empty vector otherwise.
165 std::vector<uint8_t> createThumbnail(Resolution resolution, int quality);
166
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100167 // Render current image to the BLOB buffer.
168 // If fence is specified, this function will block until the fence is cleared
169 // before writing to the buffer.
170 // Always called on render thread.
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +0100171 ndk::ScopedAStatus renderIntoBlobStreamBuffer(
172 const int streamId, const int bufferId,
Vadim Caenc0aff132024-03-12 17:20:07 +0100173 const ::aidl::android::hardware::camera::device::CameraMetadata&
174 resultMetadata,
Jan Sebechlebsky4ce32082024-02-14 16:02:11 +0100175 const RequestSettings& requestSettings, sp<Fence> fence = nullptr);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100176
177 // Render current image to the YCbCr buffer.
178 // If fence is specified, this function will block until the fence is cleared
179 // before writing to the buffer.
180 // Always called on render thread.
181 ndk::ScopedAStatus renderIntoImageStreamBuffer(int streamId, int bufferId,
182 sp<Fence> fence = nullptr);
183
Jan Sebechlebsky042d1fb2023-12-12 16:37:00 +0100184 // Render current image into provided EglFramebuffer.
185 // If fence is specified, this function will block until the fence is cleared
186 // before writing to the buffer.
187 // Always called on the render thread.
Jan Sebechlebskyb3771312024-03-15 10:38:02 +0100188 ndk::ScopedAStatus renderIntoEglFramebuffer(
189 EglFrameBuffer& framebuffer, sp<Fence> fence = nullptr,
190 std::optional<Rect> viewport = std::nullopt);
Jan Sebechlebsky042d1fb2023-12-12 16:37:00 +0100191
Vadim Caenb79f4e32024-08-30 16:35:33 +0200192 // Throttle the current thread to ensure that we are not rendering faster than
193 // the provided maxFps.
194 // maxFps: The maximum fps in the capture request
195 // lastAcquisitionTimestamp: timestamp of the previous frame
196 // timestamp: the current capture time
197 // Returns the time at which the capture has happened after throttling.
198 std::chrono::nanoseconds throttleRendering(
199 int maxFps, std::chrono::nanoseconds lastAcquisitionTimestamp,
200 std::chrono::nanoseconds timestamp);
201
202 // Fetch the timestamp of the latest buffer from the EGL Surface
203 // timeSinceLastFrame: The elapsed time since the last captured frame.
204 // Return 0 if no timestamp has been associated to this surface by the producer.
205 std::chrono::nanoseconds getSurfaceTimestamp(
206 std::chrono::nanoseconds timeSinceLastFrame);
207
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100208 // Camera callback
209 const std::shared_ptr<
210 ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
211 mCameraDeviceCallback;
212
Jan Sebechlebskybb01c1d2024-02-12 11:41:37 +0100213 const Resolution mInputSurfaceSize;
214 const Resolution mReportedSensorSize;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100215
216 VirtualCameraSessionContext& mSessionContext;
217
218 std::thread mThread;
219
220 // Blocking queue implementation.
221 std::mutex mLock;
222 std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
223 std::condition_variable mCondVar;
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +0200224 volatile bool mTextureUpdateRequested GUARDED_BY(mLock);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100225 volatile bool mPendingExit GUARDED_BY(mLock);
226
Jan Sebechlebsky2f4478e2024-05-08 17:26:42 +0200227 // Acquisition timestamp of last frame.
228 std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;
Vadim Caenb79f4e32024-08-30 16:35:33 +0200229 std::atomic<uint64_t> mLastSurfaceTimestampNanoseconds;
Jan Sebechlebsky2f4478e2024-05-08 17:26:42 +0200230
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100231 // EGL helpers - constructed and accessed only from rendering thread.
232 std::unique_ptr<EglDisplayContext> mEglDisplayContext;
Jan Sebechlebsky042d1fb2023-12-12 16:37:00 +0100233 std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram;
234 std::unique_ptr<EglTextureProgram> mEglTextureRgbProgram;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100235 std::unique_ptr<EglSurfaceTexture> mEglSurfaceTexture;
236
237 std::promise<sp<Surface>> mInputSurfacePromise;
Jan Sebechlebsky9fcd0262024-05-31 15:20:09 +0200238 std::shared_future<sp<Surface>> mInputSurfaceFuture;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100239};
240
241} // namespace virtualcamera
242} // namespace companion
243} // namespace android
244
245#endif // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H