1 /* 2 * Copyright (C) 2021 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 <cstdint> 20 21 #include "common/libs/concurrency/multiplexer.h" 22 #include "common/libs/confui/confui.h" 23 24 #include "host/libs/confui/host_mode_ctrl.h" 25 #include "host/libs/screen_connector/screen_connector_queue.h" 26 27 namespace cuttlefish { 28 template <typename ProcessedFrameType> 29 class ScreenConnectorInputMultiplexer { 30 using Queue = ScreenConnectorQueue<ProcessedFrameType>; 31 using Multiplexer = Multiplexer<ProcessedFrameType, Queue>; 32 33 public: ScreenConnectorInputMultiplexer(HostModeCtrl & host_mode_ctrl)34 ScreenConnectorInputMultiplexer(HostModeCtrl& host_mode_ctrl) 35 : host_mode_ctrl_(host_mode_ctrl) { 36 sc_android_queue_id_ = 37 multiplexer_.RegisterQueue(multiplexer_.CreateQueue(/* q size */ 2)); 38 sc_confui_queue_id_ = 39 multiplexer_.RegisterQueue(multiplexer_.CreateQueue(/* q size */ 2)); 40 } 41 42 virtual ~ScreenConnectorInputMultiplexer() = default; 43 PushToAndroidQueue(ProcessedFrameType && t)44 void PushToAndroidQueue(ProcessedFrameType&& t) { 45 multiplexer_.Push(sc_android_queue_id_, std::move(t)); 46 } 47 PushToConfUiQueue(ProcessedFrameType && t)48 void PushToConfUiQueue(ProcessedFrameType&& t) { 49 multiplexer_.Push(sc_confui_queue_id_, std::move(t)); 50 } 51 52 // customize Pop() Pop()53 ProcessedFrameType Pop() { 54 on_next_frame_cnt_++; 55 56 // is_discard_frame is thread-specific 57 bool is_discard_frame = false; 58 59 // callback to select the queue index, and update is_discard_frame 60 auto selector = [this, &is_discard_frame]() -> int { 61 if (multiplexer_.IsEmpty(sc_android_queue_id_)) { 62 ConfUiLog(VERBOSE) 63 << "Streamer gets Conf UI frame with host ctrl mode = " 64 << static_cast<std::uint32_t>(host_mode_ctrl_.GetMode()) 65 << " and cnd = #" << on_next_frame_cnt_; 66 return sc_confui_queue_id_; 67 } 68 auto mode = host_mode_ctrl_.GetMode(); 69 if (mode != HostModeCtrl::ModeType::kAndroidMode) { 70 // AndroidFrameFetchingLoop could have added 1 or 2 frames 71 // before it becomes Conf UI mode. 72 ConfUiLog(VERBOSE) 73 << "Streamer ignores Android frame with host ctrl mode =" 74 << static_cast<std::uint32_t>(mode) << "and cnd = #" 75 << on_next_frame_cnt_; 76 is_discard_frame = true; 77 } 78 ConfUiLog(VERBOSE) << "Streamer gets Android frame with host ctrl mode =" 79 << static_cast<std::uint32_t>(mode) << "and cnd = #" 80 << on_next_frame_cnt_; 81 return sc_android_queue_id_; 82 }; 83 84 while (true) { 85 ConfUiLog(VERBOSE) << "Streamer waiting Semaphore with host ctrl mode =" 86 << static_cast<std::uint32_t>( 87 host_mode_ctrl_.GetMode()) 88 << " and cnd = #" << on_next_frame_cnt_; 89 auto processed_frame = multiplexer_.Pop(selector); 90 if (!is_discard_frame) { 91 return processed_frame; 92 } 93 is_discard_frame = false; 94 } 95 } 96 97 private: 98 HostModeCtrl& host_mode_ctrl_; 99 Multiplexer multiplexer_; 100 unsigned long long int on_next_frame_cnt_; 101 int sc_android_queue_id_; 102 int sc_confui_queue_id_; 103 }; 104 } // end of namespace cuttlefish 105