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 #pragma once
18 
19 #include <chrono>
20 #include <memory>
21 #include <mutex>
22 #include <optional>
23 #include <thread>
24 
25 #include "host/frontend/webrtc/cvd_video_frame_buffer.h"
26 #include "host/frontend/webrtc/libdevice/video_sink.h"
27 #include "host/frontend/webrtc/screenshot_handler.h"
28 #include "host/libs/screen_connector/screen_connector.h"
29 
30 namespace cuttlefish {
31 /**
32  * ScreenConnectorImpl will generate this, and enqueue
33  *
34  * It's basically a (processed) frame, so it:
35  *   must be efficiently std::move-able
36  * Also, for the sake of algorithm simplicity:
37  *   must be default-constructable & assignable
38  *
39  */
40 struct WebRtcScProcessedFrame : public ScreenConnectorFrameInfo {
41   // must support move semantic
42   std::unique_ptr<CvdVideoFrameBuffer> buf_;
CloneWebRtcScProcessedFrame43   std::unique_ptr<WebRtcScProcessedFrame> Clone() {
44     // copy internal buffer, not move
45     CvdVideoFrameBuffer* new_buffer = new CvdVideoFrameBuffer(*(buf_.get()));
46     auto cloned_frame = std::make_unique<WebRtcScProcessedFrame>();
47     cloned_frame->buf_ = std::unique_ptr<CvdVideoFrameBuffer>(new_buffer);
48     return cloned_frame;
49   }
50 };
51 
52 namespace webrtc_streaming {
53 class Streamer;
54 }  // namespace webrtc_streaming
55 
56 class DisplayHandler {
57  public:
58   using ScreenConnector = cuttlefish::ScreenConnector<WebRtcScProcessedFrame>;
59   using GenerateProcessedFrameCallback =
60       ScreenConnector::GenerateProcessedFrameCallback;
61   using WebRtcScProcessedFrame = cuttlefish::WebRtcScProcessedFrame;
62 
63   DisplayHandler(webrtc_streaming::Streamer& streamer,
64                  ScreenshotHandler& screenshot_handler,
65                  ScreenConnector& screen_connector);
66   ~DisplayHandler();
67 
68   [[noreturn]] void Loop();
69 
70   // If std::nullopt, send last frame for all displays.
71   void SendLastFrame(std::optional<uint32_t> display_number);
72 
73   void AddDisplayClient();
74   void RemoveDisplayClient();
75 
76  private:
77   struct BufferInfo {
78     std::chrono::system_clock::time_point last_sent_time_stamp;
79     std::shared_ptr<webrtc_streaming::VideoFrameBuffer> buffer;
80   };
81   enum class RepeaterState {
82     RUNNING,
83     STOPPED,
84   };
85 
86   GenerateProcessedFrameCallback GetScreenConnectorCallback();
87   void SendBuffers(std::map<uint32_t, std::shared_ptr<BufferInfo>> buffers);
88   void RepeatFramesPeriodically();
89 
90   std::map<uint32_t, std::shared_ptr<webrtc_streaming::VideoSink>>
91       display_sinks_;
92   webrtc_streaming::Streamer& streamer_;
93   ScreenshotHandler& screenshot_handler_;
94   ScreenConnector& screen_connector_;
95   std::map<uint32_t, std::shared_ptr<BufferInfo>> display_last_buffers_;
96   std::mutex last_buffers_mutex_;
97   std::mutex send_mutex_;
98   std::thread frame_repeater_;
99   // Protected by repeater_state_mutex
100   RepeaterState repeater_state_ = RepeaterState::RUNNING;
101   // Protected by repeater_state_mutex
102   int num_active_clients_ = 0;
103   std::mutex repeater_state_mutex_;
104   std::condition_variable repeater_state_condvar_;
105 };
106 }  // namespace cuttlefish
107