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