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