• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #pragma once
18 
19 #include <cstdint>
20 #include <functional>
21 #include <memory>
22 #include <mutex>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <thread>
27 #include <type_traits>
28 #include <unordered_set>
29 
30 #include <android-base/logging.h>
31 #include <fruit/fruit.h>
32 
33 #include "common/libs/confui/confui.h"
34 #include "common/libs/fs/shared_fd.h"
35 #include "common/libs/utils/contains.h"
36 #include "common/libs/utils/size_utils.h"
37 #include "host/libs/config/cuttlefish_config.h"
38 #include "host/libs/confui/host_mode_ctrl.h"
39 #include "host/libs/confui/host_utils.h"
40 #include "host/libs/screen_connector/screen_connector_common.h"
41 #include "host/libs/screen_connector/screen_connector_multiplexer.h"
42 #include "host/libs/screen_connector/screen_connector_queue.h"
43 #include "host/libs/screen_connector/wayland_screen_connector.h"
44 
45 namespace cuttlefish {
46 
47 template <typename ProcessedFrameType>
48 class ScreenConnector : public ScreenConnectorInfo,
49                         public ScreenConnectorFrameRenderer {
50  public:
51   static_assert(cuttlefish::is_movable<ProcessedFrameType>::value,
52                 "ProcessedFrameType should be std::move-able.");
53   static_assert(
54       std::is_base_of<ScreenConnectorFrameInfo, ProcessedFrameType>::value,
55       "ProcessedFrameType should inherit ScreenConnectorFrameInfo");
56 
57   using FrameMultiplexer = ScreenConnectorInputMultiplexer<ProcessedFrameType>;
58 
INJECT(ScreenConnector (WaylandScreenConnector & sc_android_src,HostModeCtrl & host_mode_ctrl))59   INJECT(ScreenConnector(WaylandScreenConnector& sc_android_src,
60                          HostModeCtrl& host_mode_ctrl))
61       : sc_android_src_(sc_android_src),
62         host_mode_ctrl_{host_mode_ctrl},
63         on_next_frame_cnt_{0},
64         render_confui_cnt_{0},
65         sc_frame_multiplexer_{host_mode_ctrl_} {
66     auto config = cuttlefish::CuttlefishConfig::Get();
67     if (!config) {
68       LOG(FATAL) << "CuttlefishConfig is not available.";
69     }
70     auto instance = config->ForDefaultInstance();
71     std::unordered_set<std::string_view> valid_gpu_modes{
72         cuttlefish::kGpuModeCustom,
73         cuttlefish::kGpuModeDrmVirgl,
74         cuttlefish::kGpuModeGfxstream,
75         cuttlefish::kGpuModeGfxstreamGuestAngle,
76         cuttlefish::kGpuModeGfxstreamGuestAngleHostSwiftShader,
77         cuttlefish::kGpuModeGfxstreamGuestAngleHostLavapipe,
78         cuttlefish::kGpuModeGuestSwiftshader};
79     if (!Contains(valid_gpu_modes, instance.gpu_mode())) {
80       LOG(FATAL) << "Invalid gpu mode: " << instance.gpu_mode();
81     }
82   }
83 
84   /**
85    * This is the type of the callback function WebRTC is supposed to provide
86    * ScreenConnector with.
87    *
88    * The callback function is how a raw bytes frame should be processed for
89    * WebRTC
90    *
91    */
92   using GenerateProcessedFrameCallback = std::function<void(
93       std::uint32_t /*display_number*/, std::uint32_t /*frame_width*/,
94       std::uint32_t /*frame_height*/, std::uint32_t /*frame_fourcc_format*/,
95       std::uint32_t /*frame_stride_bytes*/, std::uint8_t* /*frame_bytes*/,
96       /* ScImpl enqueues this type into the Q */
97       ProcessedFrameType& msg)>;
98 
99   virtual ~ScreenConnector() = default;
100 
101   /**
102    * set the callback function to be eventually used by Wayland-Based
103    * Connector
104    *
105    */
SetCallback(GenerateProcessedFrameCallback && frame_callback)106   void SetCallback(GenerateProcessedFrameCallback&& frame_callback) {
107     std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
108     callback_from_streamer_ = std::move(frame_callback);
109     streamer_callback_set_cv_.notify_all();
110 
111     sc_android_src_.SetFrameCallback(
112         [this](std::uint32_t display_number, std::uint32_t frame_w,
113                std::uint32_t frame_h, std::uint32_t frame_fourcc_format,
114                std::uint32_t frame_stride_bytes, std::uint8_t* frame_bytes) {
115           InjectFrame(display_number, frame_w, frame_h, frame_fourcc_format,
116                       frame_stride_bytes, frame_bytes);
117         });
118   }
119 
InjectFrame(std::uint32_t display_number,std::uint32_t frame_w,std::uint32_t frame_h,std::uint32_t frame_fourcc_format,std::uint32_t frame_stride_bytes,std::uint8_t * frame_bytes)120   void InjectFrame(std::uint32_t display_number, std::uint32_t frame_w,
121                    std::uint32_t frame_h, std::uint32_t frame_fourcc_format,
122                    std::uint32_t frame_stride_bytes,
123                    std::uint8_t* frame_bytes) {
124     const bool is_confui_mode = host_mode_ctrl_.IsConfirmatioUiMode();
125     if (is_confui_mode) {
126       return;
127     }
128 
129     ProcessedFrameType processed_frame;
130 
131     {
132       std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
133       callback_from_streamer_(display_number, frame_w, frame_h,
134                               frame_fourcc_format, frame_stride_bytes,
135                               frame_bytes, processed_frame);
136     }
137 
138     sc_frame_multiplexer_.PushToAndroidQueue(std::move(processed_frame));
139   }
140 
IsCallbackSet()141   bool IsCallbackSet() const override {
142     if (callback_from_streamer_) {
143       return true;
144     }
145     return false;
146   }
147 
SetDisplayEventCallback(DisplayEventCallback event_callback)148   void SetDisplayEventCallback(DisplayEventCallback event_callback) {
149     sc_android_src_.SetDisplayEventCallback(std::move(event_callback));
150   }
151 
152   /* returns the processed frame that also includes meta-info such as
153    * success/fail and display number from the guest
154    *
155    * NOTE THAT THIS IS THE ONLY CONSUMER OF THE TWO QUEUES
156    */
OnNextFrame()157   ProcessedFrameType OnNextFrame() { return sc_frame_multiplexer_.Pop(); }
158 
159   /**
160    * ConfUi calls this when it has frames to render
161    *
162    * This won't be called if not by Confirmation UI. This won't affect rendering
163    * Android guest frames if Confirmation UI HAL is not active.
164    *
165    */
RenderConfirmationUi(std::uint32_t display_number,std::uint32_t frame_width,std::uint32_t frame_height,std::uint32_t frame_fourcc_format,std::uint32_t frame_stride_bytes,std::uint8_t * frame_bytes)166   bool RenderConfirmationUi(std::uint32_t display_number,
167                             std::uint32_t frame_width,
168                             std::uint32_t frame_height,
169                             std::uint32_t frame_fourcc_format,
170                             std::uint32_t frame_stride_bytes,
171                             std::uint8_t* frame_bytes) override {
172     render_confui_cnt_++;
173     // wait callback is not set, the streamer is not ready
174     // return with LOG(ERROR)
175     if (!IsCallbackSet()) {
176       ConfUiLog(ERROR) << "callback function to process frames is not yet set";
177       return false;
178     }
179     ProcessedFrameType processed_frame;
180     auto this_thread_name = cuttlefish::confui::thread::GetName();
181     ConfUiLog(DEBUG) << this_thread_name
182                      << "is sending a #" + std::to_string(render_confui_cnt_)
183                      << "Conf UI frame";
184     callback_from_streamer_(display_number, frame_width, frame_height,
185                             frame_fourcc_format, frame_stride_bytes,
186                             frame_bytes, processed_frame);
187     // now add processed_frame to the queue
188     sc_frame_multiplexer_.PushToConfUiQueue(std::move(processed_frame));
189     return true;
190   }
191 
192  protected:
193   ScreenConnector() = delete;
194 
195  private:
196   WaylandScreenConnector& sc_android_src_;
197   HostModeCtrl& host_mode_ctrl_;
198   unsigned long long int on_next_frame_cnt_;
199   unsigned long long int render_confui_cnt_;
200   /**
201    * internally has conf ui & android queues.
202    *
203    * multiplexting the two input queues, so the consumer gets one input
204    * at a time from the right queue
205    */
206   FrameMultiplexer sc_frame_multiplexer_;
207   GenerateProcessedFrameCallback callback_from_streamer_;
208   std::mutex
209       streamer_callback_mutex_;  // mutex to set & read callback_from_streamer_
210   std::condition_variable streamer_callback_set_cv_;
211 };
212 
213 }  // namespace cuttlefish
214