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::kGpuModeGuestSwiftshader}; 78 if (!Contains(valid_gpu_modes, instance.gpu_mode())) { 79 LOG(FATAL) << "Invalid gpu mode: " << instance.gpu_mode(); 80 } 81 } 82 83 /** 84 * This is the type of the callback function WebRTC is supposed to provide 85 * ScreenConnector with. 86 * 87 * The callback function is how a raw bytes frame should be processed for 88 * WebRTC 89 * 90 */ 91 using GenerateProcessedFrameCallback = std::function<void( 92 std::uint32_t /*display_number*/, std::uint32_t /*frame_width*/, 93 std::uint32_t /*frame_height*/, std::uint32_t /*frame_fourcc_format*/, 94 std::uint32_t /*frame_stride_bytes*/, std::uint8_t* /*frame_bytes*/, 95 /* ScImpl enqueues this type into the Q */ 96 ProcessedFrameType& msg)>; 97 98 virtual ~ScreenConnector() = default; 99 100 /** 101 * set the callback function to be eventually used by Wayland-Based 102 * Connector 103 * 104 */ SetCallback(GenerateProcessedFrameCallback && frame_callback)105 void SetCallback(GenerateProcessedFrameCallback&& frame_callback) { 106 std::lock_guard<std::mutex> lock(streamer_callback_mutex_); 107 callback_from_streamer_ = std::move(frame_callback); 108 streamer_callback_set_cv_.notify_all(); 109 110 sc_android_src_.SetFrameCallback( 111 [this](std::uint32_t display_number, std::uint32_t frame_w, 112 std::uint32_t frame_h, std::uint32_t frame_fourcc_format, 113 std::uint32_t frame_stride_bytes, std::uint8_t* frame_bytes) { 114 const bool is_confui_mode = host_mode_ctrl_.IsConfirmatioUiMode(); 115 if (is_confui_mode) { 116 return; 117 } 118 119 ProcessedFrameType processed_frame; 120 121 { 122 std::lock_guard<std::mutex> lock(streamer_callback_mutex_); 123 callback_from_streamer_(display_number, frame_w, frame_h, 124 frame_fourcc_format, frame_stride_bytes, 125 frame_bytes, processed_frame); 126 } 127 128 sc_frame_multiplexer_.PushToAndroidQueue(std::move(processed_frame)); 129 }); 130 } 131 IsCallbackSet()132 bool IsCallbackSet() const override { 133 if (callback_from_streamer_) { 134 return true; 135 } 136 return false; 137 } 138 SetDisplayEventCallback(DisplayEventCallback event_callback)139 void SetDisplayEventCallback(DisplayEventCallback event_callback) { 140 sc_android_src_.SetDisplayEventCallback(std::move(event_callback)); 141 } 142 143 /* returns the processed frame that also includes meta-info such as 144 * success/fail and display number from the guest 145 * 146 * NOTE THAT THIS IS THE ONLY CONSUMER OF THE TWO QUEUES 147 */ OnNextFrame()148 ProcessedFrameType OnNextFrame() { return sc_frame_multiplexer_.Pop(); } 149 150 /** 151 * ConfUi calls this when it has frames to render 152 * 153 * This won't be called if not by Confirmation UI. This won't affect rendering 154 * Android guest frames if Confirmation UI HAL is not active. 155 * 156 */ 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)157 bool RenderConfirmationUi(std::uint32_t display_number, 158 std::uint32_t frame_width, 159 std::uint32_t frame_height, 160 std::uint32_t frame_fourcc_format, 161 std::uint32_t frame_stride_bytes, 162 std::uint8_t* frame_bytes) override { 163 render_confui_cnt_++; 164 // wait callback is not set, the streamer is not ready 165 // return with LOG(ERROR) 166 if (!IsCallbackSet()) { 167 ConfUiLog(ERROR) << "callback function to process frames is not yet set"; 168 return false; 169 } 170 ProcessedFrameType processed_frame; 171 auto this_thread_name = cuttlefish::confui::thread::GetName(); 172 ConfUiLog(DEBUG) << this_thread_name 173 << "is sending a #" + std::to_string(render_confui_cnt_) 174 << "Conf UI frame"; 175 callback_from_streamer_(display_number, frame_width, frame_height, 176 frame_fourcc_format, frame_stride_bytes, 177 frame_bytes, processed_frame); 178 // now add processed_frame to the queue 179 sc_frame_multiplexer_.PushToConfUiQueue(std::move(processed_frame)); 180 return true; 181 } 182 183 protected: 184 ScreenConnector() = delete; 185 186 private: 187 WaylandScreenConnector& sc_android_src_; 188 HostModeCtrl& host_mode_ctrl_; 189 unsigned long long int on_next_frame_cnt_; 190 unsigned long long int render_confui_cnt_; 191 /** 192 * internally has conf ui & android queues. 193 * 194 * multiplexting the two input queues, so the consumer gets one input 195 * at a time from the right queue 196 */ 197 FrameMultiplexer sc_frame_multiplexer_; 198 GenerateProcessedFrameCallback callback_from_streamer_; 199 std::mutex 200 streamer_callback_mutex_; // mutex to set & read callback_from_streamer_ 201 std::condition_variable streamer_callback_set_cv_; 202 }; 203 204 } // namespace cuttlefish 205