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
21 #include <libyuv.h>
22
23 namespace cuttlefish {
DisplayHandler(std::shared_ptr<webrtc_streaming::VideoSink> display_sink,ScreenConnector * screen_connector)24 DisplayHandler::DisplayHandler(
25 std::shared_ptr<webrtc_streaming::VideoSink> display_sink,
26 ScreenConnector* screen_connector)
27 : display_sink_(display_sink), screen_connector_(screen_connector) {}
28
Loop()29 [[noreturn]] void DisplayHandler::Loop() {
30 std::uint32_t frame_num = 0;
31 for (;;) {
32 auto have_frame = screen_connector_->OnFrameAfter(
33 frame_num, [&frame_num, this](std::uint32_t fn, std::uint8_t* frame) {
34 frame_num = fn;
35 std::shared_ptr<CvdVideoFrameBuffer> buffer(
36 new CvdVideoFrameBuffer(screen_connector_->ScreenWidth(),
37 screen_connector_->ScreenHeight()));
38 libyuv::ABGRToI420(frame, screen_connector_->ScreenStride(),
39 buffer->DataY(), buffer->StrideY(),
40 buffer->DataU(), buffer->StrideU(),
41 buffer->DataV(), buffer->StrideV(),
42 screen_connector_->ScreenWidth(),
43 screen_connector_->ScreenHeight());
44 {
45 std::lock_guard<std::mutex> lock(last_buffer_mutex_);
46 last_buffer_ =
47 std::static_pointer_cast<webrtc_streaming::VideoFrameBuffer>(buffer);
48 }
49 });
50 if (have_frame) {
51 SendLastFrame();
52 }
53 }
54 }
55
SendLastFrame()56 void DisplayHandler::SendLastFrame() {
57 std::shared_ptr<webrtc_streaming::VideoFrameBuffer> buffer;
58 {
59 std::lock_guard<std::mutex> lock(last_buffer_mutex_);
60 buffer = last_buffer_;
61 }
62 if (!buffer) {
63 // If a connection request arrives before the first frame is available don't
64 // send any frame.
65 return;
66 }
67 {
68 // SendLastFrame can be called from multiple threads simultaneously, locking
69 // here avoids injecting frames with the timestamps in the wrong order.
70 std::lock_guard<std::mutex> lock(next_frame_mutex_);
71 int64_t time_stamp =
72 std::chrono::duration_cast<std::chrono::microseconds>(
73 std::chrono::system_clock::now().time_since_epoch())
74 .count();
75 display_sink_->OnFrame(buffer, time_stamp);
76 }
77 }
78
79 } // namespace cuttlefish
80