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