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