1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
// 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 "components/cast_receiver/browser/streaming_receiver_session_client.h"
#include <algorithm>
#include <utility>
#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/task/sequenced_task_runner.h"
#include "components/cast/message_port/platform_message_port.h"
#include "components/cast_receiver/browser/streaming_controller_base.h"
#include "components/cast_streaming/common/public/cast_streaming_url.h"
#include "media/base/video_decoder_config.h"
namespace cast_receiver {
constexpr base::TimeDelta
StreamingReceiverSessionClient::kMaxAVSettingsWaitTime;
StreamingReceiverSessionClient::StreamingReceiverSessionClient(
scoped_refptr<base::SequencedTaskRunner> task_runner,
network::NetworkContextGetter network_context_getter,
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
content::WebContents* web_contents,
Handler* handler,
cast_receiver::StreamingConfigManager* config_manager,
bool supports_audio,
bool supports_video)
: StreamingReceiverSessionClient(
std::move(task_runner),
std::move(network_context_getter),
StreamingControllerBase::Create(std::move(message_port),
web_contents),
handler,
config_manager,
supports_audio,
supports_video) {}
StreamingReceiverSessionClient::StreamingReceiverSessionClient(
scoped_refptr<base::SequencedTaskRunner> task_runner,
network::NetworkContextGetter network_context_getter,
std::unique_ptr<StreamingController> streaming_controller,
Handler* handler,
cast_receiver::StreamingConfigManager* config_manager,
bool supports_audio,
bool supports_video)
: handler_(handler),
task_runner_(std::move(task_runner)),
streaming_controller_(std::move(streaming_controller)),
supports_audio_(supports_audio),
supports_video_(supports_video),
weak_factory_(this) {
DCHECK(handler_);
DCHECK(task_runner_);
DCHECK(!network_context_getter.is_null());
DCHECK(config_manager);
cast_streaming::SetNetworkContextGetter(std::move(network_context_getter));
DVLOG(1) << "Streaming Receiver Session start pending...";
config_manager->AddConfigObserver(*this);
if (config_manager->has_config()) {
// TODO(crbug.com/1359568): This may not behave correctly if the config is
// updated before the pushed task runs.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&StreamingReceiverSessionClient::OnStreamingConfigSet,
weak_factory_.GetWeakPtr(), config_manager->config()));
return;
}
task_runner_->PostDelayedTask(
FROM_HERE,
base::BindOnce(&StreamingReceiverSessionClient::VerifyAVSettingsReceived,
weak_factory_.GetWeakPtr()),
kMaxAVSettingsWaitTime);
}
StreamingReceiverSessionClient::~StreamingReceiverSessionClient() {
DVLOG(1) << "StreamingReceiverSessionClient state when destroyed"
<< "\n\tIs Healthy: " << is_healthy()
<< "\n\tLaunch called: " << is_streaming_launch_pending()
<< "\n\tAV Settings Received: " << has_received_av_settings();
cast_streaming::SetNetworkContextGetter({});
}
StreamingReceiverSessionClient::Handler::~Handler() = default;
void StreamingReceiverSessionClient::LaunchStreamingReceiverAsync() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!is_streaming_launch_pending());
streaming_state_ |= LaunchState::kLaunchCalled;
streaming_controller_->StartPlaybackAsync(
base::BindOnce(&StreamingReceiverSessionClient::OnPlaybackStarted,
weak_factory_.GetWeakPtr()));
}
void StreamingReceiverSessionClient::VerifyAVSettingsReceived() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (streaming_state_ & LaunchState::kAVSettingsReceived) {
return;
}
LOG(ERROR) << "AVSettings not received within the allocated amount of time";
TriggerError();
}
void StreamingReceiverSessionClient::OnPlaybackStarted() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
streaming_state_ |= LaunchState::kLaunched;
handler_->OnStreamingSessionStarted();
}
void StreamingReceiverSessionClient::OnStreamingConfigSet(
const cast_streaming::ReceiverConfig& config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Make a copy so that it can be mofidied locally.
cast_streaming::ReceiverConfig constraints = config;
if (streaming_state_ == LaunchState::kError) {
LOG(WARNING) << "Config received after an error!";
return;
}
if (!supports_audio_) {
LOG(WARNING) << "Disallowing audio for this streaming session!";
constraints.audio_codecs.clear();
constraints.audio_limits.clear();
}
if (!supports_video_) {
LOG(WARNING) << "Disallowing video for this streaming session!";
constraints.video_codecs.clear();
constraints.video_limits.clear();
}
if (supports_audio_ && supports_video_) {
DVLOG(1) << "Allowing both audio and video for this streaming session!";
}
streaming_state_ |= LaunchState::kAVSettingsReceived;
if (!has_streaming_launched()) {
streaming_controller_->InitializeReceiverSession(config, this);
return;
}
// TODO(crbug.com/1359568): Handle receiving a new config after streaming has
// already started.
LOG(WARNING)
<< "Received updated streaming config during an ongoing session!";
}
void StreamingReceiverSessionClient::OnAudioConfigUpdated(
const ::media::AudioDecoderConfig& audio_config) {}
void StreamingReceiverSessionClient::OnVideoConfigUpdated(
const ::media::VideoDecoderConfig& video_config) {
handler_->OnResolutionChanged(video_config.visible_rect(),
video_config.video_transformation());
}
void StreamingReceiverSessionClient::OnStreamingSessionEnded() {
// The streaming session will only "end" (as opposed to being "renegotated"
// when a new config is sent or the stream changes between mirroring and
// remoting) when the session completely exits. This occurs either when there
// is an error in the runtime or the when sender-side ends the streaming
// session.
//
// In either case, the result is an unsupported state for the
// StreamingRuntimeApplication, so an error.
TriggerError();
}
void StreamingReceiverSessionClient::TriggerError() {
if (!is_healthy()) {
return;
}
streaming_state_ |= LaunchState::kError;
handler_->OnError();
}
} // namespace cast_receiver
|