blob: 49e52535892035b1ee87a568caf342c9148daf97 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <thread>
#include <type_traits>
#include <android-base/logging.h>
#include "common/libs/confui/confui.h"
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/size_utils.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/confui/host_mode_ctrl.h"
#include "host/libs/confui/host_utils.h"
#include "host/libs/screen_connector/screen_connector_common.h"
#include "host/libs/screen_connector/screen_connector_multiplexer.h"
#include "host/libs/screen_connector/screen_connector_queue.h"
#include "host/libs/screen_connector/wayland_screen_connector.h"
namespace cuttlefish {
template <typename ProcessedFrameType>
class ScreenConnector : public ScreenConnectorInfo,
public ScreenConnectorFrameRenderer {
public:
static_assert(cuttlefish::is_movable<ProcessedFrameType>::value,
"ProcessedFrameType should be std::move-able.");
static_assert(std::is_base_of<ScreenConnectorFrameInfo, ProcessedFrameType>::value,
"ProcessedFrameType should inherit ScreenConnectorFrameInfo");
using FrameMultiplexer = ScreenConnectorInputMultiplexer<ProcessedFrameType>;
/**
* This is the type of the callback function WebRTC is supposed to provide
* ScreenConnector with.
*
* The callback function is how a raw bytes frame should be processed for
* WebRTC
*
*/
using GenerateProcessedFrameCallback = std::function<void(
std::uint32_t /*display_number*/, std::uint32_t /*frame_width*/,
std::uint32_t /*frame_height*/, std::uint32_t /*frame_stride_bytes*/,
std::uint8_t* /*frame_bytes*/,
/* ScImpl enqueues this type into the Q */
ProcessedFrameType& msg)>;
static std::unique_ptr<ScreenConnector<ProcessedFrameType>> Get(
const int frames_fd, HostModeCtrl& host_mode_ctrl) {
auto config = cuttlefish::CuttlefishConfig::Get();
ScreenConnector<ProcessedFrameType>* raw_ptr = nullptr;
if (config->gpu_mode() == cuttlefish::kGpuModeDrmVirgl ||
config->gpu_mode() == cuttlefish::kGpuModeGfxStream ||
config->gpu_mode() == cuttlefish::kGpuModeGuestSwiftshader) {
raw_ptr = new ScreenConnector<ProcessedFrameType>(
std::make_unique<WaylandScreenConnector>(frames_fd), host_mode_ctrl);
} else {
LOG(FATAL) << "Invalid gpu mode: " << config->gpu_mode();
}
return std::unique_ptr<ScreenConnector<ProcessedFrameType>>(raw_ptr);
}
virtual ~ScreenConnector() = default;
/**
* set the callback function to be eventually used by Wayland-Based
* Connector
*
*/
void SetCallback(GenerateProcessedFrameCallback&& frame_callback) {
std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
callback_from_streamer_ = std::move(frame_callback);
streamer_callback_set_cv_.notify_all();
sc_android_src_->SetFrameCallback(
[this](std::uint32_t display_number, std::uint32_t frame_w,
std::uint32_t frame_h, std::uint32_t frame_stride_bytes,
std::uint8_t* frame_bytes) {
const bool is_confui_mode = host_mode_ctrl_.IsConfirmatioUiMode();
if (is_confui_mode) {
return;
}
ProcessedFrameType processed_frame;
{
std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
callback_from_streamer_(display_number, frame_w, frame_h,
frame_stride_bytes, frame_bytes,
processed_frame);
}
sc_frame_multiplexer_.PushToAndroidQueue(std::move(processed_frame));
});
}
bool IsCallbackSet() const override {
if (callback_from_streamer_) {
return true;
}
return false;
}
/* returns the processed frame that also includes meta-info such as success/fail
* and display number from the guest
*
* NOTE THAT THIS IS THE ONLY CONSUMER OF THE TWO QUEUES
*/
ProcessedFrameType OnNextFrame() { return sc_frame_multiplexer_.Pop(); }
/**
* ConfUi calls this when it has frames to render
*
* This won't be called if not by Confirmation UI. This won't affect rendering
* Android guest frames if Confirmation UI HAL is not active.
*
*/
bool RenderConfirmationUi(std::uint32_t display_number,
std::uint32_t frame_width,
std::uint32_t frame_height,
std::uint32_t frame_stride_bytes,
std::uint8_t* frame_bytes) override {
render_confui_cnt_++;
// wait callback is not set, the streamer is not ready
// return with LOG(ERROR)
if (!IsCallbackSet()) {
ConfUiLog(ERROR) << "callback function to process frames is not yet set";
return false;
}
ProcessedFrameType processed_frame;
auto this_thread_name = cuttlefish::confui::thread::GetName();
ConfUiLog(DEBUG) << this_thread_name
<< "is sending a #" + std::to_string(render_confui_cnt_)
<< "Conf UI frame";
callback_from_streamer_(display_number, frame_width, frame_height,
frame_stride_bytes, frame_bytes, processed_frame);
// now add processed_frame to the queue
sc_frame_multiplexer_.PushToConfUiQueue(std::move(processed_frame));
return true;
}
protected:
ScreenConnector(std::unique_ptr<WaylandScreenConnector>&& impl,
HostModeCtrl& host_mode_ctrl)
: sc_android_src_{std::move(impl)},
host_mode_ctrl_{host_mode_ctrl},
on_next_frame_cnt_{0},
render_confui_cnt_{0},
sc_frame_multiplexer_{host_mode_ctrl_} {}
ScreenConnector() = delete;
private:
std::unique_ptr<WaylandScreenConnector> sc_android_src_;
HostModeCtrl& host_mode_ctrl_;
unsigned long long int on_next_frame_cnt_;
unsigned long long int render_confui_cnt_;
/**
* internally has conf ui & android queues.
*
* multiplexting the two input queues, so the consumer gets one input
* at a time from the right queue
*/
FrameMultiplexer sc_frame_multiplexer_;
GenerateProcessedFrameCallback callback_from_streamer_;
std::mutex streamer_callback_mutex_; // mutex to set & read callback_from_streamer_
std::condition_variable streamer_callback_set_cv_;
};
} // namespace cuttlefish