xref: /aosp_15_r20/frameworks/av/services/camera/virtualcamera/VirtualCameraRenderThread.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
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 
20 #include <atomic>
21 #include <chrono>
22 #include <cstddef>
23 #include <cstdint>
24 #include <deque>
25 #include <future>
26 #include <memory>
27 #include <thread>
28 #include <variant>
29 #include <vector>
30 
31 #include "VirtualCameraCaptureRequest.h"
32 #include "VirtualCameraDevice.h"
33 #include "VirtualCameraSessionContext.h"
34 #include "aidl/android/hardware/camera/device/CameraMetadata.h"
35 #include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
36 #include "android/binder_auto_utils.h"
37 #include "util/EglDisplayContext.h"
38 #include "util/EglFramebuffer.h"
39 #include "util/EglProgram.h"
40 #include "util/EglSurfaceTexture.h"
41 #include "util/Util.h"
42 
43 namespace android {
44 namespace companion {
45 namespace virtualcamera {
46 
47 // Represents single output buffer of capture request.
48 class CaptureRequestBuffer {
49  public:
50   CaptureRequestBuffer(int streamId, int bufferId, sp<Fence> fence = nullptr);
51 
52   int getStreamId() const;
53   int getBufferId() const;
54   sp<Fence> getFence() const;
55 
56  private:
57   const int mStreamId;
58   const int mBufferId;
59   const sp<Fence> mFence;
60 };
61 
62 // Represents single capture request to fill set of buffers.
63 class ProcessCaptureRequestTask {
64  public:
65   ProcessCaptureRequestTask(
66       int frameNumber, const std::vector<CaptureRequestBuffer>& requestBuffers,
67       const RequestSettings& RequestSettings = {});
68 
69   // Returns frame number corresponding to the request.
70   int getFrameNumber() const;
71 
72   // Get reference to vector describing output buffers corresponding
73   // to this request.
74   //
75   // Note that the vector is owned by the ProcessCaptureRequestTask instance,
76   // so it cannot be access outside of its lifetime.
77   const std::vector<CaptureRequestBuffer>& getBuffers() const;
78 
79   const RequestSettings& getRequestSettings() const;
80 
81  private:
82   const int mFrameNumber;
83   const std::vector<CaptureRequestBuffer> mBuffers;
84   const RequestSettings mRequestSettings;
85 };
86 
87 struct UpdateTextureTask {};
88 
89 struct RenderThreadTask
90     : public std::variant<std::unique_ptr<ProcessCaptureRequestTask>,
91                           UpdateTextureTask> {
92   // Allow implicit conversion to bool.
93   //
94   // Returns false, if the RenderThreadTask consist of null
95   // ProcessCaptureRequestTask, which signals that the thread should terminate.
96   operator bool() const {
97     const bool isExitSignal =
98         std::holds_alternative<std::unique_ptr<ProcessCaptureRequestTask>>(
99             *this) &&
100         std::get<std::unique_ptr<ProcessCaptureRequestTask>>(*this) == nullptr;
101     return !isExitSignal;
102   }
103 };
104 
105 // Wraps dedicated rendering thread and rendering business with corresponding
106 // input surface.
107 class VirtualCameraRenderThread {
108  public:
109   // Create VirtualCameraRenderThread instance:
110   // * sessionContext - VirtualCameraSessionContext reference for shared access
111   // to mapped buffers.
112   // * inputSurfaceSize - requested size of input surface.
113   // * reportedSensorSize - reported static sensor size of virtual camera.
114   // * cameraDeviceCallback - callback for corresponding camera instance
115   // * testMode - when set to true, test pattern is rendered to input surface
116   // before each capture request is processed to simulate client input.
117   VirtualCameraRenderThread(
118       VirtualCameraSessionContext& sessionContext, Resolution inputSurfaceSize,
119       Resolution reportedSensorSize,
120       std::shared_ptr<
121           ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
122           cameraDeviceCallback);
123 
124   ~VirtualCameraRenderThread();
125 
126   // Start rendering thread.
127   void start();
128   // Stop rendering thread.
129   void stop();
130 
131   // Send request to render thread to update the texture.
132   // Currently queued buffers in the input surface will be consumed and the most
133   // recent buffer in the input surface will be attached to the texture), all
134   // other buffers will be returned to the buffer queue.
135   void requestTextureUpdate() EXCLUDES(mLock);
136 
137   // Equeue capture task for processing on render thread.
138   void enqueueTask(std::unique_ptr<ProcessCaptureRequestTask> task)
139       EXCLUDES(mLock);
140 
141   // Flush all in-flight requests.
142   void flush() EXCLUDES(mLock);
143 
144   // Returns input surface corresponding to "virtual camera sensor".
145   sp<Surface> getInputSurface();
146 
147  private:
148   RenderThreadTask dequeueTask() EXCLUDES(mLock);
149 
150   // Rendering thread entry point.
151   void threadLoop();
152 
153   // Process single capture request task (always called on render thread).
154   void processTask(const ProcessCaptureRequestTask& captureRequestTask);
155 
156   // Flush single capture request task returning the error status immediately.
157   void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);
158 
159   // TODO(b/301023410) - Refactor the actual rendering logic off this class for
160   // easier testability.
161 
162   // Create thumbnail with specified size for current image.
163   // The compressed image size is limited by 32KiB.
164   // Returns vector with compressed thumbnail if successful,
165   // empty vector otherwise.
166   std::vector<uint8_t> createThumbnail(Resolution resolution, int quality);
167 
168   // Render current image to the BLOB buffer.
169   // If fence is specified, this function will block until the fence is cleared
170   // before writing to the buffer.
171   // Always called on render thread.
172   ndk::ScopedAStatus renderIntoBlobStreamBuffer(
173       const int streamId, const int bufferId,
174       const ::aidl::android::hardware::camera::device::CameraMetadata&
175           resultMetadata,
176       const RequestSettings& requestSettings, sp<Fence> fence = nullptr);
177 
178   // Render current image to the YCbCr buffer.
179   // If fence is specified, this function will block until the fence is cleared
180   // before writing to the buffer.
181   // Always called on render thread.
182   ndk::ScopedAStatus renderIntoImageStreamBuffer(int streamId, int bufferId,
183                                                  sp<Fence> fence = nullptr);
184 
185   // Render current image into provided EglFramebuffer.
186   // If fence is specified, this function will block until the fence is cleared
187   // before writing to the buffer.
188   // Always called on the render thread.
189   ndk::ScopedAStatus renderIntoEglFramebuffer(
190       EglFrameBuffer& framebuffer, sp<Fence> fence = nullptr,
191       std::optional<Rect> viewport = std::nullopt);
192 
193   // Throttle the current thread to ensure that we are not rendering faster than
194   // the provided maxFps.
195   // maxFps: The maximum fps in the capture request
196   // lastAcquisitionTimestamp: timestamp of the previous frame
197   // timestamp: the current capture time
198   // Returns the time at which the capture has happened after throttling.
199   std::chrono::nanoseconds throttleRendering(
200       int maxFps, std::chrono::nanoseconds lastAcquisitionTimestamp,
201       std::chrono::nanoseconds timestamp);
202 
203   // Fetch the timestamp of the latest buffer from the EGL Surface
204   // timeSinceLastFrame: The elapsed time since the last captured frame.
205   // Return 0 if no timestamp has been associated to this surface by the producer.
206   std::chrono::nanoseconds getSurfaceTimestamp(
207       std::chrono::nanoseconds timeSinceLastFrame);
208 
209   // Build a default capture result object populating the metadata from the request.
210   std::unique_ptr<::aidl::android::hardware::camera::device::CaptureResult>
211   createCaptureResult(
212       int frameNumber,
213       std::unique_ptr<aidl::android::hardware::camera::device::CameraMetadata>
214           metadata);
215 
216   // Renders the images from the input surface into the request's buffers.
217   void renderOutputBuffers(
218       const ProcessCaptureRequestTask& request,
219       ::aidl::android::hardware::camera::device::CaptureResult& captureResult);
220 
221   // Notify a shutter event for all the buffers in this request.
222   ::ndk::ScopedAStatus notifyShutter(
223       const ProcessCaptureRequestTask& request,
224       const ::aidl::android::hardware::camera::device::CaptureResult& captureResult,
225       std::chrono::nanoseconds captureTimestamp);
226 
227   // Notify a timeout error for this request. The capture result still needs to
228   // be submitted after this call.
229   ::ndk::ScopedAStatus notifyTimeout(
230       const ProcessCaptureRequestTask& request,
231       ::aidl::android::hardware::camera::device::CaptureResult& captureResult);
232 
233   // Submit the capture result to the camera callback.
234   ::ndk::ScopedAStatus submitCaptureResult(
235       std::unique_ptr<::aidl::android::hardware::camera::device::CaptureResult>
236           captureResult);
237 
238   // Camera callback
239   const std::shared_ptr<
240       ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
241       mCameraDeviceCallback;
242 
243   const Resolution mInputSurfaceSize;
244   const Resolution mReportedSensorSize;
245 
246   VirtualCameraSessionContext& mSessionContext;
247 
248   std::thread mThread;
249 
250   // Blocking queue implementation.
251   std::mutex mLock;
252   std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
253   std::condition_variable mCondVar;
254   volatile bool GUARDED_BY(mLock) mTextureUpdateRequested = false;
255   volatile bool GUARDED_BY(mLock) mPendingExit = false;
256 
257   // Acquisition timestamp of last frame.
258   std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;
259   std::atomic<uint64_t> mLastSurfaceTimestampNanoseconds;
260 
261   // EGL helpers - constructed and accessed only from rendering thread.
262   std::unique_ptr<EglDisplayContext> mEglDisplayContext;
263   std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram;
264   std::unique_ptr<EglTextureProgram> mEglTextureRgbProgram;
265   std::unique_ptr<EglSurfaceTexture> mEglSurfaceTexture;
266 
267   std::promise<sp<Surface>> mInputSurfacePromise;
268   std::shared_future<sp<Surface>> mInputSurfaceFuture;
269 };
270 
271 }  // namespace virtualcamera
272 }  // namespace companion
273 }  // namespace android
274 
275 #endif  // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
276