// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia_web/webengine/browser/receiver_session_client.h"
#include "base/functional/bind.h"
#include "components/cast/message_port/fuchsia/message_port_fuchsia.h"
#include "components/cast/message_port/message_port.h"
#include "components/cast_streaming/browser/public/receiver_config.h"
#include "components/cast_streaming/browser/public/receiver_session.h"
#include "components/cast_streaming/common/public/mojom/demuxer_connector.mojom.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/video_decoder_config.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/size.h"
namespace {
constexpr size_t kMaxFrameRate = 30;
} // namespace
ReceiverSessionClient::ReceiverSessionClient(
fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
bool video_only_receiver)
: message_port_request_(std::move(message_port_request)),
video_only_receiver_(video_only_receiver) {
DCHECK(message_port_request_);
}
ReceiverSessionClient::~ReceiverSessionClient() = default;
void ReceiverSessionClient::SetMojoEndpoints(
mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector>
demuxer_connector,
mojo::AssociatedRemote<cast_streaming::mojom::RendererController>
renderer_controller) {
DCHECK(message_port_request_);
// TODO: Add streaming session Constraints based on system capabilities
// (see crbug.com/1013412) and DisplayDescription (see crbug.com/1087520).
// TODO(crbug.com/40185682): Only populate codecs corresponding to those
// called out by build flags.
std::vector<media::VideoCodec> video_codecs;
std::vector<media::AudioCodec> audio_codecs;
// Codecs are set in order of preference for the receiver, i.e. H264 is
// preferred above VP8 in the below code.
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
video_codecs.push_back(media::VideoCodec::kH264);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
video_codecs.push_back(media::VideoCodec::kVP8);
if (!video_only_receiver_) {
audio_codecs.push_back(media::AudioCodec::kOpus);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
audio_codecs.push_back(media::AudioCodec::kAAC);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
}
// TODO(crbug.com/40241121): Set config.remoting to expose the device as a
// valid remoting endpoint when |renderer_controller| is set.
cast_streaming::ReceiverConfig config(std::move(video_codecs),
std::move(audio_codecs));
gfx::Size display_resolution =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size();
config.video_limits.push_back(cast_streaming::ReceiverConfig::VideoLimits{
.max_pixels_per_second =
static_cast<int>(display_resolution.width() *
display_resolution.height() * kMaxFrameRate),
.max_dimensions = gfx::Rect(display_resolution),
.max_frame_rate = kMaxFrameRate});
config.display_description = cast_streaming::ReceiverConfig::Display{
.dimensions = gfx::Rect(display_resolution),
.max_frame_rate = kMaxFrameRate,
.can_scale_content = true};
receiver_session_ = cast_streaming::ReceiverSession::Create(
config,
base::BindOnce(
[](fidl::InterfaceRequest<fuchsia::web::MessagePort> port)
-> std::unique_ptr<cast_api_bindings::MessagePort> {
return cast_api_bindings::MessagePortFuchsia::Create(
std::move(port));
},
std::move(message_port_request_)));
if (renderer_controller) {
receiver_session_->StartStreamingAsync(std::move(demuxer_connector),
std::move(renderer_controller));
} else {
receiver_session_->StartStreamingAsync(std::move(demuxer_connector));
}
}
bool ReceiverSessionClient::HasReceiverSession() {
return !!receiver_session_;
}