aboutsummaryrefslogtreecommitdiff
path: root/cast
diff options
context:
space:
mode:
authorJordan Bayles <jophba@chromium.org>2021-06-10 11:23:55 -0700
committerOpenscreen LUCI CQ <openscreen-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-06-10 19:10:22 +0000
commitf6e2b5ea1dfca4fceb6e1d4004494a88006e1f9f (patch)
tree1bcb7cfe38c6c8ea18f4bb42b6b01ef7fc68b022 /cast
parent1a4e533d57c2b879704759cdffb2a00f71266346 (diff)
downloadopenscreen-f6e2b5ea1dfca4fceb6e1d4004494a88006e1f9f.tar.gz
[Cast Streaming] Improve remoting in ReceiverSession API
This patch continues the process of wrapping up remoting support, by adding some support to the standalone implementations and cleaning up the ReceiverSession API. From here, the actual media stream will have to be mocked out/a standalone implementation created so that we can properly test the entire remoting flow and set the stage for integration into chrome. Bug: b/184186390 Change-Id: Ib2a5526ce5db71cb093f228acbc64cf3060e677d Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2939634 Commit-Queue: Jordan Bayles <jophba@chromium.org> Reviewed-by: Ryan Keane <rwkeane@google.com>
Diffstat (limited to 'cast')
-rw-r--r--cast/standalone_receiver/cast_service.cc41
-rw-r--r--cast/standalone_receiver/cast_service.h26
-rw-r--r--cast/standalone_receiver/main.cc41
-rw-r--r--cast/standalone_receiver/mirroring_application.cc12
-rw-r--r--cast/standalone_receiver/streaming_playback_controller.cc8
-rw-r--r--cast/standalone_receiver/streaming_playback_controller.h5
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.cc26
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.h7
-rw-r--r--cast/standalone_sender/main.cc14
-rw-r--r--cast/streaming/receiver_session.cc72
-rw-r--r--cast/streaming/receiver_session.h45
-rw-r--r--cast/streaming/sender_session.h5
12 files changed, 217 insertions, 85 deletions
diff --git a/cast/standalone_receiver/cast_service.cc b/cast/standalone_receiver/cast_service.cc
index efab229b..28e6c65c 100644
--- a/cast/standalone_receiver/cast_service.cc
+++ b/cast/standalone_receiver/cast_service.cc
@@ -37,28 +37,27 @@ discovery::Config MakeDiscoveryConfig(const InterfaceInfo& interface) {
} // namespace
-CastService::CastService(TaskRunner* task_runner,
- const InterfaceInfo& interface,
- GeneratedCredentials credentials,
- const std::string& friendly_name,
- const std::string& model_name,
- bool enable_discovery)
- : local_endpoint_(DetermineEndpoint(interface)),
- credentials_(std::move(credentials)),
- agent_(task_runner, credentials_.provider.get()),
- mirroring_application_(task_runner, local_endpoint_.address, &agent_),
+CastService::CastService(CastService::Configuration config)
+ : local_endpoint_(DetermineEndpoint(config.interface)),
+ credentials_(std::move(config.credentials)),
+ agent_(config.task_runner, credentials_.provider.get()),
+ mirroring_application_(config.task_runner,
+ local_endpoint_.address,
+ &agent_),
socket_factory_(&agent_, agent_.cast_socket_client()),
connection_factory_(
- TlsConnectionFactory::CreateFactory(&socket_factory_, task_runner)),
- discovery_service_(enable_discovery ? discovery::CreateDnsSdService(
- task_runner,
- this,
- MakeDiscoveryConfig(interface))
- : LazyDeletedDiscoveryService()),
+ TlsConnectionFactory::CreateFactory(&socket_factory_,
+ config.task_runner)),
+ discovery_service_(config.enable_discovery
+ ? discovery::CreateDnsSdService(
+ config.task_runner,
+ this,
+ MakeDiscoveryConfig(config.interface))
+ : LazyDeletedDiscoveryService()),
discovery_publisher_(
discovery_service_
? MakeSerialDelete<discovery::DnsSdServicePublisher<ServiceInfo>>(
- task_runner,
+ config.task_runner,
discovery_service_.get(),
kCastV2ServiceId,
ServiceInfoToDnsSdInstance)
@@ -69,11 +68,11 @@ CastService::CastService(TaskRunner* task_runner,
if (discovery_publisher_) {
ServiceInfo info;
info.port = local_endpoint_.port;
- info.unique_id = HexEncode(interface.hardware_address);
- info.friendly_name = friendly_name;
- info.model_name = model_name;
+ info.unique_id = HexEncode(config.interface.hardware_address);
+ info.friendly_name = config.friendly_name;
+ info.model_name = config.model_name;
info.capabilities = kHasVideoOutput | kHasAudioOutput;
- Error error = discovery_publisher_->Register(info);
+ const Error error = discovery_publisher_->Register(info);
if (!error.ok()) {
OnFatalError(std::move(error));
}
diff --git a/cast/standalone_receiver/cast_service.h b/cast/standalone_receiver/cast_service.h
index 99137de2..c210b433 100644
--- a/cast/standalone_receiver/cast_service.h
+++ b/cast/standalone_receiver/cast_service.h
@@ -41,13 +41,27 @@ namespace cast {
// * Publishes over mDNS to be discoverable to all senders on the same LAN.
class CastService final : public discovery::ReportingClient {
public:
- CastService(TaskRunner* task_runner,
- const InterfaceInfo& interface,
- GeneratedCredentials credentials,
- const std::string& friendly_name,
- const std::string& model_name,
- bool enable_discovery = true);
+ struct Configuration {
+ // The task runner to be used for async calls.
+ TaskRunner* task_runner;
+ // The interface the cast service is running on.
+ InterfaceInfo interface;
+
+ // The credentials that the cast service should use for TLS.
+ GeneratedCredentials credentials;
+
+ // The friendly name to be used for broadcasting.
+ std::string friendly_name;
+
+ // The model name to be used for broadcasting.
+ std::string model_name;
+
+ // Whether we should broadcast over mDNS/DNS-SD.
+ bool enable_discovery = true;
+ };
+
+ explicit CastService(Configuration config);
~CastService() final;
private:
diff --git a/cast/standalone_receiver/main.cc b/cast/standalone_receiver/main.cc
index 8dd0f37a..d66d70e6 100644
--- a/cast/standalone_receiver/main.cc
+++ b/cast/standalone_receiver/main.cc
@@ -67,6 +67,11 @@ options:
-v, --verbose: Enable verbose logging.
-h, --help: Show this help message.
+
+ -x, --disable-discovery: Disable discovery, useful for platforms like Mac OS
+ where our implementation is incompatible with
+ the native Bonjour service.
+
)";
std::cerr << StringPrintf(kTemplate, argv0);
@@ -95,30 +100,22 @@ InterfaceInfo GetInterfaceInfoFromName(const char* name) {
return interface_info;
}
-void RunCastService(TaskRunnerImpl* task_runner,
- const InterfaceInfo& interface,
- GeneratedCredentials creds,
- const std::string& friendly_name,
- const std::string& model_name,
- bool discovery_enabled) {
+void RunCastService(TaskRunnerImpl* runner, CastService::Configuration config) {
std::unique_ptr<CastService> service;
- task_runner->PostTask([&] {
- service = std::make_unique<CastService>(task_runner, interface,
- std::move(creds), friendly_name,
- model_name, discovery_enabled);
- });
+ runner->PostTask(
+ [&] { service = std::make_unique<CastService>(std::move(config)); });
OSP_LOG_INFO << "CastService is running. CTRL-C (SIGINT), or send a "
"SIGTERM to exit.";
- task_runner->RunUntilSignaled();
+ runner->RunUntilSignaled();
// Spin the TaskRunner to execute destruction/shutdown tasks.
OSP_LOG_INFO << "Shutting down...";
- task_runner->PostTask([&] {
+ runner->PostTask([&] {
service.reset();
- task_runner->RequestStopSoon();
+ runner->RequestStopSoon();
});
- task_runner->RunUntilStopped();
+ runner->RunUntilStopped();
OSP_LOG_INFO << "Bye!";
}
@@ -160,7 +157,7 @@ int RunStandaloneReceiver(int argc, char* argv[]) {
{nullptr, 0, nullptr, 0}};
bool is_verbose = false;
- bool discovery_enabled = true;
+ bool enable_discovery = true;
std::string private_key_path;
std::string developer_certificate_path;
std::string friendly_name = "Cast Standalone Receiver";
@@ -168,7 +165,7 @@ int RunStandaloneReceiver(int argc, char* argv[]) {
bool should_generate_credentials = false;
std::unique_ptr<TextTraceLoggingPlatform> trace_logger;
int ch = -1;
- while ((ch = getopt_long(argc, argv, "p:d:f:m:gtvhx", kArgumentOptions,
+ while ((ch = getopt_long(argc, argv, "p:d:f:m:grtvhx", kArgumentOptions,
nullptr)) != -1) {
switch (ch) {
case 'p':
@@ -193,7 +190,7 @@ int RunStandaloneReceiver(int argc, char* argv[]) {
is_verbose = true;
break;
case 'x':
- discovery_enabled = false;
+ enable_discovery = false;
break;
case 'h':
LogUsage(argv[0]);
@@ -234,14 +231,16 @@ int RunStandaloneReceiver(int argc, char* argv[]) {
<< "Hardware address is empty. Either you are on a loopback device "
"or getting the network interface information failed somehow. "
"Discovery publishing will be disabled.";
- discovery_enabled = false;
+ enable_discovery = false;
}
auto* const task_runner = new TaskRunnerImpl(&Clock::now);
PlatformClientPosix::Create(milliseconds(50),
std::unique_ptr<TaskRunnerImpl>(task_runner));
- RunCastService(task_runner, interface, std::move(creds.value()),
- friendly_name, model_name, discovery_enabled);
+ RunCastService(task_runner,
+ CastService::Configuration{
+ task_runner, interface, std::move(creds.value()),
+ friendly_name, model_name, enable_discovery});
PlatformClientPosix::ShutDown();
return 0;
diff --git a/cast/standalone_receiver/mirroring_application.cc b/cast/standalone_receiver/mirroring_application.cc
index b654e010..83921d76 100644
--- a/cast/standalone_receiver/mirroring_application.cc
+++ b/cast/standalone_receiver/mirroring_application.cc
@@ -4,6 +4,8 @@
#include "cast/standalone_receiver/mirroring_application.h"
+#include <utility>
+
#include "cast/common/public/message_port.h"
#include "cast/streaming/constants.h"
#include "cast/streaming/environment.h"
@@ -53,9 +55,13 @@ bool MirroringApplication::Launch(const std::string& app_id,
IPEndpoint{interface_address_, kDefaultCastStreamingPort});
controller_ =
std::make_unique<StreamingPlaybackController>(task_runner_, this);
- current_session_ = std::make_unique<ReceiverSession>(
- controller_.get(), environment_.get(), message_port,
- ReceiverSession::Preferences{});
+
+ ReceiverSession::Preferences preferences;
+ preferences.remoting =
+ std::make_unique<ReceiverSession::RemotingPreferences>();
+ current_session_ =
+ std::make_unique<ReceiverSession>(controller_.get(), environment_.get(),
+ message_port, std::move(preferences));
return true;
}
diff --git a/cast/standalone_receiver/streaming_playback_controller.cc b/cast/standalone_receiver/streaming_playback_controller.cc
index 4c3f627b..918653f5 100644
--- a/cast/standalone_receiver/streaming_playback_controller.cc
+++ b/cast/standalone_receiver/streaming_playback_controller.cc
@@ -83,6 +83,14 @@ void StreamingPlaybackController::OnNegotiated(
#endif // defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
}
+void StreamingPlaybackController::OnRemotingNegotiated(
+ const ReceiverSession* session,
+ ReceiverSession::RemotingNegotiation negotiation) {
+ // TODO(issuetracker.google.com/190078859): need ability to initialize
+ // remoting codecs.
+ OSP_UNIMPLEMENTED();
+}
+
void StreamingPlaybackController::OnReceiversDestroying(
const ReceiverSession* session,
ReceiversDestroyingReason reason) {
diff --git a/cast/standalone_receiver/streaming_playback_controller.h b/cast/standalone_receiver/streaming_playback_controller.h
index d2ab72f2..5a743bf6 100644
--- a/cast/standalone_receiver/streaming_playback_controller.h
+++ b/cast/standalone_receiver/streaming_playback_controller.h
@@ -35,10 +35,11 @@ class StreamingPlaybackController final : public ReceiverSession::Client {
// ReceiverSession::Client overrides.
void OnNegotiated(const ReceiverSession* session,
ReceiverSession::ConfiguredReceivers receivers) override;
-
+ void OnRemotingNegotiated(
+ const ReceiverSession* session,
+ ReceiverSession::RemotingNegotiation negotiation) override;
void OnReceiversDestroying(const ReceiverSession* session,
ReceiversDestroyingReason reason) override;
-
void OnError(const ReceiverSession* session, Error error) override;
private:
diff --git a/cast/standalone_sender/looping_file_cast_agent.cc b/cast/standalone_sender/looping_file_cast_agent.cc
index e26d4f5e..70d489de 100644
--- a/cast/standalone_sender/looping_file_cast_agent.cc
+++ b/cast/standalone_sender/looping_file_cast_agent.cc
@@ -268,8 +268,14 @@ void LoopingFileCastAgent::CreateAndStartSession() {
video_config.resolutions.emplace_back(Resolution{1920, 1080});
OSP_VLOG << "Starting session negotiation.";
- const Error negotiation_error =
- current_session_->Negotiate({audio_config}, {video_config});
+ Error negotiation_error;
+ if (connection_settings_->use_remoting) {
+ negotiation_error =
+ current_session_->NegotiateRemoting(audio_config, video_config);
+ } else {
+ negotiation_error =
+ current_session_->Negotiate({audio_config}, {video_config});
+ }
if (!negotiation_error.ok()) {
OSP_LOG_ERROR << "Failed to negotiate a session: " << negotiation_error;
}
@@ -289,6 +295,22 @@ void LoopingFileCastAgent::OnNegotiated(
std::move(senders), connection_settings_->max_bitrate);
}
+void LoopingFileCastAgent::OnRemotingNegotiated(
+ const SenderSession* session,
+ SenderSession::RemotingNegotiation negotiation) {
+ // TODO(jophba): this needs to be hashed out as part of
+ // figuring out the embedder workflow.
+ if (negotiation.senders.audio_sender == nullptr &&
+ negotiation.senders.video_sender == nullptr) {
+ OSP_LOG_ERROR << "Missing both audio and video, so exiting...";
+ return;
+ }
+
+ file_sender_ = std::make_unique<LoopingFileSender>(
+ environment_.get(), connection_settings_->path_to_file.c_str(), session,
+ std::move(negotiation.senders), connection_settings_->max_bitrate);
+}
+
void LoopingFileCastAgent::OnError(const SenderSession* session, Error error) {
OSP_LOG_ERROR << "SenderSession fatal error: " << error;
Shutdown();
diff --git a/cast/standalone_sender/looping_file_cast_agent.h b/cast/standalone_sender/looping_file_cast_agent.h
index 74ca7f3a..d1d6b6ce 100644
--- a/cast/standalone_sender/looping_file_cast_agent.h
+++ b/cast/standalone_sender/looping_file_cast_agent.h
@@ -95,6 +95,10 @@ class LoopingFileCastAgent final
// Whether we should use the hacky RTP stream IDs for legacy android
// receivers, or if we should use the proper values.
bool use_android_rtp_hack = true;
+
+ // Whether we should use remoting for the video, instead of the default of
+ // mirroring.
+ bool use_remoting = false;
};
// Connect to a Cast Receiver, and start the workflow to establish a
@@ -147,6 +151,9 @@ class LoopingFileCastAgent final
SenderSession::ConfiguredSenders senders,
capture_recommendations::Recommendations
capture_recommendations) override;
+ void OnRemotingNegotiated(
+ const SenderSession* session,
+ SenderSession::RemotingNegotiation negotiation) override;
void OnError(const SenderSession* session, Error error) override;
// Helper for stopping the current session, and/or unwinding a remote
diff --git a/cast/standalone_sender/main.cc b/cast/standalone_sender/main.cc
index c6680cd5..27ff3287 100644
--- a/cast/standalone_sender/main.cc
+++ b/cast/standalone_sender/main.cc
@@ -70,6 +70,8 @@ usage: %s <options> addr[:port] media_file
Use the wrong RTP payload types, for compatibility with older Android
TV receivers. See https://crbug.com/631828.
+ -r, --remoting: Enable remoting content instead of mirroring.
+
-t, --tracing: Enable performance tracing logging.
-v, --verbose: Enable verbose logging.
@@ -111,6 +113,7 @@ int StandaloneSenderMain(int argc, char* argv[]) {
{"developer-certificate", required_argument, nullptr, 'd'},
#endif
{"android-hack", no_argument, nullptr, 'a'},
+ {"remoting", no_argument, nullptr, 'r'},
{"tracing", no_argument, nullptr, 't'},
{"verbose", no_argument, nullptr, 'v'},
{"help", no_argument, nullptr, 'h'},
@@ -120,10 +123,11 @@ int StandaloneSenderMain(int argc, char* argv[]) {
bool is_verbose = false;
std::string developer_certificate_path;
bool use_android_rtp_hack = false;
+ bool use_remoting = false;
int max_bitrate = kDefaultMaxBitrate;
std::unique_ptr<TextTraceLoggingPlatform> trace_logger;
int ch = -1;
- while ((ch = getopt_long(argc, argv, "m:d:atvh", kArgumentOptions,
+ while ((ch = getopt_long(argc, argv, "m:d:artvh", kArgumentOptions,
nullptr)) != -1) {
switch (ch) {
case 'm':
@@ -143,6 +147,9 @@ int StandaloneSenderMain(int argc, char* argv[]) {
case 'a':
use_android_rtp_hack = true;
break;
+ case 'r':
+ use_remoting = true;
+ break;
case 't':
trace_logger = std::make_unique<TextTraceLoggingPlatform>();
break;
@@ -206,8 +213,9 @@ int StandaloneSenderMain(int argc, char* argv[]) {
cast_agent = new LoopingFileCastAgent(
task_runner, [&] { task_runner->RequestStopSoon(); });
cast_agent->Connect({remote_endpoint, path, max_bitrate,
- true /* should_include_video */,
- use_android_rtp_hack});
+ .should_include_video = true,
+ .use_android_rtp_hack = use_android_rtp_hack,
+ .use_remoting = use_remoting});
});
// Run the event loop until SIGINT (e.g., CTRL-C at the console) or
diff --git a/cast/streaming/receiver_session.cc b/cast/streaming/receiver_session.cc
index c2a06d01..9d267ada 100644
--- a/cast/streaming/receiver_session.cc
+++ b/cast/streaming/receiver_session.cc
@@ -74,6 +74,14 @@ MediaCapability ToCapability(VideoCodec codec) {
ReceiverSession::Client::~Client() = default;
+using RemotingPreferences = ReceiverSession::RemotingPreferences;
+
+RemotingPreferences::RemotingPreferences() = default;
+RemotingPreferences::RemotingPreferences(RemotingPreferences&&) noexcept =
+ default;
+RemotingPreferences& RemotingPreferences::operator=(
+ RemotingPreferences&&) noexcept = default;
+
using Preferences = ReceiverSession::Preferences;
Preferences::Preferences() = default;
@@ -172,25 +180,17 @@ void ReceiverSession::OnOffer(SenderMessage message) {
auto properties = std::make_unique<SessionProperties>();
properties->sequence_number = message.sequence_number;
- // TODO(issuetracker.google.com/184186390): ReceiverSession needs to support
- // fielding remoting offers.
const Offer& offer = absl::get<Offer>(message.body);
if (offer.cast_mode == CastMode::kRemoting) {
- SendErrorAnswerReply(message.sequence_number,
- "Remoting support is not complete in libcast");
- return;
- }
-
- if (!offer.audio_streams.empty() && !preferences_.audio_codecs.empty()) {
- properties->selected_audio =
- SelectStream(preferences_.audio_codecs, offer.audio_streams);
- }
-
- if (!offer.video_streams.empty() && !preferences_.video_codecs.empty()) {
- properties->selected_video =
- SelectStream(preferences_.video_codecs, offer.video_streams);
+ if (!preferences_.remoting) {
+ SendErrorAnswerReply(message.sequence_number,
+ "This receiver does not have remoting enabled.");
+ return;
+ }
}
+ properties->mode = offer.cast_mode;
+ SelectStreams(offer, properties.get());
if (!properties->IsValid()) {
SendErrorAnswerReply(message.sequence_number,
"Failed to select any streams from OFFER");
@@ -243,6 +243,31 @@ void ReceiverSession::OnCapabilitiesRequest(SenderMessage message) {
}
}
+void ReceiverSession::SelectStreams(const Offer& offer,
+ SessionProperties* properties) {
+ if (offer.cast_mode == CastMode::kMirroring) {
+ if (!offer.audio_streams.empty() && !preferences_.audio_codecs.empty()) {
+ properties->selected_audio =
+ SelectStream(preferences_.audio_codecs, offer.audio_streams);
+ }
+ if (!offer.video_streams.empty() && !preferences_.video_codecs.empty()) {
+ properties->selected_video =
+ SelectStream(preferences_.video_codecs, offer.video_streams);
+ }
+ } else {
+ OSP_DCHECK(offer.cast_mode == CastMode::kRemoting);
+
+ if (offer.audio_streams.size() == 1) {
+ properties->selected_audio =
+ std::make_unique<AudioStream>(offer.audio_streams[0]);
+ }
+ if (offer.video_streams.size() == 1) {
+ properties->selected_video =
+ std::make_unique<VideoStream>(offer.video_streams[0]);
+ }
+ }
+}
+
void ReceiverSession::InitializeSession(const SessionProperties& properties) {
Answer answer = ConstructAnswer(properties);
if (!answer.IsValid()) {
@@ -255,7 +280,22 @@ void ReceiverSession::InitializeSession(const SessionProperties& properties) {
// Only spawn receivers if we know we have a valid answer message.
ConfiguredReceivers receivers = SpawnReceivers(properties);
- client_->OnNegotiated(this, std::move(receivers));
+ if (properties.mode == CastMode::kMirroring) {
+ client_->OnNegotiated(this, std::move(receivers));
+ } else {
+ // TODO(jophba): cleanup sequence number usage.
+ broker_ = std::make_unique<RpcBroker>([this](std::vector<uint8_t> message) {
+ Error error = this->messenger_.SendMessage(
+ ReceiverMessage{ReceiverMessage::Type::kRpc, -1, true /* valid */,
+ std::move(message)});
+
+ if (!error.ok()) {
+ OSP_LOG_WARN << "Failed to send RPC message: " << error;
+ }
+ });
+ client_->OnRemotingNegotiated(
+ this, RemotingNegotiation{std::move(receivers), broker_.get()});
+ }
const Error result = messenger_.SendMessage(ReceiverMessage{
ReceiverMessage::Type::kAnswer, properties.sequence_number,
true /* valid */, std::move(answer)});
diff --git a/cast/streaming/receiver_session.h b/cast/streaming/receiver_session.h
index 3c341279..0f9f00cf 100644
--- a/cast/streaming/receiver_session.h
+++ b/cast/streaming/receiver_session.h
@@ -16,6 +16,7 @@
#include "cast/streaming/offer_messages.h"
#include "cast/streaming/receiver_packet_router.h"
#include "cast/streaming/resolution.h"
+#include "cast/streaming/rpc_broker.h"
#include "cast/streaming/sender_message.h"
#include "cast/streaming/session_config.h"
#include "cast/streaming/session_messenger.h"
@@ -26,9 +27,9 @@ namespace cast {
class Environment;
class Receiver;
-// This class is responsible for listening for streaming (both mirroring and
-// remoting) requests from Cast Sender devices, then negotiating capture
-// constraints and instantiating audio and video Receiver objects.
+// This class is responsible for listening for streaming requests from Cast
+// Sender devices, then negotiating capture constraints and instantiating audio
+// and video Receiver objects.
// The owner of this session is expected to provide a client for
// updates, an environment for getting UDP socket information (as well as
// other OS dependencies), and a set of preferences to be used for
@@ -62,17 +63,33 @@ class ReceiverSession final : public Environment::SocketSubscriber {
VideoCaptureConfig video_config;
};
+ // This struct contains all of the information necessary to begin remoting
+ // once we get a remoting request from a Sender.
+ struct RemotingNegotiation {
+ ConfiguredReceivers receivers;
+
+ // The RPC broker to be used for subscribing to remoting proto messages.
+ RpcBroker* broker;
+ };
+
// The embedder should provide a client for handling connections.
// When a connection is established, the OnNegotiated callback is called.
class Client {
public:
enum ReceiversDestroyingReason { kEndOfSession, kRenegotiated };
- // Called when a new set of receivers has been negotiated. This may be
- // called multiple times during a session, as renegotiations occur.
+ // Called when a set of streaming receivers has been negotiated. Both this
+ // and |OnRemotingNegotiated| may be called repeatedly as negotiations occur
+ // through the life of a session.
virtual void OnNegotiated(const ReceiverSession* session,
ConfiguredReceivers receivers) = 0;
+ // Called when a set of remoting receivers has been negotiated. This will
+ // only be called if |RemotingPreferences| are provided as part of
+ // constructing the ReceiverSession object.
+ virtual void OnRemotingNegotiated(const ReceiverSession* session,
+ RemotingNegotiation negotiation) {}
+
// Called immediately preceding the destruction of this session's receivers.
// If |reason| is |kEndOfSession|, OnNegotiated() will never be called
// again; if it is |kRenegotiated|, OnNegotiated() will be called again
@@ -92,7 +109,7 @@ class ReceiverSession final : public Environment::SocketSubscriber {
// Information about the display the receiver is attached to.
struct Display {
// The display limitations of the actual screen, used to provide upper
- // bounds on mirroring and remoting streams. For example, we will never
+ // bounds on streams. For example, we will never
// send 60FPS if it is going to be displayed on a 30FPS screen.
// Note that we may exceed the display width and height for standard
// content sizes like 720p or 1080p.
@@ -166,6 +183,12 @@ class ReceiverSession final : public Environment::SocketSubscriber {
// TODO(issuetracker.google.com/184429130): the mirroring control
// protocol needs to be updated to allow more discrete support.
struct RemotingPreferences {
+ RemotingPreferences();
+ RemotingPreferences(RemotingPreferences&&) noexcept;
+ RemotingPreferences(const RemotingPreferences&) = delete;
+ RemotingPreferences& operator=(RemotingPreferences&&) noexcept;
+ RemotingPreferences& operator=(const RemotingPreferences&) = delete;
+
// Current remoting senders take an "all or nothing" support for audio
// codec support. While Opus and AAC support is handled in our Preferences'
// |audio_codecs| property, support for the following codecs must be
@@ -219,7 +242,7 @@ class ReceiverSession final : public Environment::SocketSubscriber {
// Libcast remoting support is opt-in: embedders wishing to field remoting
// offers may provide a set of remoting preferences, or leave nullptr for
- // all remoting OFFERs to be rejected in favor of continuing mirroring.
+ // all remoting OFFERs to be rejected in favor of continuing streaming.
std::unique_ptr<RemotingPreferences> remoting;
};
@@ -263,6 +286,10 @@ class ReceiverSession final : public Environment::SocketSubscriber {
void OnOffer(SenderMessage message);
void OnCapabilitiesRequest(SenderMessage message);
+ // Selects streams from an offer based on its configuration, and sets
+ // them in the session properties.
+ void SelectStreams(const Offer& offer, SessionProperties* properties);
+
// Creates receivers and sends an appropriate Answer message using the
// session properties.
void InitializeSession(const SessionProperties& properties);
@@ -307,6 +334,10 @@ class ReceiverSession final : public Environment::SocketSubscriber {
// through |Client::OnReceiversDestroying|.
std::unique_ptr<Receiver> current_audio_receiver_;
std::unique_ptr<Receiver> current_video_receiver_;
+
+ // If remoting, we store the RpcBroker used by the embedder to send RPC
+ // messages from the remoting protobuf specification.
+ std::unique_ptr<RpcBroker> broker_;
};
} // namespace cast
diff --git a/cast/streaming/sender_session.h b/cast/streaming/sender_session.h
index 7702b490..d95c61aa 100644
--- a/cast/streaming/sender_session.h
+++ b/cast/streaming/sender_session.h
@@ -50,8 +50,6 @@ class SenderSession final {
// This struct contains all of the information necessary to begin remoting
// after we receive the capabilities from the receiver.
- // TODO(issuetracker.google.com/184189241): capture recommendations should be
- // exposed as part of the remoting negotiation.
struct RemotingNegotiation {
ConfiguredSenders senders;
@@ -258,8 +256,7 @@ class SenderSession final {
std::unique_ptr<Sender> current_video_sender_;
// If remoting, we store the RpcBroker used by the embedder to send RPC
- // messages from the remoting protobuf specification. For more information,
- // see //cast/streaming/remoting.proto.
+ // messages from the remoting protobuf specification.
std::unique_ptr<RpcBroker> broker_;
}; // namespace cast