summaryrefslogtreecommitdiff
path: root/devices/VirtualCamera/VirtualCameraRenderThread.h
blob: 30de7c2e4c68e2643dc9d16ef9f3bb9c3542cfb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * Copyright (C) 2023 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_VIRTUALCAMERARENDERTHREAD_H
#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H

#include <deque>
#include <future>
#include <memory>
#include <thread>

#include "VirtualCameraSessionContext.h"
#include "aidl/android/hardware/camera/device/ICameraDeviceCallback.h"
#include "util/EglDisplayContext.h"
#include "util/EglProgram.h"
#include "util/EglSurfaceTexture.h"

namespace android {
namespace companion {
namespace virtualcamera {

// Represents single output buffer of capture request.
class CaptureRequestBuffer {
 public:
  CaptureRequestBuffer(int streamId, int bufferId, sp<Fence> fence = nullptr);

  int getStreamId() const;
  int getBufferId() const;
  sp<Fence> getFence() const;

 private:
  const int mStreamId;
  const int mBufferId;
  const sp<Fence> mFence;
};

// Represents single capture request to fill set of buffers.
class ProcessCaptureRequestTask {
 public:
  ProcessCaptureRequestTask(
      int frameNumber, const std::vector<CaptureRequestBuffer>& requestBuffers);

  // Returns frame number corresponding to the request.
  int getFrameNumber() const;

  // Get reference to vector describing output buffers corresponding
  // to this request.
  //
  // Note that the vector is owned by the ProcessCaptureRequestTask instance,
  // so it cannot be access outside of its lifetime.
  const std::vector<CaptureRequestBuffer>& getBuffers() const;

 private:
  const int mFrameNumber;
  const std::vector<CaptureRequestBuffer> mBuffers;
};

// Wraps dedicated rendering thread and rendering business with corresponding
// input surface.
class VirtualCameraRenderThread {
 public:
  // Create VirtualCameraRenderThread instance:
  // * sessionContext - VirtualCameraSessionContext reference for shared access
  // to mapped buffers.
  // * inputWidth - requested width of input surface ("virtual camera sensor")
  // * inputHeight - requested height of input surface ("virtual camera sensor")
  // * cameraDeviceCallback - callback for corresponding camera instance
  // * testMode - when set to true, test pattern is rendered to input surface
  // before each capture request is processed to simulate client input.
  VirtualCameraRenderThread(
      VirtualCameraSessionContext& sessionContext, int inputWidth,
      int inputHeight,
      std::shared_ptr<
          ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
          cameraDeviceCallback,
      bool testMode = false);

  ~VirtualCameraRenderThread();

  // Start rendering thread.
  void start();
  // Stop rendering thread.
  void stop();

  // Equeue capture task for processing on render thread.
  void enqueueTask(std::unique_ptr<ProcessCaptureRequestTask> task)
      EXCLUDES(mLock);

  // Flush all in-flight requests.
  void flush() EXCLUDES(mLock);

  // Returns input surface corresponding to "virtual camera sensor".
  sp<Surface> getInputSurface();

 private:
  std::unique_ptr<ProcessCaptureRequestTask> dequeueTask() EXCLUDES(mLock);

  // Rendering thread entry point.
  void threadLoop();

  // Process single capture request task (always called on render thread).
  void processCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);

  // Flush single capture request task returning the error status immediately.
  void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask);

  // TODO(b/301023410) - Refactor the actual rendering logic off this class for
  // easier testability.

  // Render current image to the BLOB buffer.
  // If fence is specified, this function will block until the fence is cleared
  // before writing to the buffer.
  // Always called on render thread.
  ndk::ScopedAStatus renderIntoBlobStreamBuffer(const int streamId,
                                                const int bufferId,
                                                const size_t bufferSize,
                                                sp<Fence> fence = nullptr);

  // Render current image to the YCbCr buffer.
  // If fence is specified, this function will block until the fence is cleared
  // before writing to the buffer.
  // Always called on render thread.
  ndk::ScopedAStatus renderIntoImageStreamBuffer(int streamId, int bufferId,
                                                 sp<Fence> fence = nullptr);

  // Camera callback
  const std::shared_ptr<
      ::aidl::android::hardware::camera::device::ICameraDeviceCallback>
      mCameraDeviceCallback;

  const int mInputSurfaceWidth;
  const int mInputSurfaceHeight;
  const int mTestMode;

  VirtualCameraSessionContext& mSessionContext;

  std::thread mThread;

  // Blocking queue implementation.
  std::mutex mLock;
  std::deque<std::unique_ptr<ProcessCaptureRequestTask>> mQueue GUARDED_BY(mLock);
  std::condition_variable mCondVar;
  volatile bool mPendingExit GUARDED_BY(mLock);

  // EGL helpers - constructed and accessed only from rendering thread.
  std::unique_ptr<EglDisplayContext> mEglDisplayContext;
  std::unique_ptr<EglTextureProgram> mEglTextureProgram;
  std::unique_ptr<EglSurfaceTexture> mEglSurfaceTexture;

  std::promise<sp<Surface>> mInputSurfacePromise;
};

}  // namespace virtualcamera
}  // namespace companion
}  // namespace android

#endif  // ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H