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