• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 #include "host/frontend/webrtc/display_handler.h"
18 
19 #include <chrono>
20 #include <memory>
21 
22 #include <drm/drm_fourcc.h>
23 #include <libyuv.h>
24 
25 #include "host/frontend/webrtc/libdevice/streamer.h"
26 #include "host/libs/screen_connector/composition_manager.h"
27 
28 namespace cuttlefish {
29 
DisplayHandler(webrtc_streaming::Streamer & streamer,ScreenshotHandler & screenshot_handler,ScreenConnector & screen_connector,std::optional<std::unique_ptr<CompositionManager>> composition_manager)30 DisplayHandler::DisplayHandler(
31     webrtc_streaming::Streamer& streamer, ScreenshotHandler& screenshot_handler,
32     ScreenConnector& screen_connector,
33     std::optional<std::unique_ptr<CompositionManager>> composition_manager)
34     : composition_manager_(std::move(composition_manager)),
35       streamer_(streamer),
36       screenshot_handler_(screenshot_handler),
37       screen_connector_(screen_connector),
38       frame_repeater_([this]() { RepeatFramesPeriodically(); }) {
39   screen_connector_.SetCallback(GetScreenConnectorCallback());
__anon56ead1400202(const DisplayEvent& event) 40   screen_connector_.SetDisplayEventCallback([this](const DisplayEvent& event) {
41     std::visit(
42         [this](auto&& e) {
43           using T = std::decay_t<decltype(e)>;
44           if constexpr (std::is_same_v<DisplayCreatedEvent, T>) {
45             LOG(VERBOSE) << "Display:" << e.display_number << " created "
46                          << " w:" << e.display_width
47                          << " h:" << e.display_height;
48 
49             const auto display_number = e.display_number;
50             const std::string display_id =
51                 "display_" + std::to_string(e.display_number);
52             auto display = streamer_.AddDisplay(display_id, e.display_width,
53                                                 e.display_height, 160, true);
54             if (!display) {
55               LOG(ERROR) << "Failed to create display.";
56               return;
57             }
58 
59             std::lock_guard<std::mutex> lock(send_mutex_);
60             display_sinks_[display_number] = display;
61             if (composition_manager_.has_value()) {
62               composition_manager_.value()->OnDisplayCreated(e);
63             }
64           } else if constexpr (std::is_same_v<DisplayDestroyedEvent, T>) {
65             LOG(VERBOSE) << "Display:" << e.display_number << " destroyed.";
66 
67             const auto display_number = e.display_number;
68             const auto display_id =
69                 "display_" + std::to_string(e.display_number);
70             std::lock_guard<std::mutex> lock(send_mutex_);
71             display_sinks_.erase(display_number);
72             streamer_.RemoveDisplay(display_id);
73           } else {
74             static_assert("Unhandled display event.");
75           }
76         },
77         event);
78   });
79 }
80 
~DisplayHandler()81 DisplayHandler::~DisplayHandler() {
82   {
83     std::lock_guard lock(repeater_state_mutex_);
84     repeater_state_ = RepeaterState::STOPPED;
85     repeater_state_condvar_.notify_one();
86   }
87   frame_repeater_.join();
88 }
89 
90 DisplayHandler::GenerateProcessedFrameCallback
GetScreenConnectorCallback()91 DisplayHandler::GetScreenConnectorCallback() {
92   // only to tell the producer how to create a ProcessedFrame to cache into the
93   // queue
94   auto& composition_manager = composition_manager_;
95   DisplayHandler::GenerateProcessedFrameCallback callback =
96       [&composition_manager](
97           std::uint32_t display_number, std::uint32_t frame_width,
98           std::uint32_t frame_height, std::uint32_t frame_fourcc_format,
99           std::uint32_t frame_stride_bytes, std::uint8_t* frame_pixels,
100           WebRtcScProcessedFrame& processed_frame) {
101         processed_frame.display_number_ = display_number;
102         processed_frame.buf_ =
103             std::make_unique<CvdVideoFrameBuffer>(frame_width, frame_height);
104         if (composition_manager.has_value()) {
105           composition_manager.value()->OnFrame(
106               display_number, frame_width, frame_height, frame_fourcc_format,
107               frame_stride_bytes, frame_pixels);
108         }
109         if (frame_fourcc_format == DRM_FORMAT_ARGB8888 ||
110             frame_fourcc_format == DRM_FORMAT_XRGB8888) {
111           libyuv::ARGBToI420(
112               frame_pixels, frame_stride_bytes, processed_frame.buf_->DataY(),
113               processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
114               processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
115               processed_frame.buf_->StrideV(), frame_width, frame_height);
116           processed_frame.is_success_ = true;
117         } else if (frame_fourcc_format == DRM_FORMAT_ABGR8888 ||
118                    frame_fourcc_format == DRM_FORMAT_XBGR8888) {
119           libyuv::ABGRToI420(
120               frame_pixels, frame_stride_bytes, processed_frame.buf_->DataY(),
121               processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
122               processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
123               processed_frame.buf_->StrideV(), frame_width, frame_height);
124           processed_frame.is_success_ = true;
125         } else {
126           processed_frame.is_success_ = false;
127         }
128       };
129   return callback;
130 }
131 
Loop()132 [[noreturn]] void DisplayHandler::Loop() {
133   for (;;) {
134     auto processed_frame = screen_connector_.OnNextFrame();
135 
136     std::shared_ptr<CvdVideoFrameBuffer> buffer =
137         std::move(processed_frame.buf_);
138 
139     const uint32_t display_number = processed_frame.display_number_;
140     {
141       std::lock_guard<std::mutex> lock(last_buffers_mutex_);
142       display_last_buffers_[display_number] =
143           std::make_shared<BufferInfo>(BufferInfo{
144               .last_sent_time_stamp = std::chrono::system_clock::now(),
145               .buffer =
146                   std::static_pointer_cast<webrtc_streaming::VideoFrameBuffer>(
147                       buffer),
148           });
149     }
150     if (processed_frame.is_success_) {
151       SendLastFrame(display_number);
152     }
153   }
154 }
155 
SendLastFrame(std::optional<uint32_t> display_number)156 void DisplayHandler::SendLastFrame(std::optional<uint32_t> display_number) {
157   std::map<uint32_t, std::shared_ptr<BufferInfo>> buffers;
158   {
159     std::lock_guard<std::mutex> lock(last_buffers_mutex_);
160     if (display_number) {
161       // Resend the last buffer for a single display.
162       auto last_buffer_it = display_last_buffers_.find(*display_number);
163       if (last_buffer_it == display_last_buffers_.end()) {
164         return;
165       }
166       auto& last_buffer_info = last_buffer_it->second;
167       if (!last_buffer_info) {
168         return;
169       }
170       auto& last_buffer = last_buffer_info->buffer;
171       if (!last_buffer) {
172         return;
173       }
174       buffers[*display_number] = last_buffer_info;
175     } else {
176       // Resend the last buffer for all displays.
177       buffers = display_last_buffers_;
178     }
179   }
180   if (buffers.empty()) {
181     // If a connection request arrives before the first frame is available don't
182     // send any frame.
183     return;
184   }
185   SendBuffers(buffers);
186 }
187 
SendBuffers(std::map<uint32_t,std::shared_ptr<BufferInfo>> buffers)188 void DisplayHandler::SendBuffers(
189     std::map<uint32_t, std::shared_ptr<BufferInfo>> buffers) {
190   // SendBuffers can be called from multiple threads simultaneously, locking
191   // here avoids injecting frames with the timestamps in the wrong order and
192   // protects writing the BufferInfo timestamps.
193   std::lock_guard<std::mutex> lock(send_mutex_);
194   auto time_stamp = std::chrono::system_clock::now();
195   int64_t time_stamp_since_epoch =
196       std::chrono::duration_cast<std::chrono::microseconds>(
197           time_stamp.time_since_epoch())
198           .count();
199 
200   for (const auto& [display_number, buffer_info] : buffers) {
201     screenshot_handler_.OnFrame(display_number, buffer_info->buffer);
202 
203     auto it = display_sinks_.find(display_number);
204     if (it != display_sinks_.end()) {
205       it->second->OnFrame(buffer_info->buffer, time_stamp_since_epoch);
206       buffer_info->last_sent_time_stamp = time_stamp;
207     }
208   }
209 }
210 
RepeatFramesPeriodically()211 void DisplayHandler::RepeatFramesPeriodically() {
212   // SendBuffers can be called from multiple threads simultaneously, locking
213   // here avoids injecting frames with the timestamps in the wrong order and
214   // protects writing the BufferInfo timestamps.
215   const std::chrono::milliseconds kRepeatingInterval(20);
216   auto next_send = std::chrono::system_clock::now() + kRepeatingInterval;
217   while (true) {
218     {
219       std::unique_lock lock(repeater_state_mutex_);
220       if (repeater_state_ == RepeaterState::STOPPED) {
221         break;
222       }
223       if (num_active_clients_ > 0) {
224         bool stopped =
225             repeater_state_condvar_.wait_until(lock, next_send, [this]() {
226               // Wait until time interval completes or asked to stop. Continue
227               // waiting even if the number of active clients drops to 0.
228               return repeater_state_ == RepeaterState::STOPPED;
229             });
230         if (stopped || num_active_clients_ == 0) {
231           continue;
232         }
233       } else {
234         repeater_state_condvar_.wait(lock, [this]() {
235           // Wait until asked to stop or have clients
236           return repeater_state_ == RepeaterState::STOPPED ||
237                  num_active_clients_ > 0;
238         });
239         // Need to break the loop if stopped or wait for the interval if have
240         // clients.
241         continue;
242       }
243     }
244 
245     std::map<uint32_t, std::shared_ptr<BufferInfo>> buffers;
246     {
247       std::lock_guard last_buffers_lock(last_buffers_mutex_);
248       auto time_stamp = std::chrono::system_clock::now();
249 
250       for (auto& [display_number, buffer_info] : display_last_buffers_) {
251         if (time_stamp >
252             buffer_info->last_sent_time_stamp + kRepeatingInterval) {
253           if (composition_manager_.has_value()) {
254             composition_manager_.value()->ComposeFrame(
255                 display_number, std::static_pointer_cast<CvdVideoFrameBuffer>(
256                                     buffer_info->buffer));
257           }
258           buffers[display_number] = buffer_info;
259         }
260       }
261     }
262     SendBuffers(buffers);
263     {
264       std::lock_guard last_buffers_lock(last_buffers_mutex_);
265       for (const auto& [_, buffer_info] : display_last_buffers_) {
266         next_send = std::min(
267             next_send, buffer_info->last_sent_time_stamp + kRepeatingInterval);
268       }
269     }
270   }
271 }
272 
AddDisplayClient()273 void DisplayHandler::AddDisplayClient() {
274   std::lock_guard lock(repeater_state_mutex_);
275   if (++num_active_clients_ == 1) {
276     repeater_state_condvar_.notify_one();
277   };
278 }
279 
RemoveDisplayClient()280 void DisplayHandler::RemoveDisplayClient() {
281   std::lock_guard lock(repeater_state_mutex_);
282   --num_active_clients_;
283 }
284 
285 }  // namespace cuttlefish
286