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