• 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 <functional>
21 #include <memory>
22 
23 #include <libyuv.h>
24 
25 namespace cuttlefish {
DisplayHandler(std::vector<std::shared_ptr<webrtc_streaming::VideoSink>> display_sinks,ScreenConnector & screen_connector)26 DisplayHandler::DisplayHandler(
27     std::vector<std::shared_ptr<webrtc_streaming::VideoSink>> display_sinks,
28     ScreenConnector& screen_connector)
29     : display_sinks_(display_sinks), screen_connector_(screen_connector) {
30   screen_connector_.SetCallback(std::move(GetScreenConnectorCallback()));
31 }
32 
GetScreenConnectorCallback()33 DisplayHandler::GenerateProcessedFrameCallback DisplayHandler::GetScreenConnectorCallback() {
34     // only to tell the producer how to create a ProcessedFrame to cache into the queue
35     DisplayHandler::GenerateProcessedFrameCallback callback =
36         [](std::uint32_t display_number, std::uint32_t frame_width,
37            std::uint32_t frame_height, std::uint32_t frame_stride_bytes,
38            std::uint8_t* frame_pixels,
39            WebRtcScProcessedFrame& processed_frame) {
40           processed_frame.display_number_ = display_number;
41           processed_frame.buf_ =
42               std::make_unique<CvdVideoFrameBuffer>(frame_width, frame_height);
43           libyuv::ABGRToI420(
44               frame_pixels, frame_stride_bytes, processed_frame.buf_->DataY(),
45               processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
46               processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
47               processed_frame.buf_->StrideV(), frame_width, frame_height);
48           processed_frame.is_success_ = true;
49         };
50     return callback;
51 }
52 
Loop()53 [[noreturn]] void DisplayHandler::Loop() {
54   for (;;) {
55     auto processed_frame = screen_connector_.OnNextFrame();
56     // processed_frame has display number from the guest
57     {
58       std::lock_guard<std::mutex> lock(last_buffer_mutex_);
59       std::shared_ptr<CvdVideoFrameBuffer> buffer = std::move(processed_frame.buf_);
60       last_buffer_display_ = processed_frame.display_number_;
61       last_buffer_ =
62           std::static_pointer_cast<webrtc_streaming::VideoFrameBuffer>(buffer);
63     }
64     if (processed_frame.is_success_) {
65       SendLastFrame();
66     }
67   }
68 }
69 
SendLastFrame()70 void DisplayHandler::SendLastFrame() {
71   std::shared_ptr<webrtc_streaming::VideoFrameBuffer> buffer;
72   std::uint32_t buffer_display;
73   {
74     std::lock_guard<std::mutex> lock(last_buffer_mutex_);
75     buffer = last_buffer_;
76     buffer_display = last_buffer_display_;
77   }
78   if (!buffer) {
79     // If a connection request arrives before the first frame is available don't
80     // send any frame.
81     return;
82   }
83   {
84     // SendLastFrame can be called from multiple threads simultaneously, locking
85     // here avoids injecting frames with the timestamps in the wrong order.
86     std::lock_guard<std::mutex> lock(next_frame_mutex_);
87     int64_t time_stamp =
88         std::chrono::duration_cast<std::chrono::microseconds>(
89             std::chrono::system_clock::now().time_since_epoch())
90             .count();
91     display_sinks_[buffer_display]->OnFrame(buffer, time_stamp);
92   }
93 }
94 }  // namespace cuttlefish
95